pay-company/src/common/libs/umi/layoutConfig.tsx

303 lines
9.1 KiB
TypeScript
Raw Normal View History

2026-01-08 16:35:06 +08:00
import { MyIcons, MyIconsType, PermissionsType, useMyState } from '@/common';
import AvatarProps from '@/common/components/layout/AvatarProps';
2026-02-04 12:32:17 +08:00
import { Apis } from '@/gen/Apis';
2026-01-08 16:35:06 +08:00
import { Link, RuntimeConfig, history, useNavigate } from '@umijs/max';
2026-02-04 12:32:17 +08:00
import { AutoComplete, Input, Menu, MenuProps, Select, Space } from 'antd';
import { useEffect, useState } from 'react';
2026-01-08 16:35:06 +08:00
import './allConfig.scss';
// import Logo from './logo.png';
interface LevelKeysProps {
key?: string;
children?: LevelKeysProps[];
}
2026-02-04 12:32:17 +08:00
2026-01-08 16:35:06 +08:00
const loopMenu = (permissions: PermissionsType[] | undefined) => {
let tree: PermissionsType[] = [];
let map: Record<number, PermissionsType> = {};
// 过滤掉Button和Tab类型的权限这些不应该显示在菜单中
const menuPermissions = permissions?.filter(
(p) => p.type !== 'Button' && p.type !== 'Tab',
);
menuPermissions?.forEach((permission) => {
map[permission.id] = {
path: permission.path,
name: permission.name,
icon: permission.icon && MyIcons[permission.icon as MyIconsType],
label: permission.name,
key: permission.path || permission.id.toString(),
hideInMenu: false, // 已经过滤过类型这里可以设置为false
};
});
menuPermissions?.forEach((permission) => {
let node = map[permission.id];
const parentId = permission?.parent_id;
if (parentId !== null && parentId !== undefined) {
const parentNode = map[parentId];
if (parentNode) {
// 初始化 children 如果不存在
if (!Array.isArray(parentNode.children)) {
parentNode.children = [];
}
parentNode.children.push(node);
} else {
// 父节点不存在,作为根节点处理
console.warn(
`Parent node with id ${parentId} not found for permission ${permission.id}`,
);
tree.push(node);
}
} else {
tree.push(node);
}
});
return tree?.[0]?.children;
};
export const LayoutConfig: RuntimeConfig['layout'] = () => {
2026-02-04 12:32:17 +08:00
const [getSelectProject, setSelectProject] = useState<LevelKeysProps[]>([]);
2026-01-08 16:35:06 +08:00
const { snap } = useMyState();
const navigate = useNavigate();
const permissionsList = (snap.session.permissions || [])
.filter((p: any) => p.type !== 'Button' && p.path)
.sort((a: any, b: any) => a._lft - b._lft)
.map((p: any) => ({ value: p.path, label: p.name }));
const quickLinks = [
{ label: '工单Bi', path: '/work_order/work_bi' },
{ label: '合同Bi', path: '/contract/contracts_bi' },
{ label: '收费Bi', path: '/charge/charge_bi' },
{ label: '项目Bi', path: '/asset/asset_bi' },
];
2026-02-04 12:32:17 +08:00
const handleLoadProject = async () => {
let res = await Apis.Common.Auth.GetProjects();
setSelectProject(
res?.data?.map((item) => ({
value: item.id,
label: item.name,
})),
);
};
2026-01-08 16:35:06 +08:00
const [stateOpenKeys, setStateOpenKeys] = useState(['2', '23']);
const getLevelKeys: any = (items1: LevelKeysProps[]) => {
const key: Record<string, number> = {};
const func = (items2: LevelKeysProps[], level = 1) => {
items2?.forEach((item) => {
if (item.key) {
key[item.key] = level;
}
if (item.children) {
func(item.children, level + 1);
}
});
};
func(items1);
return key;
};
2026-02-04 12:32:17 +08:00
useEffect(() => {
handleLoadProject('');
}, []);
2026-01-08 16:35:06 +08:00
return {
title: '',
// 首页 logo
logo: (
2026-02-04 12:32:17 +08:00
<div style={{ width: 136, display: 'flex', justifyContent: 'center' }}>
2026-01-19 14:56:53 +08:00
<img
src={
2026-01-22 11:41:29 +08:00
snap.session?.company_configs?.config_value?.admin_logo
? snap.session?.company_configs?.config_value?.admin_logo[0]?.url
2026-01-19 14:56:53 +08:00
: ''
}
2026-02-04 12:32:17 +08:00
style={{ width: 'auto', height: '42px' }}
2026-01-19 14:56:53 +08:00
/>
2026-01-08 16:35:06 +08:00
</div>
),
layout: 'mix',
siderWidth: 180,
colorPrimary: '#1890ff',
pure: history.location.pathname === '/login',
avatarProps: {
render: () => <AvatarProps user={snap.session.user} />,
},
headerContentRender: () => (
<div className="headerContentRender">
<div style={{ display: 'flex', alignItems: 'center', gap: 20 }}>
<HeaderSearch permissionsList={permissionsList} />
</div>
<Space size={10}>
2026-02-04 12:32:17 +08:00
{/* <Button
2026-01-08 16:35:06 +08:00
type="default"
shape="circle"
icon={<SettingOutlined />}
onClick={() => history.push('/system/sys_permissions')}
2026-02-04 12:32:17 +08:00
/> */}
<Select
onSearch={handleLoadProject}
options={getSelectProject}
allowClear
style={{ width: 160 }}
defaultValue={snap.session.current_project?.id}
onChange={(e: any) => {
Apis.Common.Auth.SwitchProject({
project_id: e ? e?.toString() : 'all',
}).then(() => {
window.location.reload();
});
console.log(e, 'e');
}}
placeholder="选择项目"
2026-01-08 16:35:06 +08:00
/>
</Space>
</div>
),
//水印设置
waterMarkProps: {
content: snap.session.user?.username,
},
defaultCollapsed: true,
collapsedButtonRender: false,
token: {
bgLayout: '#f6f6f6',
// header: {
// colorBgHeader: '#1B1F3B',
// colorHeaderTitle: '#f8f8f8',
// colorTextRightActionsItem: '#FFF',
// heightLayoutHeader: 50,
// },
//菜单背景色
sider: {
colorMenuBackground: '#fff',
colorTextMenuSelected: '#1890ff', // 菜单激活项字体颜色设置为蓝色
},
},
// 上下菜单
menuItemRender: (item, dom) => <Link to={item.path || '/'}>{dom}</Link>,
//点击目录,收起其他菜单
menuCollapse: true,
// //左右菜单
menuRender: () => {
let objjs: any = [];
snap.session.permissions?.forEach((res: any) => {
objjs.push(res);
});
let data = objjs.sort((a: any, b: any) => {
return a._lft - b._lft;
});
const menus = loopMenu(data);
const levelKeys: any = getLevelKeys(menus as LevelKeysProps[]);
const onOpenChange: MenuProps['onOpenChange'] = (openKeys) => {
const currentOpenKey = openKeys.find(
(key) => !stateOpenKeys.includes(key),
);
// open
if (currentOpenKey !== undefined) {
const repeatIndex = openKeys
.filter((key) => key !== currentOpenKey)
.findIndex((key) => levelKeys[key] === levelKeys[currentOpenKey]);
setStateOpenKeys(
openKeys
// remove repeat key
.filter((_, index) => index !== repeatIndex)
// remove current level all child
.filter((key) => levelKeys[key] <= levelKeys[currentOpenKey]),
);
} else {
// close
setStateOpenKeys(openKeys);
}
};
return (
<div
style={{
position: 'relative',
width: 180,
top: 0,
left: 0,
bottom: 0,
height: '100vh',
zIndex: 100,
boxShadow: '0 2px 10px rgba(0, 0, 0, 0.1)',
}}
>
<div
style={{
position: 'fixed',
paddingTop: 60,
top: 0,
left: 0,
bottom: 0,
backgroundColor: '#fff',
overflowY: 'auto',
}}
>
<Menu
style={{ width: '165px' }}
mode="inline"
defaultSelectedKeys={[history.location.pathname]}
theme="light"
items={menus}
openKeys={stateOpenKeys}
onOpenChange={onOpenChange}
onClick={({ key }) => {
sessionStorage.setItem('breadcrumbs', '');
navigate(key);
console.log(key, 'key2');
}}
onSelect={({ key }) => {
console.log(key, 'key');
}}
/>
</div>
</div>
);
},
menuMode: 'inline',
menu: {
params: snap.session.permissions,
mode: 'inline',
request: async () => {
let objjs: any = [];
snap.session.permissions?.forEach((res: any) => {
objjs.push(res);
});
let data = objjs.sort((a: any, b: any) => {
return a._lft - b._lft;
});
const menus = loopMenu(data);
return Promise.resolve(menus);
},
},
// unAccessible: <div>unAccessible</div>,
};
};
const HeaderSearch = ({ permissionsList }: { permissionsList: any[] }) => {
const [value, setValue] = useState<string>('');
return (
<AutoComplete
value={value}
options={permissionsList}
style={{ width: 280 }}
placeholder="~输入关键字,搜索系统功能"
filterOption={(inputValue, option) =>
(option?.label as string)
?.toLowerCase()
.includes(inputValue.toLowerCase())
}
onChange={(v) => setValue(v)}
onSelect={(v) => {
setValue('');
history.push(v as string);
}}
>
:
<Input allowClear size="middle" />
</AutoComplete>
);
};