diff --git a/app/user_data/2026_03_27.log b/app/user_data/2026_03_27.log index 7ea250d..357883d 100644 --- a/app/user_data/2026_03_27.log +++ b/app/user_data/2026_03_27.log @@ -719,3 +719,15 @@ Traceback (most recent call last): value = func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ TypeError: WindowAPI.__init__..() missing 1 required positional argument: '_' +[pywebview] WindowAPI.__init__..() missing 1 required positional argument: '_' +Traceback (most recent call last): + File "C:\Users\\AppData\Local\Programs\Python\Python312\Lib\site-packages\webview\event.py", line 45, in execute + value = func(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^ +TypeError: WindowAPI.__init__..() missing 1 required positional argument: '_' +[pywebview] WindowAPI.__init__..() missing 1 required positional argument: '_' +Traceback (most recent call last): + File "C:\Users\\AppData\Local\Programs\Python\Python312\Lib\site-packages\webview\event.py", line 45, in execute + value = func(*args, **kwargs) + ^^^^^^^^^^^^^^^^^^^^^ +TypeError: WindowAPI.__init__..() missing 1 required positional argument: '_' diff --git a/app/web_source/brand.html b/app/web_source/brand.html index 430936b..92372a0 100644 --- a/app/web_source/brand.html +++ b/app/web_source/brand.html @@ -56,47 +56,96 @@ background: #2a2a2a; } - /* 顶部栏目导航(容器化,便于后续增加栏目) */ .nav-tabs { display: flex; align-items: center; - gap: 0; + gap: 12px; } .nav-tab-group { display: flex; align-items: center; - gap: 6px; - background: rgba(77, 72, 72, 0.99); + gap: 12px; + } + + .nav-dropdown { + position: relative; + } + + .nav-dropdown-trigger { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + min-width: 112px; + height: 38px; + padding: 0 16px; border-radius: 10px; - } - - .nav-tab-sep { - width: 1px; - height: 20px; - background: linear-gradient(to bottom, transparent, #444 15%, #444 85%, transparent); - margin: 0 10px; - flex-shrink: 0; - opacity: 0.9; - } - - .nav-tab { - padding: 8px 14px; - font-size: 13px; + border: 1px solid transparent; color: #999; background: transparent; - border: none; - border-radius: 6px; + font-size: 13px; + font-weight: 600; cursor: pointer; - transition: all 0.2s; + transition: all 0.2s ease; } - .nav-tab:hover { + .nav-dropdown:hover .nav-dropdown-trigger, + .nav-dropdown.active .nav-dropdown-trigger { color: #fff; background: #2a2a2a; } - .nav-tab.active { + .nav-dropdown.active .nav-dropdown-trigger { + color: #3498db; + background: rgba(52, 152, 219, 0.2); + border-color: rgba(52, 152, 219, 0.3); + } + + .nav-dropdown-arrow { + font-size: 11px; + line-height: 1; + } + + .nav-dropdown-menu { + position: absolute; + top: calc(100% + 8px); + left: 0; + min-width: 220px; + padding: 8px; + border: 1px solid #2a2a2a; + border-radius: 12px; + background: #171717; + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35); + display: none; + z-index: 20; + } + + .nav-dropdown:hover .nav-dropdown-menu { + display: flex; + flex-direction: column; + gap: 4px; + } + + .nav-dropdown-item { + display: flex; + align-items: center; + min-height: 38px; + padding: 0 12px; + border-radius: 8px; + color: #b8b8b8; + font-size: 13px; + font-weight: 600; + text-decoration: none; + transition: all 0.2s ease; + } + + .nav-dropdown-item:hover { + color: #fff; + background: #2a2a2a; + } + + .nav-dropdown-item.active { color: #3498db; background: rgba(52, 152, 219, 0.2); } @@ -597,16 +646,29 @@ 返回首页
@@ -739,12 +801,12 @@ var cachedTasks = []; var api = window.pywebview && window.pywebview.api; - // 顶部栏目切换:点击 nav-tab 时显示对应 data-panel 的 tab-panel - document.querySelectorAll('.nav-tab').forEach(function (tab) { + // 顶部栏目切换:点击当前页菜单项时显示对应 data-panel 的 tab-panel + document.querySelectorAll('.nav-dropdown-item[data-panel]').forEach(function (tab) { tab.addEventListener('click', function () { var panelId = this.getAttribute('data-panel'); if (!panelId) return; - document.querySelectorAll('.nav-tab').forEach(function (t) { t.classList.remove('active'); }); + document.querySelectorAll('.nav-dropdown-item[data-panel]').forEach(function (t) { t.classList.remove('active'); }); document.querySelectorAll('.tab-panel').forEach(function (p) { p.classList.toggle('active', p.getAttribute('data-panel') === panelId); }); diff --git a/frontend-vue/src/pages/brand/components/BrandTopBar.vue b/frontend-vue/src/pages/brand/components/BrandTopBar.vue index ccfda6b..5e0b4ae 100644 --- a/frontend-vue/src/pages/brand/components/BrandTopBar.vue +++ b/frontend-vue/src/pages/brand/components/BrandTopBar.vue @@ -6,12 +6,30 @@
@@ -25,12 +43,22 @@ const props = defineProps<{ const active = props.active -const navItems = [ - { key: 'brand', label: '品牌检测', href: '/brand' }, - { key: 'dedupe', label: '数据去重', href: '/new_web_source/dedupe.html' }, - { key: 'split', label: '数据拆分', href: '/new_web_source/split.html' }, - { key: 'convert', label: '格式转换', href: '/new_web_source/convert.html' }, - { key: 'delete-brand', label: '删除品牌', href: '/new_web_source/delete-brand.html' }, +const navGroups = [ + { + label: '前端工具', + items: [ + { key: 'brand', label: '品牌检测', href: '/brand' }, + { key: 'dedupe', label: '数据去重', href: '/new_web_source/dedupe.html' }, + { key: 'split', label: '数据拆分', href: '/new_web_source/split.html' }, + { key: 'convert', label: '格式转换', href: '/new_web_source/convert.html' }, + ], + }, + { + label: '运营工具', + items: [ + { key: 'delete-brand', label: '删除指定ASIN和品牌', href: '/new_web_source/delete-brand.html' }, + ], + }, ] as const @@ -86,11 +114,16 @@ const navItems = [ justify-content: center; } -.nav-tab { +.nav-dropdown { + position: relative; +} + +.nav-dropdown-trigger { display: inline-flex; align-items: center; justify-content: center; - min-width: 92px; + gap: 8px; + min-width: 112px; height: 38px; padding: 0 16px; border-radius: 10px; @@ -99,21 +132,70 @@ const navItems = [ background: transparent; font-size: 13px; font-weight: 600; - text-decoration: none; + cursor: pointer; transition: all 0.2s ease; } -.nav-tab:hover { +.nav-dropdown:hover .nav-dropdown-trigger, +.nav-dropdown.active .nav-dropdown-trigger { color: #b9d6ff; background: rgba(77, 126, 189, 0.14); } -.nav-tab.active { +.nav-dropdown.active .nav-dropdown-trigger { background: rgba(77, 126, 189, 0.24); border-color: rgba(91, 148, 219, 0.35); color: #6caeff; } +.nav-dropdown-arrow { + font-size: 11px; + line-height: 1; +} + +.nav-dropdown-menu { + position: absolute; + top: calc(100% + 8px); + left: 0; + min-width: 220px; + padding: 8px; + border: 1px solid #2a2a2a; + border-radius: 12px; + background: #171717; + box-shadow: 0 12px 30px rgba(0, 0, 0, 0.35); + display: none; + z-index: 20; +} + +.nav-dropdown:hover .nav-dropdown-menu { + display: flex; + flex-direction: column; + gap: 4px; +} + +.nav-dropdown-item { + display: flex; + align-items: center; + min-height: 38px; + padding: 0 12px; + border-radius: 8px; + color: #b8b8b8; + font-size: 13px; + font-weight: 600; + text-decoration: none; + transition: all 0.2s ease; +} + +.nav-dropdown-item:hover { + color: #e8f2ff; + background: rgba(77, 126, 189, 0.14); +} + +.nav-dropdown-item.active { + color: #6caeff; + background: rgba(77, 126, 189, 0.24); +} + .top-right { width: 120px; flex-shrink: 0; @@ -132,6 +214,16 @@ const navItems = [ justify-content: flex-start; } + .nav-tab-group { + width: 100%; + justify-content: flex-start; + } + + .nav-dropdown-menu { + left: 0; + right: auto; + } + .top-right { display: none; }