diff --git a/docker-compose.yml b/docker-compose.yml index 336e54b..70d328f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,7 +5,7 @@ services: build: context: . dockerfile: Dockerfile - image: tradus-web:1.0.13 + image: tradus-web:1.0.14 container_name: tradus-web ports: - '6000:80' diff --git a/src/App.vue b/src/App.vue index d35a461..c4f8796 100644 --- a/src/App.vue +++ b/src/App.vue @@ -7,6 +7,7 @@ const userStore = useUserStore() const isAuthenticated = computed(() => userStore.isAuthenticated) const userInfo = computed(() => userStore.userInfo) const showMobileMenu = ref(false) +const showUserMenu = ref(false) const handleLogout = () => { userStore.logout() @@ -14,18 +15,27 @@ const handleLogout = () => { window.location.href = '/' } showMobileMenu.value = false + showUserMenu.value = false } const toggleMobileMenu = () => { showMobileMenu.value = !showMobileMenu.value } +const toggleUserMenu = (event: Event) => { + event.stopPropagation() + showUserMenu.value = !showUserMenu.value +} + // 点击其他地方关闭菜单 const closeMenus = (event: MouseEvent) => { const target = event.target as HTMLElement if (!target.closest('.mobile-menu') && !target.closest('.menu-button')) { showMobileMenu.value = false } + if (!target.closest('.user-info-box') && !target.closest('.user-menu')) { + showUserMenu.value = false + } } onMounted(() => { @@ -99,13 +109,42 @@ onUnmounted(() => {
@@ -684,7 +667,7 @@ onUnmounted(() => { } .input-container { - padding: 1.5rem 2rem; + padding: 0.5rem 0.5rem 5.5rem 0.5rem; background-color: var(--color-bg-primary); width: 100%; max-width: 900px; @@ -732,7 +715,7 @@ onUnmounted(() => { .send-button { position: absolute; right: 0.75rem; - bottom: 0.75rem; + bottom: 0.5rem; width: 2rem; height: 2rem; display: flex; @@ -819,217 +802,92 @@ onUnmounted(() => { text-decoration: underline; } -/* 添加新的 Agent 选择器样式 */ +/* 修改 Agent 选择器样式 */ .agent-selector { - position: absolute; - top: 1rem; - right: 1rem; - z-index: 10; + /* padding: 1rem 2rem; */ + background-color: #ffffff; + max-width: 900px; + margin: 0 auto; + width: 100%; } -.agent-selector-button { +.agent-list { display: flex; + flex-direction: row; + gap: 0.75rem; + padding: 0.75rem; + overflow-x: auto; + scrollbar-width: none; /* Firefox */ + -ms-overflow-style: none; /* IE and Edge */ +} + +.agent-list::-webkit-scrollbar { + display: none; /* Chrome, Safari and Opera */ +} + +.agent-item { + display: inline-flex; align-items: center; gap: 0.75rem; - padding: 0.75rem 1.25rem; - background-color: #ffffff; - border: 1px solid rgba(51, 85, 255, 0.2); - border-radius: 12px; + padding: 0.75rem 1rem; + background-color: var(--color-bg-secondary); + border: 1px solid rgba(51, 85, 255, 0.15); + border-radius: 8px; color: var(--color-text-primary); cursor: pointer; transition: all 0.2s ease; + white-space: nowrap; + font-size: 0.95rem; font-weight: 500; - box-shadow: 0 2px 8px rgba(51, 85, 255, 0.08); - min-width: 160px; + min-width: 120px; + width: fit-content; + justify-content: flex-start; + flex-shrink: 0; } -.agent-selector-button:hover { +.agent-item:hover { border-color: var(--color-accent); background-color: rgba(51, 85, 255, 0.04); - transform: translateY(-1px); - box-shadow: 0 4px 12px rgba(51, 85, 255, 0.12); } -.agent-selector-button .agent-icon { - font-size: 1.25rem; - color: var(--color-accent); +.agent-item.active { + background-color: var(--color-accent); + border-color: var(--color-accent); + color: #ffffff; } -.agent-selector-button .agent-name { - font-size: 0.95rem; - color: var(--color-text-primary); - flex: 1; +.agent-icon { + width: 20px; + height: 20px; + flex-shrink: 0; + stroke: currentColor; } -.agent-selector-button::after { - content: '▼'; - font-size: 0.8rem; - color: var(--color-accent); - opacity: 0.8; - transition: transform 0.2s ease; +.agent-item.active .agent-icon { + stroke: #ffffff; } -.agent-selector-menu { - position: absolute; - top: calc(100% + 0.5rem); - right: 0; - background-color: #ffffff; - border: 1px solid rgba(51, 85, 255, 0.15); - border-radius: 12px; - min-width: 280px; - max-width: 320px; - overflow: hidden; - box-shadow: 0 4px 20px rgba(51, 85, 255, 0.15); - animation: slideDown 0.2s ease; -} - -@keyframes slideDown { - from { - opacity: 0; - transform: translateY(-10px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -.agent-menu-item { - display: flex; - align-items: center; - gap: 0.75rem; - padding: 1rem; - cursor: pointer; - transition: all 0.2s ease; - border-bottom: 1px solid rgba(51, 85, 255, 0.08); - background-color: #ffffff; -} - -.agent-menu-item:last-child { - border-bottom: none; -} - -.agent-menu-item:hover { - background-color: rgba(51, 85, 255, 0.04); -} - -.agent-menu-item.active { - background-color: rgba(51, 85, 255, 0.08); -} - -.agent-menu-item .agent-icon { - font-size: 1.5rem; - color: var(--color-accent); - width: 32px; - height: 32px; - display: flex; - align-items: center; - justify-content: center; - background-color: rgba(51, 85, 255, 0.08); - border-radius: 8px; -} - -.agent-menu-item .agent-info { - flex: 1; - min-width: 0; -} - -.agent-menu-item .agent-name { - font-weight: 600; - color: var(--color-text-primary); - margin-bottom: 0.25rem; - font-size: 0.95rem; -} - -.agent-menu-item .agent-description { - font-size: 0.85rem; - color: var(--color-text-secondary); - line-height: 1.4; +.agent-name { + text-align: left; } .agent-loading { - padding: 1rem; + padding: 0.75rem; text-align: center; color: var(--color-text-secondary); } /* 移动端适配 */ @media (max-width: 768px) { - .ai-agent-view { - height: 100%; + .agent-list { + padding: 0.5rem; + gap: 0.5rem; } - .main-container { - height: 100%; - padding-bottom: env(safe-area-inset-bottom); - } - - .messages-container { - padding: 1rem 0.5rem; - padding-bottom: calc(5rem + env(safe-area-inset-bottom)); - } - - .input-container { - position: fixed; - bottom: 0; - left: 0; - right: 0; - padding: 0.75rem; - padding-bottom: calc(0.75rem + env(safe-area-inset-bottom)); - background-color: var(--color-bg-elevated); - box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); - z-index: 100; - border-top: 1px solid var(--color-border); - } - - .input-wrapper { - max-width: 900px; - margin: 0 auto; - } - - .message-input { - font-size: 16px; /* 防止 iOS 自动缩放 */ - padding: 0.6rem 2.5rem 0.6rem 0.75rem; - min-height: 2.5rem; - height: 2.5rem; - } - - .send-button { - width: 1.8rem; - height: 1.8rem; - right: 0.5rem; - bottom: 0.35rem; - } - - .send-icon { - font-size: 0.9rem; - } - - .agent-selector { - top: 0.75rem; - right: 0.75rem; - } - - .agent-selector-button { + .agent-item { padding: 0.6rem 1rem; - min-width: 140px; font-size: 0.9rem; - } - - .agent-selector-menu { - min-width: 260px; - max-width: calc(100vw - 2rem); - right: -0.75rem; - } - - .agent-menu-item { - padding: 0.875rem; - } - - .agent-menu-item .agent-icon { - font-size: 1.25rem; - width: 28px; - height: 28px; + min-width: 100px; } } diff --git a/src/views/HomeView.vue b/src/views/HomeView.vue index df4b2ee..db70b02 100644 --- a/src/views/HomeView.vue +++ b/src/views/HomeView.vue @@ -11,8 +11,8 @@ const isAuthenticated = computed(() => userStore.isAuthenticated)AI Agent for trading
+A intelligent trading assistant