init
This commit is contained in:
parent
8394cf8872
commit
4a516afdf2
|
|
@ -67,7 +67,7 @@ export default defineConfig({
|
||||||
.split('/')
|
.split('/')
|
||||||
.map((a: string) => a.replace(/([A-Z])/g, '-$1'))
|
.map((a: string) => a.replace(/([A-Z])/g, '-$1'))
|
||||||
.map((a: string) => a.toLowerCase());
|
.map((a: string) => a.toLowerCase());
|
||||||
return `sz-${arr.join('-')}-${localName}`.replace(/--/g, '-');
|
return `lys-${arr.join('-')}-${localName}`.replace(/--/g, '-');
|
||||||
}
|
}
|
||||||
return localName;
|
return localName;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
272
mock/Menu.ts
272
mock/Menu.ts
|
|
@ -1,107 +1,231 @@
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
export const menus = [
|
||||||
const menus = [
|
|
||||||
{
|
{
|
||||||
id: '1',
|
"id": "8a8eaa657d27414e017d2861fe7a0038",
|
||||||
path: '/app',
|
"pid": "0",
|
||||||
name: '应用开发',
|
"name": "首页",
|
||||||
title: '应用开发',
|
"url": "/portal",
|
||||||
icon: 'icon-appstore',
|
"order": 0,
|
||||||
type: 'native',
|
"level": 1,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-home1"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '2',
|
"id": "ff8081817dbc0fd3017dbcc8d3140006",
|
||||||
path: '/email',
|
"pid": "0",
|
||||||
name: '邮箱',
|
"name": "业务建模",
|
||||||
title: '邮箱',
|
"url": "/business",
|
||||||
icon: 'icon-check-square',
|
"order": 1,
|
||||||
type: 'native',
|
"level": 1,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-ziyingyewu"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '3',
|
"id": "8a8ea9d37f90992d017f91de2d14006a",
|
||||||
path: '/workbench',
|
"pid": "ff8081817edc7938017edc9f149c0005",
|
||||||
name: '工作台',
|
"name": "组织管理",
|
||||||
title: '工作台',
|
"url": "/idm/orgManagement",
|
||||||
icon: 'icon-laptop',
|
"order": 1,
|
||||||
type: 'native',
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-zuzhiqunzu"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '4',
|
"id": "ff8081817dbc0fd3017dbcc976a70008",
|
||||||
path: '/idm/tenantManagement',
|
"pid": "ff8081817dbc0fd3017dbcc8d3140006",
|
||||||
name: '租户管理',
|
"name": "业务建模",
|
||||||
title: '租户管理',
|
"url": "/businessModeling",
|
||||||
icon: 'icon-laptop',
|
"order": 1,
|
||||||
type: 'native',
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-xinwaizongyewu"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '5',
|
"id": "8a8eaa5f7e0ac819017e23fde976005f",
|
||||||
path: '/idm/orgManagement',
|
"pid": "8a8eaa5f7e0ac819017e23fbfba6005d",
|
||||||
name: '组织管理',
|
"name": "实例管理",
|
||||||
title: '组织管理',
|
"url": "/operation/instanceManage",
|
||||||
icon: 'icon-laptop',
|
"order": 1,
|
||||||
type: 'native',
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-changjingguanli"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '6',
|
"id": "8a8eaaad7e437e41017e700e746d012a",
|
||||||
path: '/idm/posiManagement',
|
"pid": "8a8eaaad7e437e41017e700d47960128",
|
||||||
name: '岗位管理',
|
"name": "报告导出",
|
||||||
title: '岗位管理',
|
"url": "/library/palReport",
|
||||||
icon: 'icon-laptop',
|
"order": 1,
|
||||||
type: 'native',
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-export"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '7',
|
"id": "ff8081817edc7938017edc9f149c0005",
|
||||||
path: '/idm/groupManagement',
|
"pid": "0",
|
||||||
name: '群组管理',
|
"name": "基础数据",
|
||||||
title: '群组管理',
|
"url": "/",
|
||||||
icon: 'icon-laptop',
|
"order": 2,
|
||||||
type: 'native',
|
"level": 1,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-changyongtubiao-mianxing-21"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '8',
|
"id": "ff8081817edc7938017edca3ec300013",
|
||||||
path: '/idm/posiGroupManagement',
|
"pid": "8a8eaa5f7e0ac819017e23fbfba6005d",
|
||||||
name: '岗位组管理',
|
"name": "审计日志",
|
||||||
title: '岗位组管理',
|
"url": "/idm/logManagement?appNo=Bpmn",
|
||||||
icon: 'icon-laptop',
|
"order": 2,
|
||||||
type: 'native',
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-toggle-right"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '9',
|
"id": "ff8081817edc7938017edca20e04000b",
|
||||||
path: '/idm/roleManagement',
|
"pid": "ff8081817edc7938017edc9f149c0005",
|
||||||
name: '角色管理',
|
"name": "岗位管理",
|
||||||
title: '角色管理',
|
"url": "/idm/posiManagement",
|
||||||
icon: 'icon-laptop',
|
"order": 2,
|
||||||
type: 'native',
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-changyongtubiao-mianxing-32"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '10',
|
"id": "ff8081817edc7938017edca4ef130016",
|
||||||
path: '/idm/appManagement',
|
"pid": "ff8081817dbc0fd3017dbcc8d3140006",
|
||||||
name: '应用管理',
|
"name": "字典管理",
|
||||||
title: '应用管理',
|
"url": "/idm/dictionaryManagement",
|
||||||
icon: 'icon-laptop',
|
"order": 2,
|
||||||
type: 'native',
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-zitibiaoti"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '11',
|
"id": "8a8eaaad7e437e41017e700fea1c012c",
|
||||||
path: '/idm/resourceManagement',
|
"pid": "8a8eaaad7e437e41017e700d47960128",
|
||||||
name: '资源管理',
|
"name": "模板设置",
|
||||||
title: '资源管理',
|
"url": "/library/reportSetting",
|
||||||
icon: 'icon-laptop',
|
"order": 2,
|
||||||
type: 'native',
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-radius-setting"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '12',
|
"id": "8a8eaaad7e437e41017e700d47960128",
|
||||||
path: '/idm/resGroupManagement',
|
"pid": "0",
|
||||||
name: '资源组管理',
|
"name": "资产库",
|
||||||
title: '资源组管理',
|
"url": "/library",
|
||||||
icon: 'icon-laptop',
|
"order": 3,
|
||||||
type: 'native',
|
"level": 1,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-codelibrary"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "ff8081817edc7938017edca27471000d",
|
||||||
|
"pid": "ff8081817edc7938017edc9f149c0005",
|
||||||
|
"name": "岗位组管理",
|
||||||
|
"url": "/idm/posiGroupManagement",
|
||||||
|
"order": 3,
|
||||||
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-changyongtubiao-mianxing-32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8a8eaaad7e437e41017e8b1c5cff01b7",
|
||||||
|
"pid": "ff8081817dbc0fd3017dbcc8d3140006",
|
||||||
|
"name": "模型运维",
|
||||||
|
"url": "/business/modelManage",
|
||||||
|
"order": 3,
|
||||||
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-yuanquyunwei"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8a8eaa5f7e0ac819017e23fbfba6005d",
|
||||||
|
"pid": "0",
|
||||||
|
"name": "运维管理",
|
||||||
|
"url": "/operation",
|
||||||
|
"order": 4,
|
||||||
|
"level": 1,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-yuanquyunwei"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8a8eaa5f7e958a35017e95b142d00012",
|
||||||
|
"pid": "ff8081817dbc0fd3017dbcc8d3140006",
|
||||||
|
"name": "一键部署",
|
||||||
|
"url": "/business/deploy",
|
||||||
|
"order": 4,
|
||||||
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-deploymentunit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ff8081817edc7938017edca37d560011",
|
||||||
|
"pid": "ff8081817edc7938017edc9f149c0005",
|
||||||
|
"name": "角色管理",
|
||||||
|
"url": "/idm/roleManagement?appNo=Bpmn",
|
||||||
|
"order": 4,
|
||||||
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-changyongtubiao-mianxing-32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "ff8081817edc7938017edca2de7d000f",
|
||||||
|
"pid": "ff8081817edc7938017edc9f149c0005",
|
||||||
|
"name": "群组管理",
|
||||||
|
"url": "/idm/groupManagement",
|
||||||
|
"order": 5,
|
||||||
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-changyongtubiao-mianxing-32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8a8ea9097ffce95d017ffdaa1bfe0048",
|
||||||
|
"pid": "ff8081817dbc0fd3017dbcc8d3140006",
|
||||||
|
"name": "消息模板",
|
||||||
|
"url": "/msgTemplate",
|
||||||
|
"order": 5,
|
||||||
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-message"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "8a8ea8688016bfd701801800bf6700b3",
|
||||||
|
"pid": "ff8081817dbc0fd3017dbcc8d3140006",
|
||||||
|
"name": "连接配置",
|
||||||
|
"url": "/connectConfig",
|
||||||
|
"order": 99999,
|
||||||
|
"level": 2,
|
||||||
|
"iconType": "FONT",
|
||||||
|
"iconStyle": "{}",
|
||||||
|
"iconContent": "icon-fencengpeizhi"
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
// 支持值为 Object 和 Array
|
// 支持值为 Object 和 Array
|
||||||
'GET /gateway/idm/api/menus': {
|
'GET /gateway/idm/api/menus': {
|
||||||
|
success:true,
|
||||||
code: 0,
|
code: 0,
|
||||||
message: '成功',
|
message: '成功',
|
||||||
data: menus,
|
data: menus,
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,13 @@ class MenuService extends BasicService {
|
||||||
}
|
}
|
||||||
|
|
||||||
getAccountMenu = async () => {
|
getAccountMenu = async () => {
|
||||||
return this.get(
|
return this.get(`/gateway/idm/api/menus`)
|
||||||
`/gateway/idm/api/account/menus/${config.get('/app/code')}`,
|
// return new Promise((resolve, reject)=>{
|
||||||
);
|
//
|
||||||
|
// })
|
||||||
|
// return this.get(
|
||||||
|
// `/gateway/idm/api/account/menus/${config.get('/app/code')}`,
|
||||||
|
// );
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
export default {
|
export default {
|
||||||
$meta: 'This file configures the plot device.',
|
$meta: 'This file configures the plot device.',
|
||||||
projectName: 'Casic-portal',
|
projectName: 'Demo-Portal',
|
||||||
domains: {},
|
domains: {},
|
||||||
app: {
|
app: {
|
||||||
code: 'slave',
|
code: 'slave',
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,6 @@
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
flex: 0 0 auto;
|
flex: 0 0 auto;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
img {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
.content {
|
||||||
|
|
|
||||||
|
|
@ -289,7 +289,6 @@
|
||||||
height: calc(100% - 20px);
|
height: calc(100% - 20px);
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background: white;
|
background: white;
|
||||||
border-radius: 5px;
|
|
||||||
box-shadow: @shadow-1-down;
|
box-shadow: @shadow-1-down;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,78 +1,59 @@
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import _ from 'lodash';
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { history } from "umi";
|
||||||
import { history } from 'umi';
|
import { observer } from "mobx-react";
|
||||||
import ProLayout, { MenuDataItem, WaterMark } from '@ant-design/pro-layout';
|
import ProLayout, { MenuDataItem, WaterMark } from "@ant-design/pro-layout";
|
||||||
import styles from './index.less';
|
import { IAction } from "@/api/Types";
|
||||||
import { IAction } from '@/api/Types';
|
import { urlToList } from "@/utils/pathTools";
|
||||||
import { urlToList } from '@/utils/pathTools';
|
import { AppStore } from "@/store/AppStore";
|
||||||
import { AppStore } from '@/store/AppStore';
|
import { useMenu } from "./useMenu";
|
||||||
import { useMenu } from './useMenu';
|
import { Session, Storage, Text, Util } from "@/utils";
|
||||||
import { observer } from 'mobx-react';
|
import { buildIcon, SearchBar } from "@/lib";
|
||||||
import { Text, Util, Storage, Session } from '@/utils';
|
import defaultLogo from "@/assets/logo.svg";
|
||||||
import { buildIcon, SearchBar } from '@/lib';
|
import { CaretDownOutlined, CaretRightOutlined, UnorderedListOutlined } from "@ant-design/icons";
|
||||||
import defaultLogo from '@/assets/logo.svg';
|
import { MenuExpander, MenuFooter } from "@/layouts/BaseLayout/Sider";
|
||||||
import {
|
import Header from "@/layouts/BaseLayout/Header";
|
||||||
UnorderedListOutlined,
|
import { getOpenKeysFromSelectedMenu } from "@/layouts/BaseLayout/utils/utils";
|
||||||
CaretDownOutlined,
|
import { Breadcrumb, Button, ConfigProvider, Space, Tooltip } from "antd";
|
||||||
CaretRightOutlined,
|
import classNames from "classnames";
|
||||||
} from '@ant-design/icons';
|
import { baseLayoutStore as store } from "./Store";
|
||||||
import {
|
import { Base64 } from "js-base64";
|
||||||
MenuFooter,
|
import { HTML_ID_LAYOUT_CONTENT } from "@/constant/ID";
|
||||||
MenuExpander,
|
import styles from "./index.less";
|
||||||
} from '@/layouts/BaseLayout/Sider';
|
|
||||||
import Header from '@/layouts/BaseLayout/Header';
|
|
||||||
import { getOpenKeysFromSelectedMenu } from '@/layouts/BaseLayout/utils/utils';
|
|
||||||
import { Breadcrumb, Button, ConfigProvider, Tooltip, Space } from 'antd';
|
|
||||||
import API from '@/api';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { baseLayoutStore as store } from './Store';
|
|
||||||
import { Base64 } from 'js-base64';
|
|
||||||
import { HTML_ID_LAYOUT_CONTENT } from '@/constant/ID';
|
|
||||||
|
|
||||||
const BaseLayout = observer(({ children, location }: any) => {
|
const BaseLayout = observer(({ children, location }: any) => {
|
||||||
const { pathname, query } = location;
|
const { pathname, query } = location;
|
||||||
|
const session: any = Session.get();
|
||||||
const [collapsed, setCollapse] = useState(false);
|
const [collapsed, setCollapse] = useState(false);
|
||||||
const [selectMenuKey, setSelectMenuKey] = useState([] as Array<string>);
|
const [selectMenuKey, setSelectMenuKey] = useState([] as Array<string>);
|
||||||
const [openMenuKey, setOpenMenuKey] = useState([] as Array<string>);
|
const [openMenuKey, setOpenMenuKey] = useState([] as Array<string>);
|
||||||
const [filterMenuData, setFilterMenuData] = useState<any[]>([])
|
const [filterMenuData, setFilterMenuData] = useState<any[]>([]);
|
||||||
const session: any = Session.get();
|
|
||||||
|
|
||||||
const [
|
|
||||||
menuData,
|
|
||||||
breadCrumbMap,
|
|
||||||
defaultCollapseMenus,
|
|
||||||
defaultSelectMenus,
|
|
||||||
originalMenu,
|
|
||||||
filterMenu,
|
|
||||||
] = useMenu();
|
|
||||||
|
|
||||||
const [breadCrumbs, setBreadCrumbs] = useState<any[]>([]);
|
const [breadCrumbs, setBreadCrumbs] = useState<any[]>([]);
|
||||||
const expandMenuRef = useRef<any>();
|
const expandMenuRef = useRef<any>();
|
||||||
|
|
||||||
|
const [menuData, breadCrumbMap, defaultCollapseMenus, defaultSelectMenus, originalMenu, filterMenu] = useMenu();
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
ConfigProvider.config({
|
ConfigProvider.config({
|
||||||
theme: {
|
theme: {
|
||||||
primaryColor: store.primaryColor,
|
primaryColor: store.primaryColor
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
}, [store.primaryColor]);
|
}, [store.primaryColor]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCollapse(false)
|
setCollapse(false);
|
||||||
}, [store.layout])
|
}, [store.layout]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (_.isEmpty(menuData) || _.isEmpty(breadCrumbMap)) {
|
if (_.isEmpty(menuData) || _.isEmpty(breadCrumbMap)) return;
|
||||||
return;
|
setOpenMenuKey(store.layout === "side" ? defaultCollapseMenus : []);
|
||||||
}
|
|
||||||
setOpenMenuKey(store.layout === 'side' ? defaultCollapseMenus : []);
|
|
||||||
setSelectMenuKey(defaultSelectMenus);
|
setSelectMenuKey(defaultSelectMenus);
|
||||||
setFilterMenuData(menuData)
|
setFilterMenuData(menuData);
|
||||||
}, [menuData, breadCrumbMap, defaultCollapseMenus, defaultSelectMenus, store.layout]);
|
}, [menuData, breadCrumbMap, defaultCollapseMenus, defaultSelectMenus, store.layout]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!collapsed) {
|
if (!collapsed) {
|
||||||
|
//菜单数据中父子级关系必须有pid/id
|
||||||
const openKeys = getOpenKeysFromSelectedMenu(originalMenu, selectMenuKey);
|
const openKeys = getOpenKeysFromSelectedMenu(originalMenu, selectMenuKey);
|
||||||
if (!_.isEmpty(openKeys)) {
|
if (!_.isEmpty(openKeys)) {
|
||||||
setOpenMenuKey(openKeys);
|
setOpenMenuKey(openKeys);
|
||||||
|
|
@ -81,46 +62,39 @@ const BaseLayout = observer(({ children, location }: any) => {
|
||||||
}, [collapsed]);
|
}, [collapsed]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (_.isEmpty(breadCrumbMap)) {
|
if (_.isEmpty(breadCrumbMap)) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
const paths = urlToList(pathname);
|
const paths = urlToList(pathname);
|
||||||
let extraBreadcrumbs = _.reduce(
|
let extraBreadcrumbs = _.reduce(paths, (ret: any[], path: string) => {
|
||||||
paths,
|
|
||||||
(ret: any[], path: string) => {
|
|
||||||
const menu = breadCrumbMap[path];
|
const menu = breadCrumbMap[path];
|
||||||
if (!_.isEmpty(menu)) {
|
if (!_.isEmpty(menu)) {
|
||||||
ret.push({ ...menu });
|
ret.push({ ...menu });
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
},
|
},
|
||||||
[],
|
[]
|
||||||
);
|
);
|
||||||
const home = breadCrumbMap['/'] || breadCrumbMap['/home'];
|
const home = breadCrumbMap["/"] || breadCrumbMap["/home"];
|
||||||
const breadcrumbs = _.isEmpty(home)
|
const breadcrumbs = _.isEmpty(home)
|
||||||
? extraBreadcrumbs
|
? extraBreadcrumbs
|
||||||
: [home].concat(
|
: [home].concat(
|
||||||
_.filter(extraBreadcrumbs, (data: any) => data.key !== home.key),
|
_.filter(extraBreadcrumbs, (data: any) => data.key !== home.key)
|
||||||
);
|
);
|
||||||
setBreadCrumbs(breadcrumbs);
|
setBreadCrumbs(breadcrumbs);
|
||||||
}, [pathname, breadCrumbMap]);
|
}, [pathname, breadCrumbMap]);
|
||||||
|
|
||||||
const onMenuOpen = useCallback((openKeys: string[]) => {
|
const onMenuOpen = useCallback((openKeys: string[]) => {
|
||||||
setOpenMenuKey(openKeys);
|
setOpenMenuKey(openKeys);
|
||||||
Storage.session.set('OPEN_MENU_KEY', openKeys)
|
Storage.session.set("OPEN_MENU_KEY", openKeys);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const onMenuSelect = useCallback((menu: any) => {
|
const onMenuSelect = useCallback((menu: any) => {
|
||||||
if (_.isEmpty(menu)) {
|
if (_.isEmpty(menu)) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(menu)) {
|
if (Array.isArray(menu)) {
|
||||||
setSelectMenuKey(menu);
|
setSelectMenuKey(menu);
|
||||||
} else {
|
} else {
|
||||||
setSelectMenuKey([menu.key]);
|
setSelectMenuKey([menu.key]);
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
setOpenMenuKey((openMenuKey) => [].concat(openMenuKey).concat(menu.keyPath),
|
setOpenMenuKey((openMenuKey) => [].concat(openMenuKey).concat(menu.keyPath)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -134,37 +108,35 @@ const BaseLayout = observer(({ children, location }: any) => {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onMenuSelect({
|
onMenuSelect({
|
||||||
key: item.id,
|
key: item.id,
|
||||||
keyPath: [item.id, item.pid],
|
keyPath: [item.id, item.pid]
|
||||||
});
|
});
|
||||||
history.push(item.path);
|
history.push(item.path);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<a>
|
<a>{buildIcon("", item.icon)} {item.name}</a>
|
||||||
{buildIcon('', item.icon)} {item.name}
|
|
||||||
</a>
|
|
||||||
</Breadcrumb.Item>
|
</Breadcrumb.Item>
|
||||||
))}
|
))}
|
||||||
</Breadcrumb>
|
</Breadcrumb>
|
||||||
)
|
);
|
||||||
}, [breadCrumbs])
|
}, [breadCrumbs]);
|
||||||
|
|
||||||
const classes = useMemo(() => {
|
const classes = useMemo(() => {
|
||||||
return classNames({
|
return classNames({
|
||||||
[styles.root]: true,
|
[styles.root]: true,
|
||||||
[styles[store.navTheme]]: true,
|
[styles[store.navTheme]]: true
|
||||||
})
|
});
|
||||||
}, [store.navTheme])
|
}, [store.navTheme]);
|
||||||
|
|
||||||
const onMenuSearch = useCallback((key: any) => {
|
const onMenuSearch = useCallback((key: any) => {
|
||||||
if (_.isEmpty(key)) {
|
if (_.isEmpty(key)) {
|
||||||
setFilterMenuData(menuData);
|
setFilterMenuData(menuData);
|
||||||
} else {
|
} else {
|
||||||
setFilterMenuData(filterMenu(originalMenu, key))
|
setFilterMenuData(filterMenu(originalMenu, key));
|
||||||
}
|
}
|
||||||
}, [menuData])
|
}, [menuData]);
|
||||||
|
|
||||||
// 内嵌模式直接渲染子路由
|
// 内嵌模式直接渲染子路由
|
||||||
if (query?.embeded && query?.embeded == 'T') {
|
if (query?.embeded && query?.embeded == "T") {
|
||||||
return <>{children}</>;
|
return <>{children}</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,35 +144,28 @@ const BaseLayout = observer(({ children, location }: any) => {
|
||||||
// const appName = API.SettingService.getSystemParam('appName') || '管理系统';
|
// const appName = API.SettingService.getSystemParam('appName') || '管理系统';
|
||||||
// const globalWaterMark = API.SettingService.getSystemParam('globalWaterMark') || 'F';
|
// const globalWaterMark = API.SettingService.getSystemParam('globalWaterMark') || 'F';
|
||||||
const logo = defaultLogo;
|
const logo = defaultLogo;
|
||||||
const appName = '管理系统';
|
const appName = "管理系统";
|
||||||
const globalWaterMark = 'F';
|
const globalWaterMark = "F";
|
||||||
|
|
||||||
let layout = (
|
let layout = (
|
||||||
<div
|
<div className={classes}>
|
||||||
className={classes}
|
|
||||||
style={{
|
|
||||||
width: '100vw',
|
|
||||||
height: '100vh',
|
|
||||||
overflow: 'hidden',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ProLayout
|
<ProLayout
|
||||||
className='__layout_main__'
|
className="__layout_main__"
|
||||||
disableMobile
|
disableMobile
|
||||||
fixedHeader
|
fixedHeader
|
||||||
fixSiderbar
|
fixSiderbar
|
||||||
location={location}
|
location={location}
|
||||||
layout={store.layout}
|
layout={store.layout}
|
||||||
splitMenus={store.layout === 'mix' && store.splitMenus}
|
splitMenus={store.layout === "mix" && store.splitMenus}
|
||||||
navTheme={store.layout === 'top' ? 'dark' : 'light'}
|
navTheme={store.layout === "top" ? "dark" : "light"}
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
iconfontUrl={`${Util.getPublicPath()}css/iconfont/iconfont.js`}
|
iconfontUrl={`${Util.getPublicPath()}css/iconfont/iconfont.js`}
|
||||||
title={Text.toShortText(appName, store.layout === 'side' ? 7 : 11)}
|
title={Text.toShortText(appName, store.layout === "side" ? 7 : 11)}
|
||||||
logo={<span onClick={() => history.push('/')}><img src={logo} /></span>}
|
logo={<span onClick={() => history.push("/")}><img src={logo} alt=""/></span>}
|
||||||
collapsed={collapsed}
|
collapsed={collapsed}
|
||||||
style={{ transition: 'all 0.5s ease 0s' }}
|
style={{ transition: "all 0.5s ease 0s" }}
|
||||||
headerContentRender={() =>
|
headerContentRender={() =>
|
||||||
(store.layout === 'side' || (store.layout === 'mix' && !store.splitMenus)) ? (
|
(store.layout === "side" || (store.layout === "mix" && !store.splitMenus)) ? (
|
||||||
<div className={styles.headContent}>
|
<div className={styles.headContent}>
|
||||||
{breadCrumbComp}
|
{breadCrumbComp}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -211,51 +176,51 @@ const BaseLayout = observer(({ children, location }: any) => {
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
const external = /^https?:\/\//.test(item.path || '');
|
const external = /^https?:\/\//.test(item.path || "");
|
||||||
Storage.session.set('ACTIVE_MENU_KEY', item.key)
|
Storage.session.set("ACTIVE_MENU_KEY", item.key);
|
||||||
if (external) {
|
if (external) {
|
||||||
const embedUrl = Base64.encode(item.path || '', true);
|
const embedUrl = Base64.encode(item.path || "", true);
|
||||||
history.push(`/external?_q=${embedUrl}`);
|
history.push(`/external?_q=${embedUrl}`);
|
||||||
} else {
|
} else {
|
||||||
history.push(item.path || '/');
|
history.push(item.path || "/");
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{typeof item.icon === 'string'
|
{typeof item.icon === "string"
|
||||||
? buildIcon('FONT', item.icon)
|
? buildIcon("FONT", item.icon)
|
||||||
: item.icon}{' '}
|
: item.icon}{" "}
|
||||||
<label>{item.name}</label>
|
<label>{item.name}</label>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
menuProps={{
|
menuProps={{
|
||||||
theme: 'light',
|
theme: "light",
|
||||||
selectedKeys: selectMenuKey,
|
selectedKeys: selectMenuKey,
|
||||||
openKeys: openMenuKey,
|
openKeys: openMenuKey,
|
||||||
onOpenChange: onMenuOpen,
|
onOpenChange: onMenuOpen,
|
||||||
onSelect: onMenuSelect,
|
onSelect: onMenuSelect,
|
||||||
expandIcon: (props) => {
|
expandIcon: (props) => {
|
||||||
return props.isOpen ? (
|
return props.isOpen ? (
|
||||||
<CaretDownOutlined style={{ color: '#999' }} />
|
<CaretDownOutlined style={{ color: "#999" }}/>
|
||||||
) : (
|
) : (
|
||||||
<CaretRightOutlined style={{ color: '#999' }} />
|
<CaretRightOutlined style={{ color: "#999" }}/>
|
||||||
);
|
);
|
||||||
},
|
}
|
||||||
}}
|
}}
|
||||||
menuExtraRender={() =>
|
menuExtraRender={() =>
|
||||||
store.layout === 'mix' && store.splitMenus ? null : (
|
store.layout === "mix" && store.splitMenus ? null : (
|
||||||
<div className={styles.expandButton}>
|
<div className={styles.expandButton}>
|
||||||
<Space>
|
<Space>
|
||||||
{collapsed ? null : <SearchBar fillOnSearch onSearch={onMenuSearch} size='small' placeholder='搜索功能' />}
|
{collapsed ? null : <SearchBar fillOnSearch onSearch={onMenuSearch} size="small" placeholder="搜索功能"/>}
|
||||||
<Button size='small' onClick={() => expandMenuRef.current.toggle()}>
|
<Button size="small" onClick={() => expandMenuRef.current.toggle()}>
|
||||||
<Tooltip title='查看全部'><UnorderedListOutlined /></Tooltip>
|
<Tooltip title="查看全部"><UnorderedListOutlined/></Tooltip>
|
||||||
</Button>
|
</Button>
|
||||||
</Space>
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
rightContentRender={() => (
|
rightContentRender={() => (
|
||||||
<>
|
<>
|
||||||
<Header originalMenu={originalMenu} onMenuSelect={onMenuSelect} />
|
<Header originalMenu={originalMenu} onMenuSelect={onMenuSelect}/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
collapsedButtonRender={() => (
|
collapsedButtonRender={() => (
|
||||||
|
|
@ -264,11 +229,15 @@ const BaseLayout = observer(({ children, location }: any) => {
|
||||||
onCollapse={() => setCollapse((collapsed) => !collapsed)}
|
onCollapse={() => setCollapse((collapsed) => !collapsed)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
contentStyle={{ padding: 0, margin: 0, height: 'calc(100vh - 48px)' }}
|
contentStyle={{ padding: 0, margin: 0, height: "calc(100vh - 48px)" }}
|
||||||
>
|
>
|
||||||
<div className={styles.content} id={HTML_ID_LAYOUT_CONTENT}>
|
<div className={styles.content} id={HTML_ID_LAYOUT_CONTENT}>
|
||||||
<div className={styles.main}>
|
<div className={styles.main}>
|
||||||
{globalWaterMark === 'T' ? <WaterMark content={`${session?.name}${session?.userNo || ''}`}>{children}</WaterMark> : children}
|
{
|
||||||
|
//@ts-ignore
|
||||||
|
globalWaterMark === "T" ?
|
||||||
|
<WaterMark content={`${session?.name}${session?.userNo || ""}`}>{children}</WaterMark> : children
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ProLayout>
|
</ProLayout>
|
||||||
|
|
@ -289,7 +258,7 @@ export default (props: any) => <BaseLayout {...props} />;
|
||||||
|
|
||||||
export const resetManageLayoutBreadcrumbs = (
|
export const resetManageLayoutBreadcrumbs = (
|
||||||
store: AppStore,
|
store: AppStore,
|
||||||
breadcrumbs: [],
|
breadcrumbs: []
|
||||||
) => {
|
) => {
|
||||||
if (_.isEmpty(store.breadcrumbs)) {
|
if (_.isEmpty(store.breadcrumbs)) {
|
||||||
store.setBreadcrumbs(breadcrumbs);
|
store.setBreadcrumbs(breadcrumbs);
|
||||||
|
|
@ -298,7 +267,7 @@ export const resetManageLayoutBreadcrumbs = (
|
||||||
|
|
||||||
export const resetManageLayoutTopActions = (
|
export const resetManageLayoutTopActions = (
|
||||||
store: AppStore,
|
store: AppStore,
|
||||||
actions: Array<IAction>,
|
actions: Array<IAction>
|
||||||
) => {
|
) => {
|
||||||
if (_.isEmpty(store.topActions)) {
|
if (_.isEmpty(store.topActions)) {
|
||||||
store.setTopActions(actions);
|
store.setTopActions(actions);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
// @ts-ignore
|
||||||
import type * as H from 'history';
|
import type * as H from 'history';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ export function useMenu<S extends AnyObject>() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
API.MenuService.getAccountMenu().then(({ success, data }) => {
|
API.MenuService.getAccountMenu().then(({ success, data }) => {
|
||||||
if (success) {
|
if (success) {
|
||||||
let menus = _.map(data || [], (menu: any) => ({
|
let menus = _.map(data.data || [], (menu: any) => ({
|
||||||
key: menu.id,
|
key: menu.id,
|
||||||
id: menu.id,
|
id: menu.id,
|
||||||
pid: menu.pid,
|
pid: menu.pid,
|
||||||
|
|
@ -212,7 +212,6 @@ export function useMenu<S extends AnyObject>() {
|
||||||
),
|
),
|
||||||
order: menu.order,
|
order: menu.order,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
setOriginalMenu(menus);
|
setOriginalMenu(menus);
|
||||||
const buildMenus = buildMenuData(menus);
|
const buildMenus = buildMenuData(menus);
|
||||||
setMenuData(buildMenus);
|
setMenuData(buildMenus);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import styles from './index.less';
|
import styles from "../index.less";
|
||||||
|
|
||||||
export default ({children, style = {}}: any) => {
|
export default ({ children, style = {} }: any) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={styles.root}
|
className={styles.root}
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: "100%",
|
||||||
height: '100%',
|
height: "100%",
|
||||||
...style
|
...style
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
||||||
.root {
|
|
||||||
:global {
|
|
||||||
.ant-pro-sider-logo {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.ant-layout-sider {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
.left {
|
|
||||||
flex: 0 0 auto;
|
|
||||||
}
|
|
||||||
.center {
|
|
||||||
flex: 1 1 auto;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.trigger {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
span {
|
|
||||||
color: whitesmoke;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
import * as React from 'react';
|
import * as React from "react";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { ConfigProvider } from "antd";
|
import { ConfigProvider } from "antd";
|
||||||
import { baseLayoutStore as store } from "@/layouts/BaseLayout/Store";
|
import { baseLayoutStore as store } from "@/layouts/BaseLayout/Store";
|
||||||
import styles from './index.less';
|
import styles from "../index.less";
|
||||||
|
|
||||||
export default ({ children }: any) => {
|
export default ({ children }: any) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
ConfigProvider.config({
|
ConfigProvider.config({
|
||||||
theme: {
|
theme: {
|
||||||
primaryColor: store.primaryColor,
|
primaryColor: store.primaryColor
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
}, [store.primaryColor]);
|
}, [store.primaryColor]);
|
||||||
|
|
||||||
|
|
@ -17,9 +17,9 @@ export default ({ children }: any) => {
|
||||||
<div
|
<div
|
||||||
className={styles.root}
|
className={styles.root}
|
||||||
style={{
|
style={{
|
||||||
width: '100vw',
|
width: "100%",
|
||||||
height: '100vh',
|
height: "100%",
|
||||||
overflow: 'hidden',
|
overflow: "hidden"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
||||||
|
|
@ -1,33 +1,24 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import _ from "lodash";
|
import { ConfigProvider } from "antd";
|
||||||
|
import { DndProvider } from "react-dnd";
|
||||||
|
import moment from "moment";
|
||||||
|
import { Provider } from "mobx-react";
|
||||||
|
import zhCN from "antd/lib/locale/zh_CN";
|
||||||
|
import { HTML5Backend } from "react-dnd-html5-backend";
|
||||||
|
import { connect, IRouteComponentProps, useModel } from "umi";
|
||||||
import BaseLayout from "./BaseLayout";
|
import BaseLayout from "./BaseLayout";
|
||||||
import BlankLayout from "./BlankLayout";
|
import BlankLayout from "./BlankLayout";
|
||||||
import UserLayout from "./UserLayout";
|
import UserLayout from "./UserLayout";
|
||||||
import { IRouterProps, RouterContext } from "./RouterContext";
|
import { IRouterProps, RouterContext } from "./RouterContext";
|
||||||
import { ConfigProvider } from "antd";
|
|
||||||
import { DndProvider } from "react-dnd";
|
|
||||||
import { HTML5Backend } from "react-dnd-html5-backend";
|
|
||||||
import { layoutConfig } from "@/layouts/config";
|
import { layoutConfig } from "@/layouts/config";
|
||||||
import { connect, IRouteComponentProps, useModel } from "umi";
|
import stores from "@/store";
|
||||||
import { Provider } from "mobx-react";
|
|
||||||
import stores, { baseLayoutStore as store } from "@/store";
|
|
||||||
import zhCN from "antd/lib/locale/zh_CN";
|
|
||||||
import moment from "moment";
|
|
||||||
import API from "@/api";
|
|
||||||
import "moment/locale/zh-cn";
|
import "moment/locale/zh-cn";
|
||||||
import "antd/dist/antd.variable.min.css";
|
import "antd/dist/antd.variable.min.css";
|
||||||
|
|
||||||
|
|
||||||
moment.locale("zh-cn");
|
moment.locale("zh-cn");
|
||||||
|
|
||||||
const Layout = ({
|
const Layout = ({ children, location, route, history, match }: IRouteComponentProps) => {
|
||||||
children,
|
|
||||||
location,
|
|
||||||
route,
|
|
||||||
history,
|
|
||||||
match
|
|
||||||
}: IRouteComponentProps) => {
|
|
||||||
const props = { children, location, route, history, match };
|
const props = { children, location, route, history, match };
|
||||||
const { query } = location;
|
const { query } = location;
|
||||||
const embed = {
|
const embed = {
|
||||||
|
|
@ -36,7 +27,6 @@ const Layout = ({
|
||||||
hideFoot: !!(query.hideFoot && query.hideFoot === "true"),
|
hideFoot: !!(query.hideFoot && query.hideFoot === "true"),
|
||||||
hideAll: !!(query.hideAll && query.hideAll === "true")
|
hideAll: !!(query.hideAll && query.hideAll === "true")
|
||||||
};
|
};
|
||||||
|
|
||||||
const masterProps = useModel("@@qiankunStateFromMaster");
|
const masterProps = useModel("@@qiankunStateFromMaster");
|
||||||
let containerStyle: React.CSSProperties = {};
|
let containerStyle: React.CSSProperties = {};
|
||||||
if (masterProps?.hideAll) {
|
if (masterProps?.hideAll) {
|
||||||
|
|
@ -50,7 +40,6 @@ const Layout = ({
|
||||||
// API.SettingService.initSystemParam();
|
// API.SettingService.initSystemParam();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
let layout;
|
let layout;
|
||||||
if (embed.hideAll) {
|
if (embed.hideAll) {
|
||||||
layout = <BlankLayout {...props} style={containerStyle}/>;
|
layout = <BlankLayout {...props} style={containerStyle}/>;
|
||||||
|
|
|
||||||
|
|
@ -4,5 +4,5 @@ import { Redirect, useModel } from 'umi';
|
||||||
export default () => {
|
export default () => {
|
||||||
const masterProps = useModel('@@qiankunStateFromMaster');
|
const masterProps = useModel('@@qiankunStateFromMaster');
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return <Redirect to={`${masterProps?.route || '/sample'}`} />;
|
return <Redirect to={`${masterProps?.route || '/'}`} />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ export class AppStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
menu: IMenuData = {} as IMenuData;
|
menu: Partial<IMenuData> = {} ;
|
||||||
|
|
||||||
@observable
|
@observable
|
||||||
menus: IMenuData[] = [];
|
menus: IMenuData[] = [];
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue