Files
crawler-plugin/frontend-vue/src/pages/amazon/components/AmazonTopBar.vue
T

276 lines
6.4 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<header class="amazon-top">
<router-link class="home-back" :to="homeHref" title="返回首页"> 返回首页</router-link>
<router-link class="brand" :to="toolbarHref" title="返回工具台首页">
<span class="brand-logo"></span>
<span class="brand-text">
<span class="brand-name">数富AI</span>
<span class="brand-sub">亚马逊运营工具台</span>
</span>
</router-link>
<nav class="cat-tabs" aria-label="分类导航">
<template v-for="cat in visibleCats" :key="cat.key">
<router-link
class="cat-tab"
:class="{ 'cat-tab--active': cat.key === activeCat }"
:to="`${toolbarHref}#group-${cat.key}`"
@click="onTabClick(cat.key)"
>
<span class="cat-tab-content">
<span class="cat-dot" :style="{ background: cat.color }"></span>
<span class="cat-name">{{ cat.name }}</span>
<span class="cat-badge" :style="badgeStyle(cat)">{{ cat.tools.length }}</span>
</span>
<span class="cat-underline" :style="underlineStyle(cat)"></span>
</router-link>
</template>
</nav>
<div class="top-right">
<BrandApiSecretSettingsButton variant="topbar" />
<span class="admin-name">{{ username }}</span>
</div>
</header>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import BrandApiSecretSettingsButton from '@/pages/brand/components/BrandApiSecretSettingsButton.vue'
import { filterGroupsByPermission, TOOL_GROUPS } from '@/pages/amazon/tool-catalog'
import type { VisibleGroup } from '@/pages/amazon/tool-catalog'
import { resolvePageHref } from '@/shared/page-prefix'
import { getCurrentUserAppColumnKeys } from '@/shared/api/permission'
const props = withDefaults(
defineProps<{
/** 当前工具所属分类(功能页高亮对应 tab;工具台首页不传) */
activeCat?: 'front' | 'ops' | 'logi'
}>(),
{
activeCat: undefined,
},
)
const emit = defineEmits<{ change: [key: 'front' | 'ops' | 'logi'] }>()
const activeCat = computed(() => props.activeCat)
const visibleCats = ref<VisibleGroup[]>(TOOL_GROUPS.map((group) => ({ ...group, tools: [...group.tools] })))
const username = ref('admin')
/** 分类 tab 点击回到工具台对应分组 */
const toolbarHref = resolvePageHref('/new_web_source/amazon-console.html')
/** 返回桌面入口首页(亚马逊/视频/图片入口) */
const homeHref = resolvePageHref('/new_web_source/home.html')
function onTabClick(key: 'front' | 'ops' | 'logi') {
emit('change', key)
}
/** 激活分类角标:分类色实底白字(对齐 gemini-code tab-badge 激活态) */
function badgeStyle(cat: VisibleGroup) {
return activeCat.value === cat.key ? { background: cat.color, color: '#FFFFFF' } : {}
}
/** 激活分类下划线(对齐 gemini-code tab-underline:底部 3px 分类色圆角条) */
function underlineStyle(cat: VisibleGroup) {
return activeCat.value === cat.key ? { background: cat.color } : {}
}
onMounted(async () => {
const localName = typeof window === 'undefined' ? '' : (window.localStorage.getItem('username') || '').trim()
if (localName) username.value = localName
try {
const keys = await getCurrentUserAppColumnKeys()
visibleCats.value = filterGroupsByPermission(TOOL_GROUPS, keys)
} catch (_error) {
// 权限接口异常时展示全部分类,避免顶栏空白
visibleCats.value = TOOL_GROUPS.map((group) => ({ ...group, tools: [...group.tools] }))
}
})
</script>
<style scoped>
.amazon-top {
flex: 0 0 auto;
min-height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
padding: 0 28px;
background: #1a1f2e;
border-bottom: 1px solid #3e4a62;
font-family: "PingFang SC", "Microsoft YaHei UI", "Microsoft YaHei", "微软雅黑", sans-serif;
}
.brand {
display: flex;
align-items: center;
gap: 12px;
flex-shrink: 0;
text-decoration: none;
}
/* 返回首页按钮(顶栏最左,入口页见 DesktopHomePage */
.home-back {
flex-shrink: 0;
display: inline-flex;
align-items: center;
gap: 6px;
padding: 6px 14px;
border: 1px solid #3e4a62;
border-radius: 6px;
color: #c8d2e2;
font-size: 13px;
text-decoration: none;
white-space: nowrap;
transition: all 0.2s;
}
.home-back:hover {
background: #2b3447;
color: #f5f8fc;
}
.brand-logo {
display: flex;
align-items: center;
justify-content: center;
width: 38px;
height: 38px;
border-radius: 8px;
background: #f59e0b;
color: #fff;
font-size: 20px;
font-weight: 700;
box-shadow: 0 2px 8px rgba(245, 158, 11, 0.3);
}
.brand-text {
display: flex;
flex-direction: column;
line-height: 1.35;
}
.brand-name {
color: #f5f8fc;
font-size: 17px;
font-weight: 700;
white-space: nowrap;
}
.brand-sub {
color: #a0acbe;
font-size: 10px;
white-space: nowrap;
}
.cat-tabs {
flex: 1;
min-width: 0;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
}
.cat-tab {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
width: 150px;
height: 44px;
background: transparent;
color: #c8d2e2;
font-size: 15px;
font-weight: 700;
text-decoration: none;
transition: all 0.2s;
}
.cat-tab-content {
display: flex;
align-items: center;
gap: 8px;
padding: 7px 14px;
border-radius: 8px;
transition: background 0.2s;
}
.cat-tab:hover .cat-tab-content {
background: #3d4a63;
color: #f5f8fc;
}
.cat-tab--active {
color: #f5f8fc;
}
.cat-tab--active .cat-tab-content {
background: #3d4a63;
}
.cat-dot {
width: 9px;
height: 9px;
border-radius: 50%;
flex-shrink: 0;
}
.cat-badge {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 1px 8px;
border-radius: 12px;
background: #343f55;
color: #a0acbe;
font-size: 11px;
font-weight: 700;
}
.cat-underline {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 3px;
border-radius: 3px 3px 0 0;
background: transparent;
transition: background 0.2s;
}
.top-right {
display: flex;
align-items: center;
gap: 14px;
flex-shrink: 0;
}
.admin-name {
color: #c8d2e2;
font-size: 13px;
font-weight: 700;
white-space: nowrap;
}
@media (max-width: 1100px) {
.amazon-top {
flex-wrap: wrap;
height: auto;
padding: 10px 16px;
}
.cat-tabs {
order: 3;
width: 100%;
justify-content: flex-start;
overflow-x: auto;
}
}
</style>