2
0
mirror of https://github.com/acepanel/panel.git synced 2026-02-04 09:13:49 +08:00

feat: 支持隐藏菜单和自定义Logo长期保存 (#1200)

* Initial plan

* feat: 支持隐藏菜单和自定义Logo长期保存

- 后端:在 SettingPanel 结构体中添加 HiddenMenu 和 CustomLogo 字段
- 后端:在 GetPanel 和 UpdatePanel 方法中处理新字段的获取和保存
- 后端:修改 Panel 接口返回 hidden_menu 和 custom_logo 给前端初始化
- 前端:在基本设置页面添加隐藏菜单和自定义 Logo 设置项
- 前端:从侧边栏设置组件中移除弹窗,只保留菜单折叠按钮
- 前端:初始化时从服务端获取并应用隐藏菜单和自定义 Logo 设置
- 前端:调整 store 的 persist 配置,不再将这两个设置保存到本地存储

Co-authored-by: devhaozi <115467771+devhaozi@users.noreply.github.com>

* 代码审查完成

Co-authored-by: devhaozi <115467771+devhaozi@users.noreply.github.com>

* feat: 优化样式

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devhaozi <115467771+devhaozi@users.noreply.github.com>
Co-authored-by: 耗子 <haozi@loli.email>
This commit is contained in:
Copilot
2026-01-09 05:49:09 +08:00
committed by GitHub
parent 9baeaa47e0
commit f2d3911266
10 changed files with 110 additions and 119 deletions

View File

@@ -1,8 +1,14 @@
<script setup lang="ts">
import type { TreeSelectOption } from 'naive-ui'
import { translateTitle } from '@/locales/menu'
import { usePermissionStore } from '@/store'
import { locales as availableLocales } from '@/utils'
import { useGettext } from 'vue3-gettext'
import type { RouteType } from '~/types/router'
const { $gettext } = useGettext()
const permissionStore = usePermissionStore()
const model = defineModel<any>('model', { type: Object, required: true })
@@ -25,6 +31,43 @@ const channels = [
value: 'beta'
}
]
// 获取菜单选项
const getOption = (route: RouteType): TreeSelectOption => {
let menuItem: TreeSelectOption = {
label: route.meta?.title ? translateTitle(route.meta.title) : route.name,
key: route.name
}
const visibleChildren = route.children
? route.children.filter((item: RouteType) => item.name && !item.isHidden)
: []
if (!visibleChildren.length) return menuItem
if (visibleChildren.length === 1) {
// 单个子路由处理
const singleRoute = visibleChildren[0]
menuItem.label = singleRoute.meta?.title
? translateTitle(singleRoute.meta.title)
: singleRoute.name
const visibleItems = singleRoute.children
? singleRoute.children.filter((item: RouteType) => item.name && !item.isHidden)
: []
if (visibleItems.length === 1) menuItem = getOption(visibleItems[0])
else if (visibleItems.length > 1)
menuItem.children = visibleItems.map((item) => getOption(item))
} else {
menuItem.children = visibleChildren.map((item) => getOption(item))
}
return menuItem
}
const menus = computed<TreeSelectOption[]>(() => {
return permissionStore.allMenus.map((item) => getOption(item))
})
</script>
<template>
@@ -48,6 +91,22 @@ const channels = [
<n-form-item :label="$gettext('Default Backup Directory')">
<n-input v-model:value="model.backup_path" :placeholder="$gettext('/opt/ace/backup')" />
</n-form-item>
<n-form-item :label="$gettext('Custom Logo')">
<n-input
v-model:value="model.custom_logo"
:placeholder="$gettext('Please enter the complete URL')"
/>
</n-form-item>
<n-form-item :label="$gettext('Hide Menu')">
<n-tree-select
cascade
checkable
clearable
multiple
:options="menus"
v-model:value="model.hidden_menu"
/>
</n-form-item>
</n-form>
</n-flex>
</template>