@zat-design/sisyphus-react 3.13.24-beta.1 → 3.14.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/es/ProLayout/components/Layout/Menu/FoldMenu/index.js +8 -4
  2. package/es/ProLayout/components/Layout/Menu/OpenMenu/index.js +39 -28
  3. package/es/ProLayout/components/TabsManager/components/TabContextMenu.d.ts +7 -0
  4. package/es/ProLayout/components/TabsManager/components/TabContextMenu.js +96 -0
  5. package/es/ProLayout/components/TabsManager/components/TabItem.d.ts +26 -0
  6. package/es/ProLayout/components/TabsManager/components/TabItem.js +61 -0
  7. package/es/ProLayout/components/TabsManager/components/TabsContext.d.ts +6 -0
  8. package/es/ProLayout/components/TabsManager/components/TabsContext.js +5 -0
  9. package/es/ProLayout/components/TabsManager/hooks/useActiveTab.d.ts +6 -0
  10. package/es/ProLayout/components/TabsManager/hooks/useActiveTab.js +14 -0
  11. package/es/ProLayout/components/TabsManager/hooks/useProLayoutTabs.d.ts +18 -0
  12. package/es/ProLayout/components/TabsManager/hooks/useProLayoutTabs.js +26 -0
  13. package/es/ProLayout/components/TabsManager/hooks/useTabsCache.d.ts +31 -0
  14. package/es/ProLayout/components/TabsManager/hooks/useTabsCache.js +93 -0
  15. package/es/ProLayout/components/TabsManager/hooks/useTabsState.d.ts +5 -0
  16. package/es/ProLayout/components/TabsManager/hooks/useTabsState.js +357 -0
  17. package/es/ProLayout/components/TabsManager/index.d.ts +8 -0
  18. package/es/ProLayout/components/TabsManager/index.js +171 -0
  19. package/es/ProLayout/components/TabsManager/propTypes.d.ts +74 -0
  20. package/es/ProLayout/components/TabsManager/propTypes.js +16 -0
  21. package/es/ProLayout/components/TabsManager/style/index.less +179 -0
  22. package/es/ProLayout/components/TabsManager/utils/index.d.ts +38 -0
  23. package/es/ProLayout/components/TabsManager/utils/index.js +106 -0
  24. package/es/ProLayout/index.d.ts +10 -4
  25. package/es/ProLayout/index.js +82 -9
  26. package/es/ProLayout/propTypes.d.ts +139 -1
  27. package/es/ProLayout/propTypes.js +37 -1
  28. package/es/ProLayout/utils/index.js +8 -5
  29. package/es/index.d.ts +2 -1
  30. package/es/index.js +1 -1
  31. package/lib/ProLayout/components/Layout/Menu/FoldMenu/index.js +8 -4
  32. package/lib/ProLayout/components/Layout/Menu/OpenMenu/index.js +39 -28
  33. package/lib/ProLayout/components/TabsManager/components/TabContextMenu.d.ts +7 -0
  34. package/lib/ProLayout/components/TabsManager/components/TabContextMenu.js +103 -0
  35. package/lib/ProLayout/components/TabsManager/components/TabItem.d.ts +26 -0
  36. package/lib/ProLayout/components/TabsManager/components/TabItem.js +67 -0
  37. package/lib/ProLayout/components/TabsManager/components/TabsContext.d.ts +6 -0
  38. package/lib/ProLayout/components/TabsManager/components/TabsContext.js +11 -0
  39. package/lib/ProLayout/components/TabsManager/hooks/useActiveTab.d.ts +6 -0
  40. package/lib/ProLayout/components/TabsManager/hooks/useActiveTab.js +20 -0
  41. package/lib/ProLayout/components/TabsManager/hooks/useProLayoutTabs.d.ts +18 -0
  42. package/lib/ProLayout/components/TabsManager/hooks/useProLayoutTabs.js +31 -0
  43. package/lib/ProLayout/components/TabsManager/hooks/useTabsCache.d.ts +31 -0
  44. package/lib/ProLayout/components/TabsManager/hooks/useTabsCache.js +101 -0
  45. package/lib/ProLayout/components/TabsManager/hooks/useTabsState.d.ts +5 -0
  46. package/lib/ProLayout/components/TabsManager/hooks/useTabsState.js +364 -0
  47. package/lib/ProLayout/components/TabsManager/index.d.ts +8 -0
  48. package/lib/ProLayout/components/TabsManager/index.js +175 -0
  49. package/lib/ProLayout/components/TabsManager/propTypes.d.ts +74 -0
  50. package/lib/ProLayout/components/TabsManager/propTypes.js +22 -0
  51. package/lib/ProLayout/components/TabsManager/style/index.less +179 -0
  52. package/lib/ProLayout/components/TabsManager/utils/index.d.ts +38 -0
  53. package/lib/ProLayout/components/TabsManager/utils/index.js +119 -0
  54. package/lib/ProLayout/index.d.ts +10 -4
  55. package/lib/ProLayout/index.js +94 -8
  56. package/lib/ProLayout/propTypes.d.ts +139 -1
  57. package/lib/ProLayout/propTypes.js +40 -1
  58. package/lib/ProLayout/utils/index.js +8 -5
  59. package/lib/index.d.ts +2 -1
  60. package/lib/index.js +9 -2
  61. package/package.json +1 -1
@@ -0,0 +1,179 @@
1
+ .pro-layout-tabs {
2
+ --pro-layout-tabs-primary: var(--ant-primary-color, #1677ff);
3
+ --pro-layout-tabs-active-bg: var(--ant-color-success, #00b578);
4
+ --pro-layout-tabs-text-color: var(--ant-color-text, #1f1f1f);
5
+
6
+ display: flex;
7
+ flex-direction: column;
8
+ height: 100%;
9
+
10
+ &-header {
11
+ display: flex;
12
+ align-items: center;
13
+ min-height: 48px;
14
+ padding: 12px 0;
15
+ border-bottom: none;
16
+
17
+ .pro-layout-tab-list {
18
+ display: flex;
19
+ flex: 1;
20
+ gap: 12px;
21
+ overflow-x: auto;
22
+ overflow-y: hidden;
23
+
24
+ &::-webkit-scrollbar {
25
+ height: 3px;
26
+ }
27
+
28
+ &::-webkit-scrollbar-track {
29
+ background: transparent;
30
+ }
31
+
32
+ &::-webkit-scrollbar-thumb {
33
+ background: #d9d9d9;
34
+ border-radius: 3px;
35
+
36
+ &:hover {
37
+ background: #bfbfbf;
38
+ }
39
+ }
40
+ }
41
+
42
+ &-extra {
43
+ flex-shrink: 0;
44
+ padding: 0 16px;
45
+ }
46
+ }
47
+
48
+ &-content {
49
+ .tab-pane {
50
+ &.hidden {
51
+ display: none;
52
+ }
53
+ }
54
+ }
55
+ }
56
+
57
+ .pro-layout-tab-item {
58
+ position: relative;
59
+ display: flex;
60
+ flex-shrink: 0;
61
+ align-items: center;
62
+ min-height: 36px;
63
+ padding: 0;
64
+ background: #ffffff;
65
+ border: 1px solid transparent;
66
+ border-radius: 8px;
67
+ cursor: pointer;
68
+ transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
69
+ user-select: none;
70
+
71
+ &:hover {
72
+ background: #ffffff;
73
+ border-color: rgba(0, 0, 0, 0.06);
74
+ }
75
+
76
+ &.active {
77
+ z-index: 2;
78
+ background: var(--zaui-primary);
79
+ border-color: transparent;
80
+
81
+ &::before {
82
+ display: none;
83
+ }
84
+ }
85
+
86
+ .pro-layout-tab-content {
87
+ display: flex;
88
+ align-items: center;
89
+ min-width: 100px;
90
+ padding: 6px 12px;
91
+ text-align: left;
92
+
93
+ .pro-layout-tab-icon {
94
+ display: flex;
95
+ flex-shrink: 0;
96
+ align-items: center;
97
+ margin-right: 8px;
98
+
99
+ .iconfont {
100
+ color: inherit;
101
+ font-size: 14px;
102
+ }
103
+
104
+ img {
105
+ width: 16px;
106
+ height: 16px;
107
+ object-fit: contain;
108
+ }
109
+ }
110
+
111
+ .pro-layout-tab-title {
112
+ flex: 1;
113
+ overflow: hidden;
114
+ color: var(--pro-layout-tabs-text-color);
115
+ font-weight: 500;
116
+ font-size: 14px;
117
+ white-space: nowrap;
118
+ text-overflow: ellipsis;
119
+ transition: color 0.3s;
120
+ }
121
+
122
+ .pro-layout-tab-close {
123
+ display: flex;
124
+ flex-shrink: 0;
125
+ align-items: center;
126
+ justify-content: center;
127
+ margin-left: 8px;
128
+ padding: 3px;
129
+ color: rgba(0, 0, 0, 0.45);
130
+ border-radius: 4px;
131
+ opacity: 0.7;
132
+ transition: all 0.3s;
133
+
134
+ &:hover {
135
+ color: #ff4d4f;
136
+ background: rgba(255, 77, 79, 0.15);
137
+ opacity: 1;
138
+ }
139
+ }
140
+ }
141
+
142
+ &.active .pro-layout-tab-content {
143
+ .pro-layout-tab-title {
144
+ color: #ffffff;
145
+ font-weight: 600;
146
+ }
147
+
148
+ .pro-layout-tab-icon {
149
+ .iconfont {
150
+ color: #ffffff;
151
+ }
152
+ }
153
+
154
+ .pro-layout-tab-close {
155
+ color: #ffffff;
156
+
157
+ &:hover {
158
+ background: rgba(255, 255, 255, 0.2);
159
+ }
160
+ }
161
+ }
162
+ }
163
+
164
+ .pro-layout-dark .pro-layout-tabs {
165
+ --pro-layout-tabs-text-color: rgba(255, 255, 255, 0.85);
166
+ }
167
+
168
+ // 响应式适配
169
+ @media (max-width: 768px) {
170
+ .pro-layout-tab-item {
171
+ .pro-layout-tab-content {
172
+ padding: 6px 8px;
173
+
174
+ .pro-layout-tab-title {
175
+ max-width: 80px;
176
+ }
177
+ }
178
+ }
179
+ }
@@ -0,0 +1,38 @@
1
+ import { TabItem, MenusType } from '../../../propTypes';
2
+ /**
3
+ * 根据菜单项生成TabItem
4
+ */
5
+ export declare const createTabFromMenu: (menuItem: MenusType, index?: number) => TabItem;
6
+ /**
7
+ * 生成唯一的tab ID
8
+ */
9
+ export declare const generateTabId: (menuItem: MenusType, existingIds: string[]) => string;
10
+ /**
11
+ * 检查菜单项是否应该外部跳转
12
+ */
13
+ export declare const shouldOpenExternal: (menuItem: MenusType, target?: string) => boolean;
14
+ /**
15
+ * 处理外部跳转
16
+ */
17
+ export declare const handleExternalOpen: (menuItem: MenusType) => void;
18
+ /**
19
+ * 检查是否超出最大标签页限制
20
+ */
21
+ export declare const checkTabLimit: (currentTabs: TabItem[], maxTabs: number) => boolean;
22
+ /**
23
+ * 移除最旧的标签页(根据访问时间或创建时间)
24
+ */
25
+ export declare const removeOldestTab: (tabs: TabItem[]) => TabItem[];
26
+ /**
27
+ * 获取右侧标签页
28
+ */
29
+ export declare const getRightTabs: (tabs: TabItem[], currentTabId: string) => TabItem[];
30
+ /**
31
+ * 扁平化菜单数据
32
+ */
33
+ export declare const flattenMenuData: (menus?: MenusType[]) => MenusType[];
34
+ /**
35
+ * 判断菜单项是否为最后一级(叶子节点)
36
+ * 只有当菜单项没有子菜单或子菜单为空时,才认为是叶子节点
37
+ */
38
+ export declare const isLeafMenuItem: (menuItem: MenusType) => boolean;
@@ -0,0 +1,106 @@
1
+ /**
2
+ * 根据菜单项生成TabItem
3
+ */
4
+ export var createTabFromMenu = function createTabFromMenu(menuItem) {
5
+ var index = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
6
+ return {
7
+ id: String(menuItem.id || menuItem.code || menuItem.url || index),
8
+ code: menuItem.code,
9
+ name: menuItem.name,
10
+ title: menuItem.name,
11
+ url: menuItem.url,
12
+ closable: true,
13
+ menuItem,
14
+ icon: menuItem.icon || menuItem.imgUrl
15
+ };
16
+ };
17
+
18
+ /**
19
+ * 生成唯一的tab ID
20
+ */
21
+ export var generateTabId = (menuItem, existingIds) => {
22
+ var baseId = String(menuItem.id || menuItem.code || menuItem.url);
23
+ var finalId = baseId;
24
+ var counter = 1;
25
+
26
+ // 如果ID已存在,则添加数字后缀
27
+ while (existingIds.includes(finalId)) {
28
+ finalId = `${baseId}_${counter}`;
29
+ counter += 1;
30
+ }
31
+ return finalId;
32
+ };
33
+
34
+ /**
35
+ * 检查菜单项是否应该外部跳转
36
+ */
37
+ export var shouldOpenExternal = (menuItem, target) => {
38
+ return target === '_blank' || menuItem.redirectUrl && menuItem.redirectUrl !== menuItem.url || menuItem.type === 'EXTERNAL';
39
+ };
40
+
41
+ /**
42
+ * 处理外部跳转
43
+ */
44
+ export var handleExternalOpen = menuItem => {
45
+ var url = menuItem.redirectUrl || menuItem.url;
46
+ if (url) {
47
+ window.open(url, '_blank');
48
+ }
49
+ };
50
+
51
+ /**
52
+ * 检查是否超出最大标签页限制
53
+ */
54
+ export var checkTabLimit = (currentTabs, maxTabs) => {
55
+ return currentTabs.length >= maxTabs;
56
+ };
57
+
58
+ /**
59
+ * 移除最旧的标签页(根据访问时间或创建时间)
60
+ */
61
+ export var removeOldestTab = tabs => {
62
+ if (tabs.length === 0) return tabs;
63
+
64
+ // 找到可关闭的最旧标签页
65
+ var closableTabs = tabs.filter(tab => tab.closable);
66
+ if (closableTabs.length === 0) return tabs;
67
+
68
+ // 移除第一个可关闭的标签页
69
+ var oldestTab = closableTabs[0];
70
+ return tabs.filter(tab => tab.id !== oldestTab.id);
71
+ };
72
+
73
+ /**
74
+ * 获取右侧标签页
75
+ */
76
+ export var getRightTabs = (tabs, currentTabId) => {
77
+ var currentIndex = tabs.findIndex(tab => tab.id === currentTabId);
78
+ if (currentIndex === -1) return [];
79
+ return tabs.slice(currentIndex + 1);
80
+ };
81
+
82
+ /**
83
+ * 扁平化菜单数据
84
+ */
85
+ export var flattenMenuData = function flattenMenuData() {
86
+ var menus = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
87
+ var flatMenus = [];
88
+ menus.forEach(item => {
89
+ flatMenus.push(item);
90
+ if (item.children) {
91
+ flatMenus = [...flatMenus, ...flattenMenuData(item.children)];
92
+ }
93
+ });
94
+ return flatMenus;
95
+ };
96
+
97
+ /**
98
+ * 判断菜单项是否为最后一级(叶子节点)
99
+ * 只有当菜单项没有子菜单或子菜单为空时,才认为是叶子节点
100
+ */
101
+ export var isLeafMenuItem = menuItem => {
102
+ var _ref = menuItem || {},
103
+ children = _ref.children;
104
+ // 如果 children 不存在、为 null、为 undefined,或者为空数组,则认为是叶子节点
105
+ return !children || Array.isArray(children) && children.length === 0;
106
+ };
@@ -1,10 +1,13 @@
1
1
  /// <reference types="react" />
2
- import type { ProLayoutType } from './propTypes';
3
- export declare const LayoutContext: import("react").Context<{
2
+ import type { ProLayoutStatesType, ProLayoutType } from './propTypes';
3
+ import { useProLayoutTabs } from './components/TabsManager/hooks/useProLayoutTabs';
4
+ import { useActiveTab } from './components/TabsManager/hooks/useActiveTab';
5
+ interface LayoutContextValue {
4
6
  selectedPath: string;
5
- onSelected: (params: any) => void;
7
+ onSelected: (params: Partial<ProLayoutStatesType>) => void;
6
8
  target: '_blank' | '_parent' | '_self' | '_top';
7
- }>;
9
+ }
10
+ export declare const LayoutContext: import("react").Context<LayoutContextValue>;
8
11
  declare const ProLayout: {
9
12
  (props: ProLayoutType): import("react/jsx-runtime").JSX.Element;
10
13
  defaultProps: {
@@ -21,5 +24,8 @@ declare const ProLayout: {
21
24
  ProCollapse: (props: import("./components/ProCollapse/PropTypes").ProCollapseType) => import("react/jsx-runtime").JSX.Element;
22
25
  ProFooter: import("react").MemoExoticComponent<(props: import("./components/ProFooter/PropTypes").ProFooterType) => import("react/jsx-runtime").JSX.Element>;
23
26
  ProHeader: import("react").MemoExoticComponent<(props: import("./components/ProHeader/PropTypes").ProHeaderType) => import("react/jsx-runtime").JSX.Element>;
27
+ useProLayoutTabs: typeof useProLayoutTabs;
28
+ useActiveTab: () => import("./propTypes").TabItem;
24
29
  };
30
+ export { useProLayoutTabs, useActiveTab };
25
31
  export default ProLayout;
@@ -2,13 +2,20 @@ import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
2
2
  import "antd/es/message/style";
3
3
  import _message from "antd/es/message";
4
4
  import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
5
- import { createContext } from 'react';
5
+ /* eslint-disable func-call-spacing */
6
+ /* eslint-disable no-spaced-func */
7
+ import { createContext, useCallback, useMemo, useRef } from 'react';
6
8
  import classNames from 'classnames';
7
9
  import { useSetState, useToggle, useDeepCompareEffect } from 'ahooks';
8
10
  import { ProWaterMark } from "../index";
9
11
  import { ProCollapse, ProFooter, ProHeader } from "./components";
10
12
  import { Header, Notice, Menu } from "./components/Layout/index";
13
+ import TabsManager from "./components/TabsManager";
14
+ import { isTabsMode, validateTabsProps } from "./propTypes";
15
+ import { useProLayoutTabs } from "./components/TabsManager/hooks/useProLayoutTabs";
16
+ import { useActiveTab } from "./components/TabsManager/hooks/useActiveTab";
11
17
  import { transformMenus } from "./utils";
18
+ import { isLeafMenuItem } from "./components/TabsManager/utils";
12
19
 
13
20
  // 全局上下文
14
21
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -32,7 +39,13 @@ var ProLayout = props => {
32
39
  theme = props.theme,
33
40
  target = props.target,
34
41
  onCollapsedChange = props.onCollapsedChange,
35
- onMenuClick = props.onMenuClick;
42
+ onMenuClick = props.onMenuClick,
43
+ _props$mode = props.mode,
44
+ mode = _props$mode === void 0 ? 'normal' : _props$mode,
45
+ tabs = props.tabs;
46
+ var isTabsLayout = isTabsMode(props);
47
+ validateTabsProps(mode, tabs);
48
+ var tabsManagerRef = useRef(null);
36
49
  var _useSetState = useSetState({
37
50
  notice: headerNotice || noticeIn,
38
51
  menus: [],
@@ -64,6 +77,65 @@ var ProLayout = props => {
64
77
  menus: menuData
65
78
  });
66
79
  }, [dataSource]);
80
+ var menuDataSource = useMemo(() => Array.isArray(menus) ? {
81
+ menus
82
+ } : menus, [menus]);
83
+ var handleMenuClick = useCallback(params => {
84
+ if (isTabsLayout) {
85
+ var _tabsManagerRef$curre, _tabsManagerRef$curre2;
86
+ // 只有最后一级菜单(叶子节点)才设置选中路径
87
+ if (params.item && isLeafMenuItem(params.item)) {
88
+ var _params$item, _params$item2, _params$item3;
89
+ var targetPath = ((_params$item = params.item) === null || _params$item === void 0 ? void 0 : _params$item.url) || ((_params$item2 = params.item) === null || _params$item2 === void 0 ? void 0 : _params$item2.redirectUrl) || ((_params$item3 = params.item) === null || _params$item3 === void 0 ? void 0 : _params$item3.router);
90
+ if (targetPath && targetPath !== selectedPath) {
91
+ setState({
92
+ selectedPath: targetPath
93
+ });
94
+ }
95
+ }
96
+ (_tabsManagerRef$curre = tabsManagerRef.current) === null || _tabsManagerRef$curre === void 0 || (_tabsManagerRef$curre2 = _tabsManagerRef$curre.handleMenuClick) === null || _tabsManagerRef$curre2 === void 0 || _tabsManagerRef$curre2.call(_tabsManagerRef$curre, params);
97
+ return;
98
+ }
99
+ onMenuClick === null || onMenuClick === void 0 || onMenuClick(params);
100
+ }, [isTabsLayout, onMenuClick, selectedPath, setState]);
101
+ var enhancedTabsConfig = useMemo(() => {
102
+ if (!isTabsLayout || !tabs) {
103
+ return tabs;
104
+ }
105
+ return _objectSpread(_objectSpread({}, tabs), {}, {
106
+ onTabChange: (activeKey, activeTab, allTabs) => {
107
+ var _activeTab$menuItem, _activeTab$menuItem2, _activeTab$menuItem3, _tabs$onTabChange;
108
+ if (!allTabs || allTabs.length === 0) {
109
+ // 使用一个不可能匹配的路径来清除选中状态,避免 OpenMenu fallback 到 window.location.pathname
110
+ setState({
111
+ selectedPath: '##EMPTY##'
112
+ });
113
+ return;
114
+ }
115
+ var targetPath = (activeTab === null || activeTab === void 0 ? void 0 : activeTab.url) || (activeTab === null || activeTab === void 0 || (_activeTab$menuItem = activeTab.menuItem) === null || _activeTab$menuItem === void 0 ? void 0 : _activeTab$menuItem.router) || (activeTab === null || activeTab === void 0 || (_activeTab$menuItem2 = activeTab.menuItem) === null || _activeTab$menuItem2 === void 0 ? void 0 : _activeTab$menuItem2.url) || (activeTab === null || activeTab === void 0 || (_activeTab$menuItem3 = activeTab.menuItem) === null || _activeTab$menuItem3 === void 0 ? void 0 : _activeTab$menuItem3.redirectUrl);
116
+ if (targetPath && targetPath !== selectedPath) {
117
+ setState({
118
+ selectedPath: targetPath
119
+ });
120
+ }
121
+ (_tabs$onTabChange = tabs.onTabChange) === null || _tabs$onTabChange === void 0 || _tabs$onTabChange.call(tabs, activeKey, activeTab, allTabs);
122
+ }
123
+ });
124
+ }, [isTabsLayout, tabs, selectedPath, setState]);
125
+ var renderContent = () => {
126
+ if (!isTabsLayout || !enhancedTabsConfig) {
127
+ return /*#__PURE__*/_jsx("div", {
128
+ children: children
129
+ });
130
+ }
131
+ return /*#__PURE__*/_jsx(TabsManager, {
132
+ ref: tabsManagerRef,
133
+ config: enhancedTabsConfig,
134
+ dataSource: menuDataSource,
135
+ originalOnMenuClick: onMenuClick,
136
+ children: children
137
+ });
138
+ };
67
139
 
68
140
  /**
69
141
  * 关闭提示框
@@ -94,12 +166,10 @@ var ProLayout = props => {
94
166
  })), /*#__PURE__*/_jsxs("div", {
95
167
  className: contentCls,
96
168
  children: [/*#__PURE__*/_jsx(Menu, _objectSpread(_objectSpread({}, props), {}, {
97
- dataSource: Array.isArray(menus) ? {
98
- menus
99
- } : menus,
169
+ dataSource: menuDataSource,
100
170
  notice: notice,
101
171
  collapsed: collapsed,
102
- onMenuClick: onMenuClick,
172
+ onMenuClick: handleMenuClick,
103
173
  onToggle: () => {
104
174
  toggle();
105
175
  onCollapsedChange && onCollapsedChange(!collapsed);
@@ -109,9 +179,7 @@ var ProLayout = props => {
109
179
  style: _objectSpread(_objectSpread({}, contentStyle), {}, {
110
180
  marginTop: headerHeight + noticeHeight
111
181
  }),
112
- children: /*#__PURE__*/_jsx("div", {
113
- children: children
114
- })
182
+ children: renderContent()
115
183
  })]
116
184
  })]
117
185
  });
@@ -140,4 +208,9 @@ ProLayout.defaultProps = {
140
208
  ProLayout.ProCollapse = ProCollapse;
141
209
  ProLayout.ProFooter = ProFooter;
142
210
  ProLayout.ProHeader = ProHeader;
211
+ ProLayout.useProLayoutTabs = useProLayoutTabs;
212
+ ProLayout.useActiveTab = useActiveTab;
213
+
214
+ // 同时导出Hook供直接使用
215
+ export { useProLayoutTabs, useActiveTab };
143
216
  export default ProLayout;
@@ -94,7 +94,7 @@ type pureKey = boolean | {
94
94
  topMenu?: boolean;
95
95
  leftMenu?: boolean;
96
96
  };
97
- export interface ProLayoutType {
97
+ interface ProLayoutBaseProps {
98
98
  /**
99
99
  * @description 左侧logo
100
100
  * @default -
@@ -237,6 +237,144 @@ export interface ProLayoutStatesType {
237
237
  }
238
238
  export type MenusProps = MenusType;
239
239
  export type DataSourceProps = DataSourceType;
240
+ export interface TabItem {
241
+ /**
242
+ * @description 标签唯一标识
243
+ */
244
+ id: string;
245
+ /**
246
+ * @description 组件标识码
247
+ */
248
+ code: string;
249
+ /**
250
+ * @description 标签名称
251
+ */
252
+ name: string;
253
+ /**
254
+ * @description 标签标题(废弃,保留兼容)
255
+ */
256
+ title: string;
257
+ /**
258
+ * @description 标签关联路由
259
+ */
260
+ url?: string;
261
+ /**
262
+ * @description 是否可关闭
263
+ */
264
+ closable: boolean;
265
+ /**
266
+ * @description 关联菜单项
267
+ */
268
+ menuItem?: MenusType;
269
+ /**
270
+ * @description 额外扩展数据
271
+ */
272
+ extra?: Record<string, any>;
273
+ /**
274
+ * @description 图标
275
+ */
276
+ icon?: ReactNode | string;
277
+ }
278
+ export interface TabsState {
279
+ tabsList: TabItem[];
280
+ activeKey: string;
281
+ activeTabInfo?: TabItem;
282
+ newTabIndex: number;
283
+ activeComponent?: string;
284
+ }
285
+ export type TabsStorageStrategy = 'localStorage' | 'sessionStorage';
286
+ /**
287
+ * @description 添加标签页的业务参数
288
+ */
289
+ export interface AddTabParams {
290
+ /**
291
+ * @description 组件标识码,用于映射到具体的 React 组件
292
+ */
293
+ code: string;
294
+ /**
295
+ * @description 标签页显示名称
296
+ */
297
+ name: string;
298
+ /**
299
+ * @description 额外的业务数据
300
+ */
301
+ extra?: Record<string, any>;
302
+ }
303
+ /**
304
+ * @description 添加标签页的选项
305
+ */
306
+ export interface AddTabOptions {
307
+ /**
308
+ * @description 是否强制创建新标签页(忽略已存在的相同标签页),默认 false
309
+ */
310
+ forceNew?: boolean;
311
+ }
312
+ /**
313
+ * @description 获取标签页信息返回值
314
+ */
315
+ export interface TabsInfoResult {
316
+ /** 标签页列表 */
317
+ tabsList: TabItem[];
318
+ /** 当前激活的标签页信息 */
319
+ activeTabInfo?: TabItem;
320
+ /** 当前激活的组件标识 */
321
+ activeComponent: string;
322
+ }
323
+ /**
324
+ * @description ProLayout 标签页实例接口(类似 FormInstance)
325
+ */
326
+ export interface ProLayoutTabsInstance {
327
+ /**
328
+ * @description 添加标签页
329
+ */
330
+ addTab: (params: AddTabParams, options?: AddTabOptions) => void;
331
+ /**
332
+ * @description 删除标签页
333
+ */
334
+ removeTab: (tabId: string) => void;
335
+ /**
336
+ * @description 获取标签页信息
337
+ */
338
+ getTabInfo: () => TabsInfoResult;
339
+ }
340
+ export interface TabsConfig {
341
+ max?: number;
342
+ storage?: TabsStorageStrategy;
343
+ cacheKey?: string;
344
+ onTabChange?: (activeKey: string, activeTab: TabItem | undefined, allTabs: TabItem[]) => void;
345
+ /**
346
+ * @description 激活组件解析函数,根据 component 标识返回对应的 React 组件
347
+ */
348
+ activeComponent?: (component: string) => React.ComponentType<any> | null;
349
+ /**
350
+ * @description 空状态组件,当没有标签页时显示
351
+ */
352
+ empty?: ReactNode;
353
+ /**
354
+ * @description 自定义右键菜单项,会替换默认菜单项
355
+ */
356
+ menuItems?: import('antd').MenuProps['items'];
357
+ /**
358
+ * @description 自定义菜单项点击回调
359
+ */
360
+ tabMenuClick?: (params: {
361
+ key: string;
362
+ tab: TabItem;
363
+ tabs: TabItem[];
364
+ }) => void;
365
+ }
366
+ export type ProLayoutMode = 'normal' | 'tabs';
367
+ export interface ProLayoutTabsProps extends ProLayoutBaseProps {
368
+ mode: 'tabs';
369
+ tabs: TabsConfig;
370
+ }
371
+ export interface ProLayoutNormalProps extends ProLayoutBaseProps {
372
+ mode?: 'normal';
373
+ tabs?: never;
374
+ }
375
+ export type ProLayoutType = ProLayoutTabsProps | ProLayoutNormalProps;
240
376
  export type ProLayoutProps = ProLayoutType;
241
377
  export type ProLayoutStates = ProLayoutStatesType;
378
+ export declare const isTabsMode: (props: ProLayoutType) => props is ProLayoutTabsProps;
379
+ export declare const validateTabsProps: (mode?: ProLayoutMode, tabs?: TabsConfig) => void;
242
380
  export {};
@@ -1 +1,37 @@
1
- export {};
1
+ /**
2
+ * @description 主题枚举类型
3
+ */
4
+
5
+ /**
6
+ * @description 是否带有菜单界面的配置
7
+ */
8
+
9
+ // 为了向后兼容,保留旧的类型名称但使用新的类型定义
10
+
11
+ /**
12
+ * @description 添加标签页的业务参数
13
+ */
14
+
15
+ /**
16
+ * @description 添加标签页的选项
17
+ */
18
+
19
+ /**
20
+ * @description 获取标签页信息返回值
21
+ */
22
+
23
+ /**
24
+ * @description ProLayout 标签页实例接口(类似 FormInstance)
25
+ */
26
+
27
+ export var isTabsMode = props => props.mode === 'tabs';
28
+ export var validateTabsProps = function validateTabsProps() {
29
+ var mode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'normal';
30
+ var tabs = arguments.length > 1 ? arguments[1] : undefined;
31
+ if (mode === 'tabs' && !tabs) {
32
+ throw new Error('ProLayout: tabs configuration is required when mode="tabs",例如 <ProLayout mode="tabs" tabs={{ max: 10 }} />');
33
+ }
34
+ if (mode !== 'tabs' && tabs) {
35
+ console.warn('ProLayout: tabs configuration is ignored because mode is not "tabs"');
36
+ }
37
+ };