1
This commit is contained in:
parent
bf8c5e1cc1
commit
98ccb19fbe
@ -201,6 +201,12 @@ const routes: RouteRecordRaw[] = [
|
|||||||
component: () =>
|
component: () =>
|
||||||
import("@/views/admin/account/cost/myMoney/index.vue"),
|
import("@/views/admin/account/cost/myMoney/index.vue"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: "myMoneyDetail",
|
||||||
|
name: "myMoneyDetail",
|
||||||
|
component: () =>
|
||||||
|
import("@/views/admin/account/cost/myMoneyDetail/index.vue"),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "voucher",
|
path: "voucher",
|
||||||
name: "voucher",
|
name: "voucher",
|
||||||
|
|||||||
@ -65,12 +65,14 @@
|
|||||||
|
|
||||||
<!-- 账单表格 -->
|
<!-- 账单表格 -->
|
||||||
<a-table
|
<a-table
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data-source="billData"
|
:data-source="billData"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
@change="handleTableChange"
|
@change="handleTableChange"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
class="bill-table"
|
class="bill-table"
|
||||||
|
:scroll="{ x: 1200 }"
|
||||||
|
|
||||||
>
|
>
|
||||||
<!-- 流水号列 -->
|
<!-- 流水号列 -->
|
||||||
<template #bodyCell="{ column, record }">
|
<template #bodyCell="{ column, record }">
|
||||||
|
|||||||
@ -22,15 +22,15 @@ import { h, reactive, computed } from 'vue';
|
|||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import {
|
import {
|
||||||
HomeOutlined,
|
HomeOutlined,
|
||||||
FolderOpenOutlined,
|
|
||||||
ConsoleSqlOutlined,
|
ConsoleSqlOutlined,
|
||||||
GlobalOutlined,
|
GlobalOutlined,
|
||||||
LaptopOutlined,
|
|
||||||
MoneyCollectOutlined,
|
MoneyCollectOutlined,
|
||||||
TeamOutlined,
|
TeamOutlined,
|
||||||
} from '@ant-design/icons-vue';
|
} from '@ant-design/icons-vue';
|
||||||
import type { MenuMode, MenuTheme } from 'ant-design-vue';
|
import type { MenuMode, MenuTheme } from 'ant-design-vue';
|
||||||
import { ItemType } from 'ant-design-vue';
|
|
||||||
|
// 移除 ItemType 的导入,直接使用 Ant Design Vue 的 MenuItem 类型
|
||||||
|
import type { MenuProps } from 'ant-design-vue';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@ -39,39 +39,40 @@ interface MenuItem {
|
|||||||
path: string;
|
path: string;
|
||||||
name: string;
|
name: string;
|
||||||
icon?: any;
|
icon?: any;
|
||||||
disabled?: boolean; // 新增字段
|
disabled?: boolean;
|
||||||
children?: Omit<MenuItem, 'icon'>[]; // 子项不需要 icon
|
visible?: boolean;
|
||||||
|
children?: Omit<MenuItem, 'icon'>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const menuItems: MenuItem[] = [
|
const menuItems: MenuItem[] = [
|
||||||
{ path: '/layout/admin/home', name: '总览', icon: HomeOutlined },
|
{ path: '/layout/admin/home', name: '总览', icon: HomeOutlined, visible: true },
|
||||||
{ path: '/layout/admin/instance', name: '容器实例', icon: ConsoleSqlOutlined },
|
{ path: '/layout/admin/instance', name: '容器实例', icon: ConsoleSqlOutlined, visible: true },
|
||||||
// { path: '/layout/admin/fileStore', name: '文件存储', icon: FolderOpenOutlined },
|
{ path: '/layout/admin/image', name: '镜像', icon: GlobalOutlined, visible: true },
|
||||||
{ path: '/layout/admin/image', name: '镜像', icon: GlobalOutlined },
|
|
||||||
// { path: '/layout/publicData', name: '公开数据', icon: LaptopOutlined },
|
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
name: '费用',
|
name: '费用',
|
||||||
icon: MoneyCollectOutlined,
|
icon: MoneyCollectOutlined,
|
||||||
|
visible: true,
|
||||||
children: [
|
children: [
|
||||||
// { path: '/layout/admin/costDetail', name: '收支明细' },
|
{ path: '/layout/admin/myMoney', name: '费用总览', visible: true, disabled: false },
|
||||||
{ path: '/layout/admin/myMoney', name: '费用总览' },
|
// 消费明细设置为不可见
|
||||||
{ path: '/layout/admin/myOrder', name: '我的订单' },
|
{ path: '/layout/admin/myMoneyDetail', name: '消费明细', visible: false, disabled: false },
|
||||||
{ path: '/layout/admin/flow', name: '账单明细' },
|
{ path: '/layout/admin/myOrder', name: '我的订单', visible: true, disabled: false },
|
||||||
{ path: '/layout/admin/coupon', name: '优惠券(待开发)', disabled: true },
|
{ path: '/layout/admin/flow', name: '账单明细', visible: true, disabled: false },
|
||||||
{ path: '/layout/admin/invoice', name: '发票(待开发)', disabled: true },
|
{ path: '/layout/admin/coupon', name: '优惠券(待开发)', disabled: true, visible: true },
|
||||||
{ path: '/layout/admin/voucher', name: '代金券(待开发)', disabled: true },
|
{ path: '/layout/admin/invoice', name: '发票(待开发)', disabled: true, visible: true },
|
||||||
{ path: '/layout/admin/contract', name: '合同(待开发)', disabled: true },
|
{ path: '/layout/admin/voucher', name: '代金券(待开发)', disabled: true, visible: true },
|
||||||
|
{ path: '/layout/admin/contract', name: '合同(待开发)', disabled: true, visible: true },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
name: '账号',
|
name: '账号',
|
||||||
icon: TeamOutlined,
|
icon: TeamOutlined,
|
||||||
|
visible: true,
|
||||||
children: [
|
children: [
|
||||||
{ path: '/layout/admin/security', name: '账号安全' },
|
{ path: '/layout/admin/security', name: '账号安全', visible: true },
|
||||||
{ path: '/layout/admin/history', name: '访问记录' },
|
{ path: '/layout/admin/history', name: '访问记录', visible: true },
|
||||||
// { path: '/controlPanel/security', name: '安全设置' },
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -84,60 +85,111 @@ const state = reactive({
|
|||||||
openKeys: ['/controlPanel/fee', '/controlPanel/account'],
|
openKeys: ['/controlPanel/fee', '/controlPanel/account'],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 方法一:直接使用 MenuProps['items'] 类型
|
||||||
|
// 或者自己定义 MenuItemType 类型
|
||||||
|
type MenuItemType = NonNullable<MenuProps['items']>[number];
|
||||||
|
|
||||||
// 工具函数:生成菜单项
|
// 工具函数:生成菜单项
|
||||||
function getItem(
|
function getItem(
|
||||||
label: string,
|
label: string,
|
||||||
key: string,
|
key: string,
|
||||||
icon?: any,
|
icon?: any,
|
||||||
children?: ItemType[],
|
children?: MenuItemType[],
|
||||||
type?: 'group',
|
type?: 'group',
|
||||||
disabled?: boolean // 新增 disabled 参数
|
disabled?: boolean
|
||||||
): ItemType {
|
): MenuItemType | null {
|
||||||
return {
|
return {
|
||||||
key,
|
key,
|
||||||
icon,
|
icon,
|
||||||
children,
|
children,
|
||||||
label,
|
label,
|
||||||
type,
|
type,
|
||||||
disabled, // 应用 disabled
|
disabled,
|
||||||
} as ItemType;
|
} as MenuItemType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 将 menuItems 转为 a-menu 所需的 items
|
// 将 menuItems 转为 a-menu 所需的 items
|
||||||
const items = computed(() => {
|
const items = computed(() => {
|
||||||
return menuItems.map((item) => {
|
return menuItems
|
||||||
if (item.children && item.children.length > 0) {
|
.filter(item => item.visible !== false)
|
||||||
const childItems = item.children.map((child) =>
|
.map((item) => {
|
||||||
getItem(child.name, child.path, undefined, undefined, undefined, child.disabled)
|
if (item.children && item.children.length > 0) {
|
||||||
);
|
// 过滤掉 visible 为 false 的子项
|
||||||
return getItem(item.name, item.path, h(item.icon), childItems, undefined, item.disabled);
|
const childItems = item.children
|
||||||
} else {
|
.filter(child => child.visible !== false)
|
||||||
return getItem(item.name, item.path, h(item.icon), undefined, undefined, item.disabled);
|
.map((child) =>
|
||||||
}
|
getItem(
|
||||||
});
|
child.name,
|
||||||
|
child.path,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
child.disabled
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.filter(Boolean) as MenuItemType[];
|
||||||
|
|
||||||
|
// 如果子项全部被过滤掉了,则显示父项但不显示子菜单
|
||||||
|
if (childItems.length === 0) {
|
||||||
|
return getItem(
|
||||||
|
item.name,
|
||||||
|
item.path,
|
||||||
|
h(item.icon),
|
||||||
|
undefined, // 没有子项
|
||||||
|
undefined,
|
||||||
|
item.disabled
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return getItem(
|
||||||
|
item.name,
|
||||||
|
item.path,
|
||||||
|
h(item.icon),
|
||||||
|
childItems,
|
||||||
|
undefined,
|
||||||
|
item.disabled
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return getItem(
|
||||||
|
item.name,
|
||||||
|
item.path,
|
||||||
|
h(item.icon),
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
item.disabled
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.filter(Boolean) as MenuItemType[];
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleMenuSelect = ({ key }: { key: string }) => {
|
const handleMenuSelect = ({ key }: { key: string }) => {
|
||||||
// 防止跳转到被禁用的菜单(虽然 a-menu 不会触发 select,但加个判断更安全)
|
// 递归查找菜单项(需要包含所有项,包括隐藏的)
|
||||||
const targetItem = findMenuItemByKey(menuItems, key);
|
const allItems = flattenMenuItems(menuItems);
|
||||||
if (targetItem?.disabled) {
|
const targetItem = allItems.find(item => item.path === key);
|
||||||
|
|
||||||
|
// 检查是否禁用或不可见
|
||||||
|
if (targetItem?.disabled || targetItem?.visible === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
router.push(key);
|
router.push(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 辅助函数:递归查找菜单项
|
// 辅助函数:扁平化所有菜单项
|
||||||
function findMenuItemByKey(items: MenuItem[], key: string): MenuItem | undefined {
|
function flattenMenuItems(items: MenuItem[]): MenuItem[] {
|
||||||
for (const item of items) {
|
let result: MenuItem[] = [];
|
||||||
if (item.path === key) return item;
|
|
||||||
|
items.forEach(item => {
|
||||||
|
result.push(item);
|
||||||
if (item.children) {
|
if (item.children) {
|
||||||
const found = findMenuItemByKey(item.children, key);
|
result = result.concat(flattenMenuItems(item.children));
|
||||||
if (found) return found;
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return undefined;
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 其他代码保持不变
|
||||||
const changeMode = (checked: boolean) => {
|
const changeMode = (checked: boolean) => {
|
||||||
state.mode = checked ? 'vertical' : 'inline';
|
state.mode = checked ? 'vertical' : 'inline';
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user