ai_images/portal-ui/src/layout/components/Menu.vue

208 lines
5.1 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>
<div class="menu-wrapper">
<a-scrollbar>
<a-menu
:collapsed="collapsed"
:selected-keys="selectedKeys"
:open-keys="openedKeys"
@menu-item-click="menuItemClick"
@sub-menu-click="subMenuClick">
<template v-for="item in menuItems">
<template v-if="item.children.length > 0">
<a-sub-menu
:key="item.key"
:title="item.label">
<a-menu-item
v-for="child in item.children"
:key="child.key">
{{ child.label }}
</a-menu-item>
</a-sub-menu>
</template>
<template v-else>
<a-menu-item :key="item.key">
<template #icon>
<span
class="menu-svg-icon"
:class="{ active: selectedKeys.indexOf(item.key) > -1 }"
v-html="getMenuSvg(item.key)"
></span>
</template>
<div class="menu-item">
{{ item.label }}
</div>
</a-menu-item>
</template>
</template>
</a-menu>
</a-scrollbar>
</div>
</template>
<script setup>
import { computed, ref, watch, inject } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useStore } from 'vuex'
import cloneDeep from 'lodash-es/cloneDeep'
import { constantRoutes } from '@/router/index'
import { generateTitle, generateLang } from '@/utils/i18n'
/** 左侧导航仅显示这些路由name 与 router/index.js 一致) */
const SIDEBAR_ONLY_ROUTE_NAMES = ['video-gen', 'asset-group-manage', 'asset-manage', 'generatedAssets']
defineProps({
collapsed: Boolean
})
const store = useStore()
const route = useRoute()
const router = useRouter()
const $base = inject('$base')
const $message = inject('$message')
const menuItems = computed(() => {
const root = constantRoutes.find((d) => d.path === '/')
const children = root?.children ?? []
return children
.filter(
(r) =>
r.meta?.menuItem !== false && SIDEBAR_ONLY_ROUTE_NAMES.includes(r.name)
)
.map((route) => ({
key: route.name,
label: generateTitle(route.meta?.title),
meta: route.meta,
icon: route.meta?.icon,
children: (route.children || []).map((i) => ({
key: i.name,
label: generateTitle(i.meta?.title),
meta: i.meta,
icon: i.meta?.icon
}))
}))
})
const menuSelectedKeys = computed(() => store.getters.selectedKeys)
const defaultOpenedKeys = computed(() => {
let system = store.getters.system
if (system == 'service') {
return ['service-order', 'service-permission']
} else if (system == 'agency') {
return ['agency-order', 'agency-permission']
} else {
return []
}
})
const selectedKeys = ref([])
const openedKeys = computed(() => {
return store.getters.openedKeys
})
const menuItemClick = (key) => {
if (key == 'change-face-video') {
$message.warning(generateLang('isDevelop'))
}else {
router.push({ name: key })
if ($base.isMobile()) {
store.dispatch('main/closeSideBar')
}
}
}
const subMenuClick = (key, _openKeys) => {
store.dispatch('main/setOpenedKeys', _openKeys)
}
watch(
() => route.name,
() => {
let sk = route.matched.filter((i) => i.meta.menuItem).map((j) => j.name)
selectedKeys.value = sk
let matchKeys = route.matched
.filter((i) => i.meta.menuItem && i.children?.length > 0)
.map((j) => j.name)
let cloneOpenedKeys = cloneDeep(openedKeys.value)
matchKeys.concat(defaultOpenedKeys.value).map((item) => {
if (!cloneOpenedKeys.includes(item)) {
cloneOpenedKeys.push(item)
}
})
store.dispatch('main/setOpenedKeys', cloneOpenedKeys)
},
{
immediate: true
}
)
const servicePolicyCount = computed(() => store.getters.servicePolicyCount)
const agencyPolicyCount = computed(() => store.getters.agencyPolicyCount)
const count = (system) => {
return system === 'service'
? servicePolicyCount.value
: agencyPolicyCount.value
}
const getMenuSvg = (key) => {
if (key === 'video-gen') {
return '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 3a9 9 0 1 0 0 18a9 9 0 0 0 0-18Zm-1.5 5.2a.9.9 0 0 1 1.35-.78l4.7 2.7a.9.9 0 0 1 0 1.56l-4.7 2.7a.9.9 0 0 1-1.35-.78V8.2Z"/></svg>'
}
if (key === 'third-party-asset') {
return '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6h7l2 2h7v12H4V6Zm2 4v8h12v-8H6Zm2 2h8v4H8v-4Z"/></svg>'
}
if (key === 'generated-assets') {
return '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2l-5.5 9h11L12 2zm0 3.5L14.5 9h-5L12 5.5zM4 13v8h16v-8H4zm2 2h12v4H6v-4z"/><path d="M7 15h10v2H7z"/></svg>'
}
return '<svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/></svg>'
}
</script>
<style lang="less">
.arco-tooltip-content {
display: none;
}
</style>
<style lang="less" scoped>
.menu-wrapper {
height: 100%;
.arco-scrollbar {
height: 100%;
:deep(.arco-scrollbar-container) {
height: 100%;
overflow-x: hidden;
overflow-y: auto;
}
}
}
.menu-item {
display: flex;
justify-content: space-between;
align-items: center;
}
.menu-svg-icon {
width: 22px;
height: 22px;
display: inline-flex;
align-items: center;
justify-content: center;
color: rgba(255, 255, 255, 0.74);
transition: color 0.2s ease;
}
.menu-svg-icon:deep(svg) {
width: 22px;
height: 22px;
display: block;
fill: currentColor;
}
.menu-svg-icon.active {
color: #ffffff;
}
</style>