feat: 新增自定义图标库并调整菜单图标与菜单归属
1. 新增 iconfont 自定义图标库及相关依赖文件 2. 调整菜单图标为自定义字体图标,替换原有 Ant Design 图标 3. 将客户拜访菜单从客户管理移动到项目管理作为首个子菜单 4. 优化侧边菜单展开逻辑与图标样式适配
This commit is contained in:
1 parent
c60caa4770
commit
68af363ca9
12 files changed
+207
-19
No files matched your search
@@ -140,7 +140,14 @@ const iconMap: Record<string, Component> = {
|
||||
DashboardOutlined,
|
||||
}
|
||||
|
||||
// iconfont 图标类名前缀(对应 assets/fonts/iconfont/iconfont.css 的 css_prefix_text)
|
||||
const ICONFONT_PREFIX = 'xt-'
|
||||
|
||||
function resolveIcon(icon?: string | null) {
|
||||
// icon 值形如 xt-xxx 时渲染 iconfont 图标,否则回退到 ant-design 图标
|
||||
if (icon && icon.startsWith(ICONFONT_PREFIX)) {
|
||||
return () => h('i', { class: `iconfont ${icon}` })
|
||||
}
|
||||
const iconComponent = icon ? iconMap[icon] : undefined
|
||||
return () => h(iconComponent || MenuOutlined)
|
||||
}
|
||||
@@ -194,6 +201,20 @@ const menuItems = computed<MenuItem[]>(() => [
|
||||
...buildMenuItems(permissionStore.menus),
|
||||
])
|
||||
|
||||
// 子菜单路径 → 所属父级目录的菜单 key,用于按当前路由展开对应的父菜单
|
||||
// (不能按路径首段推导:如“客户拜访”归属项目管理,但路径仍为 /customer/visit)
|
||||
const parentKeyMap = computed<Record<string, string>>(() => {
|
||||
const map: Record<string, string> = {}
|
||||
for (const node of permissionStore.menus) {
|
||||
if (node.menuType !== 1) continue
|
||||
const dirKey = node.menuPath || `dir-${node.id}`
|
||||
for (const child of node.children || []) {
|
||||
if (child.menuPath) map[child.menuPath] = dirKey
|
||||
}
|
||||
}
|
||||
return map
|
||||
})
|
||||
|
||||
// 计算属性
|
||||
const userInfo = computed(() => permissionStore.userInfo)
|
||||
const displayName = computed(() => userInfo.value?.realName || userInfo.value?.username || '管理员')
|
||||
@@ -219,10 +240,10 @@ watch(
|
||||
(path) => {
|
||||
selectedKeys.value = [path]
|
||||
|
||||
// 自动展开父级菜单
|
||||
const pathParts = path.split('/').filter(Boolean)
|
||||
if (pathParts.length > 1) {
|
||||
openKeys.value = [`/${pathParts[0]}`]
|
||||
// 自动展开当前菜单所属的父级目录
|
||||
const parentKey = parentKeyMap.value[path]
|
||||
if (parentKey) {
|
||||
openKeys.value = [parentKey]
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
@@ -234,9 +255,9 @@ watch(collapsed, (val) => {
|
||||
openKeys.value = []
|
||||
} else {
|
||||
// 展开时根据当前路由自动打开对应的父菜单
|
||||
const pathParts = route.path.split('/').filter(Boolean)
|
||||
if (pathParts.length > 1) {
|
||||
openKeys.value = [`/${pathParts[0]}`]
|
||||
const parentKey = parentKeyMap.value[route.path]
|
||||
if (parentKey) {
|
||||
openKeys.value = [parentKey]
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -306,6 +327,30 @@ function handleUserMenuClick({ key }: { key: string }) {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
// iconfont 图标统一:该图标集为彩色字体,颜色写死在字形里,无法用 color 覆盖,
|
||||
// 这里用 filter 统一压成单色,并按菜单状态在灰 / 白之间切换,与 ant-design 图标观感保持一致
|
||||
// 尺寸统一:ant-design 菜单图标为 14px,而 iconfont.css 自带 font-size: 16px,
|
||||
// 故此处显式对齐为 14px,并重置 line-height,避免字体图标在 antd 的 line-height: 0 下出现基线偏移
|
||||
:deep(.ant-menu) .iconfont {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
vertical-align: -0.125em;
|
||||
filter: brightness(0) invert(0.65);
|
||||
}
|
||||
|
||||
// 折叠态与 ant-design 图标同步放大到 16px
|
||||
:deep(.ant-menu-inline-collapsed) .iconfont {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
:deep(.ant-menu-item:hover) .iconfont,
|
||||
:deep(.ant-menu-item-selected) .iconfont,
|
||||
:deep(.ant-menu-submenu-title:hover) .iconfont,
|
||||
:deep(.ant-menu-submenu-selected) .iconfont {
|
||||
filter: brightness(0) invert(1);
|
||||
}
|
||||
|
||||
.collapse-btn {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
||||
Reference in new issue
Block a user