|
@@ -2,7 +2,7 @@
|
|
|
* @Author: code4eat awesomedema@gmail.com
|
|
|
* @Date: 2022-12-14 14:14:32
|
|
|
* @LastEditors: code4eat awesomedema@gmail.com
|
|
|
- * @LastEditTime: 2024-06-11 16:15:45
|
|
|
+ * @LastEditTime: 2024-08-23 15:29:07
|
|
|
* @FilePath: /BudgetManaSystem/src/app.ts
|
|
|
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
|
*/
|
|
@@ -28,13 +28,38 @@ import DevicePixelRatio from './utils/devicePixelRatio.js';
|
|
|
|
|
|
import Icon, { createFromIconfontCN, FolderOutlined } from '@ant-design/icons';
|
|
|
import { getPlatformMenu } from '@/services/auth';
|
|
|
-import { Key, useEffect, useState } from 'react';
|
|
|
+import { JSXElementConstructor, Key, ReactElement, ReactFragment, ReactPortal, useEffect, useRef, useState } from 'react';
|
|
|
|
|
|
|
|
|
import './utils/zhongtaiC'
|
|
|
import { RuntimeAntdConfig } from '@umijs/max';
|
|
|
import { useLocation } from '@umijs/max';
|
|
|
import ResizableContainer from './components/ResizableContainer/index';
|
|
|
+import { IRoute } from '@umijs/max';
|
|
|
+
|
|
|
+
|
|
|
+// 权限检查函数
|
|
|
+function checkAccess(menu: IRoute[], pathname: string): boolean {
|
|
|
+ for (const item of menu) {
|
|
|
+ if (item.path === pathname) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ if (item.children) {
|
|
|
+ const hasAccess = checkAccess(item.children, pathname);
|
|
|
+ if (hasAccess) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+function removePrefix(input: string, prefix: string): string {
|
|
|
+ if (input.startsWith(prefix)) {
|
|
|
+ return input.slice(prefix.length);
|
|
|
+ }
|
|
|
+ return input;
|
|
|
+}
|
|
|
|
|
|
|
|
|
const IconFont = createFromIconfontCN({
|
|
@@ -127,12 +152,12 @@ const findItemByKey: any = (tree: any[], key: string, keyName: string) => {
|
|
|
|
|
|
|
|
|
export async function getInitialState(): Promise<{
|
|
|
- isCollapsed: boolean, spacicalPageParamsType?: any[], userData: UserData, memuData: any[]
|
|
|
+ isCollapsed: boolean, spacicalPageParamsType?: any[], userData: UserData, memuData: any[], computeDate: string
|
|
|
}> {
|
|
|
|
|
|
new DevicePixelRatio().init();
|
|
|
|
|
|
- return { isCollapsed: false, spacicalPageParamsType: [], userData: {}, memuData: [] };
|
|
|
+ return { isCollapsed: false, spacicalPageParamsType: [], userData: {}, memuData: [], computeDate: `${new Date().getFullYear()}-${(new Date().getMonth() + 1).toString().padStart(2, '0')}` };
|
|
|
}
|
|
|
|
|
|
export const request: RequestConfig = {
|
|
@@ -209,12 +234,12 @@ export const request: RequestConfig = {
|
|
|
|
|
|
} else {
|
|
|
notification.error({
|
|
|
- top:72,
|
|
|
+ top: 72,
|
|
|
message: '提示',
|
|
|
description: errorMessage || msg,
|
|
|
placement: 'topRight',
|
|
|
- icon:<IconFont type="icon-jinggaotishi" />,
|
|
|
- style:{padding:16,borderRadius:8}
|
|
|
+ icon: <IconFont type="icon-jinggaotishi" />,
|
|
|
+ style: { padding: 16, borderRadius: 8 }
|
|
|
})
|
|
|
return false
|
|
|
}
|
|
@@ -229,12 +254,12 @@ export const request: RequestConfig = {
|
|
|
} else {
|
|
|
|
|
|
notification.error({
|
|
|
- top:72,
|
|
|
+ top: 72,
|
|
|
message: '提示',
|
|
|
description: errorMessage || msg,
|
|
|
placement: 'topRight',
|
|
|
- icon:<IconFont type="icon-jinggaotishi" />,
|
|
|
- style:{padding:16,borderRadius:8}
|
|
|
+ icon: <IconFont type="icon-jinggaotishi" />,
|
|
|
+ style: { padding: 16, borderRadius: 8 }
|
|
|
})
|
|
|
return false;
|
|
|
}
|
|
@@ -360,199 +385,50 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
|
|
|
|
|
|
const location = useLocation();
|
|
|
const currentPath = location.pathname;
|
|
|
+ const isMenuClickRef = useRef(false);
|
|
|
|
|
|
const onCollapse = (isCollapsed: boolean): void => {
|
|
|
setInitialState({ ...initialState, isCollapsed }).then();
|
|
|
};
|
|
|
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
-
|
|
|
- function findMenuItemByPath(menu: any, path: string) {
|
|
|
- let result: any = null;
|
|
|
-
|
|
|
- // 递归搜索函数
|
|
|
- function search(items: any) {
|
|
|
- for (let item of items) {
|
|
|
- if (item.path === path) {
|
|
|
- result = item;
|
|
|
- return; // 找到匹配项,提前终止搜索
|
|
|
- }
|
|
|
- if (item.children && item.children.length > 0) {
|
|
|
- search(item.children); // 递归搜索子菜单
|
|
|
- if (result) return; // 如果在子菜单中找到匹配项,提前终止搜索
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- search(menu); // 从顶层菜单开始搜索
|
|
|
- return result;
|
|
|
+ const checkPermission = (path: string) => {
|
|
|
+ const { memuData = [] } = initialState || {};
|
|
|
+ // 检查是否为无访问权限页面
|
|
|
+ if (path === '/noAccess') {
|
|
|
+ return true;
|
|
|
}
|
|
|
-
|
|
|
- // const matchedItem = findMenuItemByPath(menuData, currentPath);
|
|
|
- // if (matchedItem) {
|
|
|
-
|
|
|
- // set_selectedKeys([matchedItem.key]);
|
|
|
- // }
|
|
|
-
|
|
|
- }, [currentPath])
|
|
|
+
|
|
|
+ // 检查访问权限
|
|
|
+ const hasAccess = checkAccess([...memuData], path);
|
|
|
+
|
|
|
+ return hasAccess;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // useEffect(() => {
|
|
|
+ // return history.listen((location: any) => {
|
|
|
+ // if (!isMenuClickRef.current) {
|
|
|
+ // const path = removePrefix(location.location.pathname, '/CostAccountingSys');
|
|
|
+ // const hasPermission = checkPermission(path);
|
|
|
+ // console.log({ hasPermission, path });
|
|
|
+
|
|
|
+ // // 如果hasPermission为true,确保不会跳转到/noAccess
|
|
|
+ // if (!hasPermission && path !== '/noAccess') {
|
|
|
+ // history.push('/noAccess');
|
|
|
+ // }
|
|
|
+ // }
|
|
|
+ // isMenuClickRef.current = false; // 重置状态
|
|
|
+ // });
|
|
|
+ // }, [initialState]);
|
|
|
+
|
|
|
+
|
|
|
|
|
|
|
|
|
return {
|
|
|
menuHeaderRender: false,
|
|
|
- // token: {
|
|
|
- // sider: {
|
|
|
-
|
|
|
- // colorMenuBackground: '#fff',
|
|
|
- // colorTextMenuActive: '#3376FE',
|
|
|
- // colorTextMenuSelected: '#3376FE',
|
|
|
- // colorTextMenuTitle: '#17181A',
|
|
|
- // colorTextMenu: '#17181A',
|
|
|
- // //colorBgMenuItemHover:'##f0f2f5',
|
|
|
- // colorBgMenuItemSelected: '#F2F6FF',
|
|
|
-
|
|
|
- // // colorBgMenuItemCollapsedHover:'#f0f2f5',
|
|
|
- // // //colorBgMenuItemCollapsedSelected:'blue'
|
|
|
-
|
|
|
- // }
|
|
|
-
|
|
|
- // },
|
|
|
-
|
|
|
disableMobile: true,
|
|
|
- // menuProps: {
|
|
|
- // openKeys: [...openKeys],
|
|
|
- // selectedKeys: [...selectedKeys],
|
|
|
- // onSelect: ({ selectedKeys }: { selectedKeys: string[] }) => {
|
|
|
- // set_selectedKeys(selectedKeys);
|
|
|
- // localStorage.setItem('selectedKeys', JSON.stringify(selectedKeys));
|
|
|
- // },
|
|
|
- // onOpenChange: (keys: string[]) => {
|
|
|
- // set_openKeys([...keys]);
|
|
|
- // localStorage.setItem('openKeys', JSON.stringify(keys));
|
|
|
- // },
|
|
|
- // },
|
|
|
- menu: {
|
|
|
- locale: false,
|
|
|
- // request: async () => {
|
|
|
- // const userData = localStorage.getItem('userData');
|
|
|
- // const currentSelectedTab = localStorage.getItem('currentSelectedTab');
|
|
|
- // if (currentSelectedTab) {
|
|
|
- // const { menuId } = JSON.parse(currentSelectedTab);
|
|
|
- // const systemId = menuId;
|
|
|
- // const data: any[] = await getPlatformMenu(systemId);
|
|
|
- // if (data) {
|
|
|
-
|
|
|
- // const selectedKeys = localStorage.getItem('selectedKeys');
|
|
|
- // const openKeys = localStorage.getItem('openKeys');
|
|
|
- // set_menuData(data);
|
|
|
- // if (selectedKeys && openKeys) {
|
|
|
- // const _selectedKeys = JSON.parse(selectedKeys);
|
|
|
- // const _openKeys = JSON.parse(openKeys);
|
|
|
- // set_openKeys(_openKeys);
|
|
|
- // set_selectedKeys(_selectedKeys);
|
|
|
- // } else {
|
|
|
- // if (data[0].children && data[0].children.length > 0) {
|
|
|
-
|
|
|
- // const childs = data[0].children;
|
|
|
- // set_openKeys([data[0].key]);
|
|
|
- // set_selectedKeys([childs[0].key]);
|
|
|
- // localStorage.setItem('openKeys', JSON.stringify([data[0].key]));
|
|
|
- // localStorage.setItem('selectedKeys', JSON.stringify([childs[0].key]));
|
|
|
- // history.push(`${childs[0].path}`);
|
|
|
-
|
|
|
- // } else {
|
|
|
- // if (data[0]) {
|
|
|
- // set_openKeys([data[0].key]);
|
|
|
- // set_selectedKeys([data[0].key]);
|
|
|
- // localStorage.setItem('openKeys', JSON.stringify([data[0].key]));
|
|
|
- // localStorage.setItem('selectedKeys', JSON.stringify([data[0].key]));
|
|
|
- // history.push(`${data[0].path}`);
|
|
|
- // }
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
-
|
|
|
- // function processMenuItem(item: any) {
|
|
|
- // if (!item) return null;
|
|
|
-
|
|
|
- // let newItem = { ...item }; // 深拷贝当前节点
|
|
|
-
|
|
|
- // // 如果是叶子节点
|
|
|
- // if (!item.children || item.children.length === 0) {
|
|
|
- // let queryParams = [];
|
|
|
-
|
|
|
- // if (newItem.softUrl) {
|
|
|
- // queryParams.push(`softUrl=${newItem.softUrl}`);
|
|
|
- // }
|
|
|
-
|
|
|
- // if (newItem.youshuUrl) {
|
|
|
- // queryParams.push(`youshuUrl=${newItem.youshuUrl}`);
|
|
|
- // }
|
|
|
-
|
|
|
- // if (queryParams.length > 0) {
|
|
|
- // newItem.path = `${newItem.path}?${queryParams.join('&')}`;
|
|
|
- // }
|
|
|
-
|
|
|
- // return newItem; // 返回新的叶子节点
|
|
|
- // }
|
|
|
-
|
|
|
- // // 否则,递归处理子节点
|
|
|
- // newItem.children = newItem.children.map(processMenuItem);
|
|
|
- // return newItem;
|
|
|
- // }
|
|
|
-
|
|
|
- // function processMenu(menuArray: any[]) {
|
|
|
- // if (!menuArray) return [];
|
|
|
- // return menuArray.map(processMenuItem);
|
|
|
- // }
|
|
|
-
|
|
|
- // const _menu = processMenu(data);
|
|
|
-
|
|
|
- // setInitialState((t: any) => ({ ...t, spacicalPageParamsType: _menu, memuData: data, userData: JSON.parse(userData as string) }));
|
|
|
-
|
|
|
-
|
|
|
- // function addIconToPath(node: any, paths: string[]) {
|
|
|
- // if (paths.includes(node.path)) {
|
|
|
- // if (node.path == '/home') {
|
|
|
- // node.icon = <Icon component={imgNode} />;
|
|
|
- // }
|
|
|
- // if (node.path == '/baseSetting') {
|
|
|
-
|
|
|
- // node.icon = <Icon component={setting} />;
|
|
|
- // }
|
|
|
- // if (node.path == '/monthlyInfoSearch') {
|
|
|
- // node.icon = <Icon component={()=><IconFont type='icon-yueduxinxicaiji' />} />;
|
|
|
- // }
|
|
|
- // if (node.path == '/costAccounting') {
|
|
|
- // node.icon = <Icon component={()=><IconFont type='icon-jixiaoguanli' />} />;
|
|
|
- // }
|
|
|
- // if (node.path == '/reportExport') {
|
|
|
- // node.icon = <Icon component={()=><IconFont type='icon-jixiaoguanli' />} />;
|
|
|
- // }
|
|
|
- // if (node.path == '/costLibraryManagement') {
|
|
|
- // node.icon = <Icon component={()=><IconFont type='icon-chengbenkuguanli' />} />;
|
|
|
- // }
|
|
|
- // if (node.path == '/static') {
|
|
|
- // node.icon = <Icon component={()=><IconFont type='icon-baobiaochaxun' />} />;
|
|
|
- // }
|
|
|
- // }
|
|
|
- // if (node.children) {
|
|
|
- // node.children.forEach((child: any) => addIconToPath(child, paths));
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // _menu.forEach((item: any) => {
|
|
|
- // addIconToPath(item, ['/home', '/baseInfoMana', '/costAccounting','/monthlyInfoSearch','/static','/reportExport','/costLibraryManagement','/baseSetting']);
|
|
|
- // });
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- // return _menu
|
|
|
- // }
|
|
|
- // }
|
|
|
-
|
|
|
- // },
|
|
|
- },
|
|
|
onPageChange: () => { },
|
|
|
collapsedButtonRender: () => {
|
|
|
return (
|
|
@@ -567,35 +443,22 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
|
|
|
}><IconFont className='menuCollapseIcon' type={isCollapsed ? 'icon-celanzhankai' : 'icon-celanshouqi'} /></div>
|
|
|
)
|
|
|
},
|
|
|
- // collapsed: isCollapsed,
|
|
|
+ collapsed: isCollapsed,
|
|
|
// fixSiderbar:false,
|
|
|
- menuRender: (props: any) => {
|
|
|
-
|
|
|
-
|
|
|
- const { location } = props;
|
|
|
- const [menu, set_menu] = useState<any[]>([]);
|
|
|
-
|
|
|
- const [slectedKey, set_slectedKey] = useState<string[]>([]);
|
|
|
- const [openKeys, set_openKeys] = useState<string[]>([]);
|
|
|
-
|
|
|
- // const currentSelectedItem = findItemByKey(menuData,location.pathname,'path');
|
|
|
-
|
|
|
- const menuClickHandle = (info: any) => {
|
|
|
- const foundItem = findItemByKey(menu, info.key, 'key');
|
|
|
- // console.log({foundItem,info});
|
|
|
- if (foundItem) {
|
|
|
- set_slectedKey([`${info.key}`]);
|
|
|
- history.push(foundItem.path);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- const onOpenChangeHandle = (openKeys: string[]) => {
|
|
|
- set_openKeys(openKeys);
|
|
|
- }
|
|
|
-
|
|
|
- const getMenu = async () => {
|
|
|
+ menuItemRender:(item: { path: any; }, dom: string | number | boolean | ReactElement<any, string | JSXElementConstructor<any>> | ReactFragment | ReactPortal | null | undefined) => {
|
|
|
+ return (
|
|
|
+ <a
|
|
|
+ onClick={() => {
|
|
|
+ isMenuClickRef.current = true; // 标记为菜单点击
|
|
|
+ history.push(`${item.path}`);
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {dom}
|
|
|
+ </a>
|
|
|
+ );
|
|
|
+ },
|
|
|
+ menu:{
|
|
|
+ request:async ()=>{
|
|
|
const userData = localStorage.getItem('userData');
|
|
|
const currentSelectedTab = localStorage.getItem('currentSelectedTab');
|
|
|
if (currentSelectedTab) {
|
|
@@ -603,37 +466,6 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
|
|
|
const systemId = menuId;
|
|
|
const data: any[] = await getPlatformMenu(systemId);
|
|
|
if (data) {
|
|
|
-
|
|
|
- const selectedKeys = localStorage.getItem('selectedKeys');
|
|
|
- const openKeys = localStorage.getItem('openKeys');
|
|
|
-
|
|
|
- if (selectedKeys && openKeys) {
|
|
|
- const _selectedKeys = JSON.parse(selectedKeys);
|
|
|
- const _openKeys = JSON.parse(openKeys);
|
|
|
- set_openKeys(_openKeys);
|
|
|
- set_slectedKey(_selectedKeys);
|
|
|
- } else {
|
|
|
- if (data[0].children && data[0].children.length > 0) {
|
|
|
-
|
|
|
- const childs = data[0].children;
|
|
|
- set_openKeys([data[0].key]);
|
|
|
- set_slectedKey([childs[0].key]);
|
|
|
- localStorage.setItem('openKeys', JSON.stringify([data[0].key]));
|
|
|
- localStorage.setItem('selectedKeys', JSON.stringify([childs[0].key]));
|
|
|
- history.push(`${childs[0].path}`);
|
|
|
-
|
|
|
- } else {
|
|
|
- if (data[0]) {
|
|
|
- set_openKeys([data[0].key]);
|
|
|
- set_slectedKey([data[0].key]);
|
|
|
- localStorage.setItem('openKeys', JSON.stringify([data[0].key]));
|
|
|
- localStorage.setItem('selectedKeys', JSON.stringify([data[0].key]));
|
|
|
- history.push(`${data[0].path}`);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
function processMenuItem(item: any) {
|
|
|
if (!item) return null;
|
|
|
|
|
@@ -708,44 +540,19 @@ export const layout = ({ initialState, setInitialState }: { initialState: any, s
|
|
|
});
|
|
|
|
|
|
const { newTree, firstLeafNode, firstLeafNodePath } = transformTree(_menu);
|
|
|
- // set_openKeys(firstLeafNodePath.map(a => `${a.key}`));
|
|
|
- // set_slectedKey([`${firstLeafNode.key}`]);
|
|
|
- set_menu(newTree);
|
|
|
+ return newTree
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
-
|
|
|
- const foundItem = findItemByKey(menu, location.pathname, 'path');
|
|
|
-
|
|
|
- if (foundItem) {
|
|
|
- set_slectedKey(foundItem.key);
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- }, [menu]);
|
|
|
-
|
|
|
- useEffect(() => {
|
|
|
- getMenu();
|
|
|
- }, [])
|
|
|
+ },
|
|
|
+ menuRender: (props: any, defaultDom: any) => {
|
|
|
|
|
|
return (
|
|
|
- <ResizableContainer width={isCollapsed ? 64 : 200} minWidth={0} maxWidth={600} height={'calc(100vh - 58px)'}>
|
|
|
+ <ResizableContainer width={isCollapsed ? 64 : 200} minWidth={0} maxWidth={600} height={'calc(100vh - 47px)'}>
|
|
|
<div style={{ height: '100%', background: '#fff', position: 'relative' }}>
|
|
|
<div className='menuWrapper' style={{ height: 'calc(100% - 40px)', overflowY: 'scroll', overflowX: 'hidden' }}>
|
|
|
- <Menu
|
|
|
-
|
|
|
- onClick={menuClickHandle}
|
|
|
- onOpenChange={onOpenChangeHandle}
|
|
|
- style={{ width: '100%' }}
|
|
|
- openKeys={openKeys}
|
|
|
- selectedKeys={slectedKey}
|
|
|
- mode="inline"
|
|
|
- items={menu}
|
|
|
- inlineCollapsed={isCollapsed}
|
|
|
- />
|
|
|
+ {defaultDom}
|
|
|
</div>
|
|
|
|
|
|
<div style={{
|