@zat-design/sisyphus-react 4.5.10-beta.1 → 4.6.0-beta.1

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 (268) hide show
  1. package/es/FormsProvider/index.js +14 -21
  2. package/es/ProAction/components/CheckModalContent/index.js +12 -26
  3. package/es/ProAction/index.js +79 -83
  4. package/es/ProAction/propsType.js +0 -1
  5. package/es/ProConfigProvider/index.js +63 -110
  6. package/es/ProConfigProvider/propsType.js +0 -1
  7. package/es/ProDownload/index.js +55 -65
  8. package/es/ProDownload/propsType.js +0 -1
  9. package/es/ProDownload/utils.js +61 -95
  10. package/es/ProDrawerForm/components/ProDrawer/index.js +83 -113
  11. package/es/ProDrawerForm/components/ProModal/index.js +77 -108
  12. package/es/ProDrawerForm/components/index.js +6 -2
  13. package/es/ProDrawerForm/hooks/useConfirmClose.js +20 -39
  14. package/es/ProDrawerForm/index.js +29 -38
  15. package/es/ProDrawerForm/propsType.js +0 -1
  16. package/es/ProDrawerForm/utils/index.js +18 -36
  17. package/es/ProEditLabel/components/RenderProForm.js +45 -49
  18. package/es/ProEditLabel/index.js +126 -163
  19. package/es/ProEditLabel/propsType.js +0 -1
  20. package/es/ProEditLabel/utils/index.js +5 -8
  21. package/es/ProEditTable/components/ActionButton/index.js +111 -119
  22. package/es/ProEditTable/components/RcTable/BaseTable.js +38 -51
  23. package/es/ProEditTable/components/RcTable/DraggableTable.js +97 -129
  24. package/es/ProEditTable/components/RcTable/index.js +6 -4
  25. package/es/ProEditTable/components/RenderField/ListChangedWrapper.js +77 -95
  26. package/es/ProEditTable/components/RenderField/index.js +490 -587
  27. package/es/ProEditTable/components/RenderField/propsType.js +0 -1
  28. package/es/ProEditTable/components/RenderField/tools.js +115 -112
  29. package/es/ProEditTable/components/RenderToolbar/index.js +47 -73
  30. package/es/ProEditTable/components/Summary/index.js +38 -64
  31. package/es/ProEditTable/components/Validator/index.js +46 -46
  32. package/es/ProEditTable/components/index.js +12 -5
  33. package/es/ProEditTable/index.js +456 -378
  34. package/es/ProEditTable/propsType.js +0 -1
  35. package/es/ProEditTable/utils/config.js +60 -122
  36. package/es/ProEditTable/utils/diffOriginal.js +45 -82
  37. package/es/ProEditTable/utils/getDefaultProps.js +19 -24
  38. package/es/ProEditTable/utils/index.js +150 -236
  39. package/es/ProEditTable/utils/tools.js +149 -286
  40. package/es/ProEditTable/utils/transform.js +25 -30
  41. package/es/ProEditTable/utils/useEditTableError.js +30 -43
  42. package/es/ProEditTable/utils/useShouldUpdateForTable.js +42 -72
  43. package/es/ProEditTable/utils/validateAll.js +87 -154
  44. package/es/ProEnum/components/Group.js +38 -30
  45. package/es/ProEnum/components/Tag.js +22 -26
  46. package/es/ProEnum/hooks/useEnum.js +48 -116
  47. package/es/ProEnum/hooks/useEnumRequest.js +128 -179
  48. package/es/ProEnum/hooks/useFrequentEnumRequest.js +40 -48
  49. package/es/ProEnum/index.js +162 -172
  50. package/es/ProEnum/propsType.js +0 -1
  51. package/es/ProEnum/utils/eventCenter.js +10 -12
  52. package/es/ProEnum/utils/frequentEnum.js +35 -92
  53. package/es/ProEnum/utils/getEnum.js +32 -90
  54. package/es/ProEnum/utils/getEnumLabel.js +44 -49
  55. package/es/ProEnum/utils/index.js +93 -207
  56. package/es/ProForm/components/Container.js +13 -28
  57. package/es/ProForm/components/FormFooter/index.js +36 -44
  58. package/es/ProForm/components/FormFooter/propsType.js +0 -1
  59. package/es/ProForm/components/base/Checkbox/index.js +32 -59
  60. package/es/ProForm/components/base/DatePicker/index.js +49 -71
  61. package/es/ProForm/components/base/Input/index.js +63 -97
  62. package/es/ProForm/components/base/Input/propsType.js +0 -1
  63. package/es/ProForm/components/base/InputNumber/index.js +118 -172
  64. package/es/ProForm/components/base/Radio/index.js +39 -52
  65. package/es/ProForm/components/base/RangePicker/index.js +109 -127
  66. package/es/ProForm/components/base/RangePicker/useDateRange.js +20 -17
  67. package/es/ProForm/components/base/Select/index.js +63 -89
  68. package/es/ProForm/components/base/Switch/index.js +27 -35
  69. package/es/ProForm/components/base/SwitchCheckbox/index.js +36 -54
  70. package/es/ProForm/components/base/TextArea/index.js +30 -41
  71. package/es/ProForm/components/base/TimePicker/index.js +27 -37
  72. package/es/ProForm/components/combination/Container/index.js +37 -47
  73. package/es/ProForm/components/combination/Container/propsType.js +0 -1
  74. package/es/ProForm/components/combination/FormList/components/ActionButton.js +165 -237
  75. package/es/ProForm/components/combination/FormList/components/BlockFields.js +98 -103
  76. package/es/ProForm/components/combination/FormList/components/Empty.js +27 -54
  77. package/es/ProForm/components/combination/FormList/components/LineFields.js +57 -54
  78. package/es/ProForm/components/combination/FormList/components/ToolbarButton.js +61 -109
  79. package/es/ProForm/components/combination/FormList/index.js +151 -161
  80. package/es/ProForm/components/combination/FormList/propsType.js +0 -1
  81. package/es/ProForm/components/combination/FormList/utils.js +22 -38
  82. package/es/ProForm/components/combination/Group/component/AddonWrapper/index.js +12 -28
  83. package/es/ProForm/components/combination/Group/component/ComRender.js +50 -111
  84. package/es/ProForm/components/combination/Group/component/FlexibleGroup.js +105 -206
  85. package/es/ProForm/components/combination/Group/hooks/index.js +68 -128
  86. package/es/ProForm/components/combination/Group/index.js +87 -126
  87. package/es/ProForm/components/combination/Group/propsType.js +0 -1
  88. package/es/ProForm/components/combination/Group/utils/index.js +124 -239
  89. package/es/ProForm/components/combination/ProCascader/index.js +156 -199
  90. package/es/ProForm/components/combination/ProCascader/propsType.js +0 -1
  91. package/es/ProForm/components/combination/ProCascader/utils/index.js +12 -21
  92. package/es/ProForm/components/combination/ProModalSelect/hooks/useRequestList.js +63 -75
  93. package/es/ProForm/components/combination/ProModalSelect/index.js +290 -348
  94. package/es/ProForm/components/combination/ProModalSelect/propsType.js +0 -1
  95. package/es/ProForm/components/combination/ProModalSelect/utils/index.js +32 -39
  96. package/es/ProForm/components/combination/ProNumberRange/index.js +100 -156
  97. package/es/ProForm/components/combination/ProNumberRange/propsType.js +0 -1
  98. package/es/ProForm/components/combination/ProRangeLimit/index.js +104 -115
  99. package/es/ProForm/components/combination/ProRangeLimit/propsType.js +0 -1
  100. package/es/ProForm/components/combination/ProTimeLimit/hooks/useControlled.js +16 -16
  101. package/es/ProForm/components/combination/ProTimeLimit/index.js +75 -109
  102. package/es/ProForm/components/index.js +56 -34
  103. package/es/ProForm/components/render/ChangedWrapper.js +85 -94
  104. package/es/ProForm/components/render/ConfirmWrapper.js +27 -39
  105. package/es/ProForm/components/render/CustomComponentViewWrapper.js +65 -82
  106. package/es/ProForm/components/render/Render.js +223 -329
  107. package/es/ProForm/components/render/RenderFields.js +76 -113
  108. package/es/ProForm/components/render/propsType.js +0 -1
  109. package/es/ProForm/hooks/useControlled.js +8 -10
  110. package/es/ProForm/hooks/useDeepCompareMemo.js +11 -11
  111. package/es/ProForm/hooks/useFieldProps.js +8 -4
  112. package/es/ProForm/hooks/useForm.js +50 -110
  113. package/es/ProForm/hooks/useRules.js +17 -33
  114. package/es/ProForm/hooks/useShouldUpdate.js +77 -152
  115. package/es/ProForm/hooks/useWatch.js +58 -129
  116. package/es/ProForm/index.js +157 -194
  117. package/es/ProForm/propsType.js +15 -7
  118. package/es/ProForm/utils/buildFormItemProps.js +51 -58
  119. package/es/ProForm/utils/diffOriginal.js +43 -73
  120. package/es/ProForm/utils/getDefaultProps.js +18 -24
  121. package/es/ProForm/utils/index.js +159 -234
  122. package/es/ProForm/utils/processDependencies.js +21 -60
  123. package/es/ProForm/utils/reactiveValues.js +20 -34
  124. package/es/ProForm/utils/rulesCreator.js +42 -40
  125. package/es/ProForm/utils/transformNames.js +10 -13
  126. package/es/ProForm/utils/transformValue.js +16 -29
  127. package/es/ProForm/utils/valueType.js +96 -178
  128. package/es/ProIcon/config/index.js +340 -274
  129. package/es/ProIcon/index.js +135 -209
  130. package/es/ProIcon/propsTypes.js +0 -1
  131. package/es/ProIcon/utils/index.js +24 -39
  132. package/es/ProLayout/components/Layout/Header/index.js +108 -141
  133. package/es/ProLayout/components/Layout/Menu/FoldMenu/index.js +134 -190
  134. package/es/ProLayout/components/Layout/Menu/OpenMenu/index.js +111 -137
  135. package/es/ProLayout/components/Layout/Menu/OpenMenu/propsType.js +0 -1
  136. package/es/ProLayout/components/Layout/Menu/SideMenu/index.js +23 -31
  137. package/es/ProLayout/components/Layout/Menu/index.js +92 -89
  138. package/es/ProLayout/components/Layout/Notice/index.js +13 -27
  139. package/es/ProLayout/components/Layout/index.js +8 -3
  140. package/es/ProLayout/components/ProCollapse/PropTypes.js +0 -1
  141. package/es/ProLayout/components/ProCollapse/index.js +89 -111
  142. package/es/ProLayout/components/ProFooter/PropTypes.js +0 -1
  143. package/es/ProLayout/components/ProFooter/index.js +27 -25
  144. package/es/ProLayout/components/ProHeader/PropTypes.js +0 -1
  145. package/es/ProLayout/components/ProHeader/components/Copy/index.js +23 -21
  146. package/es/ProLayout/components/ProHeader/components/Describe/index.js +67 -86
  147. package/es/ProLayout/components/ProHeader/components/ProBackBtn/index.js +18 -21
  148. package/es/ProLayout/components/ProHeader/components/ProBackBtn/propsType.js +0 -1
  149. package/es/ProLayout/components/ProHeader/components/index.js +6 -2
  150. package/es/ProLayout/components/ProHeader/index.js +216 -356
  151. package/es/ProLayout/components/ProHeader/utils/index.js +19 -26
  152. package/es/ProLayout/components/TabsManager/components/TabContextMenu.js +92 -85
  153. package/es/ProLayout/components/TabsManager/components/TabItem.js +53 -64
  154. package/es/ProLayout/components/TabsManager/components/TabsContext.js +5 -5
  155. package/es/ProLayout/components/TabsManager/components/TabsHeader.js +42 -52
  156. package/es/ProLayout/components/TabsManager/hooks/useActiveTab.js +8 -9
  157. package/es/ProLayout/components/TabsManager/hooks/useIframeRoute.js +19 -32
  158. package/es/ProLayout/components/TabsManager/hooks/useProLayoutTabs.js +6 -20
  159. package/es/ProLayout/components/TabsManager/hooks/useTabsCache.js +25 -42
  160. package/es/ProLayout/components/TabsManager/hooks/useTabsState.js +310 -412
  161. package/es/ProLayout/components/TabsManager/hooks/useTabsUrlSync.js +132 -95
  162. package/es/ProLayout/components/TabsManager/index.js +415 -391
  163. package/es/ProLayout/components/TabsManager/propTypes.js +7 -15
  164. package/es/ProLayout/components/TabsManager/utils/historyObserver.js +26 -23
  165. package/es/ProLayout/components/TabsManager/utils/index.d.ts +2 -1
  166. package/es/ProLayout/components/TabsManager/utils/index.js +135 -184
  167. package/es/ProLayout/components/index.js +8 -3
  168. package/es/ProLayout/index.js +171 -229
  169. package/es/ProLayout/propTypes.d.ts +9 -0
  170. package/es/ProLayout/propTypes.js +12 -52
  171. package/es/ProLayout/utils/index.js +48 -128
  172. package/es/ProSelect/components/AdaptiveTooltip.js +26 -25
  173. package/es/ProSelect/index.js +184 -229
  174. package/es/ProSelect/propsType.js +0 -1
  175. package/es/ProSelect/utils/index.js +100 -146
  176. package/es/ProStep/components/Anchor/index.js +71 -82
  177. package/es/ProStep/components/Item/index.js +49 -56
  178. package/es/ProStep/components/LazyLoad/index.js +23 -29
  179. package/es/ProStep/components/Listener/index.js +20 -33
  180. package/es/ProStep/components/Step/index.js +31 -38
  181. package/es/ProStep/constants.js +4 -1
  182. package/es/ProStep/index.js +166 -153
  183. package/es/ProStep/propsType.js +0 -1
  184. package/es/ProStep/utils/index.js +29 -55
  185. package/es/ProStepTab/index.js +83 -138
  186. package/es/ProStepTab/propsType.js +0 -1
  187. package/es/ProTable/components/EditableCell/EditIcon.js +10 -14
  188. package/es/ProTable/components/EditableCell/index.js +37 -71
  189. package/es/ProTable/components/EditableCell/propsType.js +0 -1
  190. package/es/ProTable/components/FormatColumn/index.js +209 -340
  191. package/es/ProTable/components/FormatColumn/propsType.js +0 -1
  192. package/es/ProTable/components/RcTable/components/BaseTable/index.js +35 -39
  193. package/es/ProTable/components/RcTable/components/DraggableTable/components/DndWrapper/index.js +80 -107
  194. package/es/ProTable/components/RcTable/components/DraggableTable/components/DndWrapper/utils/index.js +54 -48
  195. package/es/ProTable/components/RcTable/components/DraggableTable/components/DndWrapper/utils/propsType.js +0 -1
  196. package/es/ProTable/components/RcTable/components/DraggableTable/index.js +47 -54
  197. package/es/ProTable/components/RcTable/index.js +6 -4
  198. package/es/ProTable/components/RenderColumn/index.js +158 -186
  199. package/es/ProTable/components/RenderEmptyText/index.js +12 -21
  200. package/es/ProTable/components/RenderFooter/index.js +15 -15
  201. package/es/ProTable/components/RenderSummary/index.js +33 -50
  202. package/es/ProTable/components/RenderTableHeader/index.js +44 -46
  203. package/es/ProTable/components/RenderTabs/index.js +47 -51
  204. package/es/ProTable/components/TableResizable/index.js +56 -72
  205. package/es/ProTable/components/TooltipTitle/index.js +13 -21
  206. package/es/ProTable/components/index.js +16 -36
  207. package/es/ProTable/hooks/useAntdTable.js +185 -219
  208. package/es/ProTable/index.js +232 -249
  209. package/es/ProTable/propsType.js +0 -1
  210. package/es/ProTable/utils/columnStorage.js +63 -88
  211. package/es/ProTable/utils/index.js +57 -90
  212. package/es/ProTabs/components/Card/index.js +20 -48
  213. package/es/ProTabs/components/index.js +4 -1
  214. package/es/ProTabs/index.js +39 -56
  215. package/es/ProTabs/propType.js +0 -1
  216. package/es/ProThemeTools/component/ProTools/index.js +106 -158
  217. package/es/ProThemeTools/component/index.js +4 -1
  218. package/es/ProThemeTools/context/ThemeContext.js +67 -146
  219. package/es/ProThemeTools/index.js +103 -156
  220. package/es/ProThemeTools/propsType.js +0 -1
  221. package/es/ProThemeTools/utils/index.js +60 -109
  222. package/es/ProTooltip/index.js +132 -165
  223. package/es/ProTooltip/propsType.js +0 -1
  224. package/es/ProTree/components/AdaptiveTooltip.js +15 -17
  225. package/es/ProTree/components/CloseIcon.js +18 -26
  226. package/es/ProTree/components/List.js +28 -47
  227. package/es/ProTree/components/ProTree.js +152 -211
  228. package/es/ProTree/components/ProTreeSelect/index.js +254 -458
  229. package/es/ProTree/components/ProTreeSelect/propsType.js +0 -1
  230. package/es/ProTree/components/SearchTitle.js +23 -42
  231. package/es/ProTree/components/Tree.js +147 -195
  232. package/es/ProTree/components/index.js +10 -5
  233. package/es/ProTree/index.js +12 -16
  234. package/es/ProTree/propsType.js +0 -1
  235. package/es/ProTree/utils.js +46 -118
  236. package/es/ProTreeModal/components/Cascader.js +56 -64
  237. package/es/ProTreeModal/components/CloseIcon.js +18 -26
  238. package/es/ProTreeModal/components/List.js +114 -180
  239. package/es/ProTreeModal/components/SearchTitle.js +15 -18
  240. package/es/ProTreeModal/components/SortableItem.js +29 -58
  241. package/es/ProTreeModal/components/Tree.js +99 -113
  242. package/es/ProTreeModal/components/Trigger.js +87 -121
  243. package/es/ProTreeModal/components/index.js +14 -6
  244. package/es/ProTreeModal/index.js +397 -435
  245. package/es/ProTreeModal/propsType.js +0 -1
  246. package/es/ProTreeModal/utils.js +52 -95
  247. package/es/ProUpload/components/ButtonRender.js +44 -54
  248. package/es/ProUpload/components/DragRender.js +94 -134
  249. package/es/ProUpload/components/DraggableUploadListItem.js +12 -25
  250. package/es/ProUpload/components/Example.js +27 -31
  251. package/es/ProUpload/components/FileItem.js +69 -163
  252. package/es/ProUpload/components/ImageRender.js +134 -170
  253. package/es/ProUpload/index.js +68 -100
  254. package/es/ProUpload/propsType.js +0 -1
  255. package/es/ProUpload/uitls.js +8 -4
  256. package/es/ProUtils/utils/index.js +17 -13
  257. package/es/ProViewer/index.js +154 -175
  258. package/es/ProViewer/propsType.js +0 -5
  259. package/es/ProWaterMark/index.js +9 -16
  260. package/es/ProWaterMark/propsType.js +0 -1
  261. package/es/hooks/useDraggableRow.js +25 -53
  262. package/es/index.js +57 -77
  263. package/es/locale/en_US.js +153 -142
  264. package/es/locale/index.js +23 -36
  265. package/es/locale/zh_CN.js +145 -142
  266. package/es/tokens.js +84 -83
  267. package/es/utils/index.js +24 -51
  268. package/package.json +4 -3
@@ -1,315 +1,263 @@
1
- import { useState, useCallback, useEffect, useRef } from 'react';
2
- import { message } from 'antd';
1
+ import { useState, useCallback, useEffect, useRef } from "react";
2
+ import { message } from "antd";
3
3
  import { DEFAULT_TABS_CONFIG } from "../propTypes";
4
4
  import { useTabsCache } from "./useTabsCache";
5
5
  import locale, { formatMessage } from "../../../../locale";
6
- import { createTabFromMenu, generateTabId, shouldOpenExternal, handleExternalOpen, checkTabLimit, getRightTabs, flattenMenuData, canOpenAsTab, getMenuRoute, findExistingTab, normalizeTabUrl, isSafeExternalUrl, isSafeHttpUrl, resolveTabMenuItem, derivePinned, getPinnedBoundary, pinTab as pinTabInList, unpinTab as unpinTabInList, reorderWithPinConstraint } from "../utils";
7
-
8
- /**
9
- * 标签页状态管理Hook
10
- */
11
- export const useTabsState = options => {
12
- const {
13
- initialState = {},
14
- config,
15
- dataSource,
16
- cacheEnabled = true
17
- } = options;
18
-
19
- // 合并默认配置
20
- const finalConfig = {
21
- ...DEFAULT_TABS_CONFIG,
22
- ...config
23
- };
24
- const urlSyncEnabled = finalConfig.urlSync === true || typeof finalConfig.urlSync === 'object' && finalConfig.urlSync !== null;
25
-
26
- // 初始化状态
6
+ import {
7
+ createTabFromMenu,
8
+ generateTabId,
9
+ shouldOpenExternal,
10
+ handleExternalOpen,
11
+ checkTabLimit,
12
+ getRightTabs,
13
+ flattenMenuData,
14
+ canOpenAsTab,
15
+ getMenuRoute,
16
+ hasRelationKey,
17
+ findExistingTab,
18
+ normalizeTabUrl,
19
+ isSafeExternalUrl,
20
+ isSafeHttpUrl,
21
+ resolveTabMenuItem,
22
+ derivePinned,
23
+ getPinnedBoundary,
24
+ pinTab as pinTabInList,
25
+ unpinTab as unpinTabInList,
26
+ reorderWithPinConstraint
27
+ } from "../utils";
28
+ const useTabsState = (options) => {
29
+ const { initialState = {}, config, dataSource, cacheEnabled = true } = options;
30
+ const finalConfig = { ...DEFAULT_TABS_CONFIG, ...config };
31
+ const urlSyncEnabled = finalConfig.urlSync === true || typeof finalConfig.urlSync === "object" && finalConfig.urlSync !== null;
32
+ const urlSyncIdentity = typeof finalConfig.urlSync === "object" && finalConfig.urlSync !== null ? finalConfig.urlSync.identity || "url" : "url";
27
33
  const [state, setState] = useState(() => ({
28
34
  tabsList: [],
29
- activeKey: '',
30
- activeTabInfo: undefined,
35
+ activeKey: "",
36
+ activeTabInfo: void 0,
31
37
  newTabIndex: 0,
32
- activeComponent: '',
38
+ activeComponent: "",
33
39
  ...initialState
34
40
  }));
35
-
36
- // 缓存管理
37
- const {
38
- saveToCache,
39
- restoreFromCache,
40
- clearCache
41
- } = useTabsCache({
41
+ const { saveToCache, restoreFromCache, clearCache } = useTabsCache({
42
42
  cacheKey: finalConfig.cacheKey,
43
43
  storage: finalConfig.storage,
44
44
  enabled: cacheEnabled
45
45
  });
46
-
47
- // 初始化标记,确保只在初始化后保存缓存
48
46
  const [isInitialized, setIsInitialized] = useState(false);
49
-
50
- // 从缓存恢复状态
51
47
  const hasRestoredCacheRef = useRef(false);
52
48
  useEffect(() => {
53
- if (hasRestoredCacheRef.current) return;
49
+ var _a, _b;
50
+ if (hasRestoredCacheRef.current)
51
+ return;
54
52
  hasRestoredCacheRef.current = true;
55
53
  const cachedState = restoreFromCache();
56
54
  if (cachedState && cachedState.tabsList && cachedState.tabsList.length > 0) {
57
- // 兼容旧缓存:如果缓存中有 activeTab 但没有 activeTabInfo,进行迁移
58
- const restoredState = {
59
- ...cachedState
60
- };
61
- if ('activeTab' in restoredState && !restoredState.activeTabInfo) {
55
+ const restoredState = { ...cachedState };
56
+ if ("activeTab" in restoredState && !restoredState.activeTabInfo) {
62
57
  restoredState.activeTabInfo = restoredState.activeTab;
63
58
  delete restoredState.activeTab;
64
59
  }
65
-
66
- // 兼容旧缓存:Ant Tabs 的 onChange 始终返回字符串 key;旧版本可能保存数字 id,
67
- // 若不归一化,严格比较会导致恢复后的标签无法切换。
68
- restoredState.tabsList = restoredState.tabsList.map(tab => ({
60
+ restoredState.tabsList = restoredState.tabsList.map((tab) => ({
69
61
  ...tab,
70
62
  id: String(tab.id),
71
- pinned: tab.pinned === undefined ? derivePinned(tab) : tab.pinned
63
+ pinned: tab.pinned === void 0 ? derivePinned(tab) : tab.pinned
72
64
  }));
73
- restoredState.activeKey = restoredState.activeKey === undefined || restoredState.activeKey === null ? '' : String(restoredState.activeKey);
65
+ restoredState.activeKey = restoredState.activeKey === void 0 || restoredState.activeKey === null ? "" : String(restoredState.activeKey);
74
66
  if (urlSyncEnabled) {
75
- const retainedTabByUrl = new Map();
76
- const retainedIdByOriginalId = new Map();
77
- restoredState.tabsList.forEach(tab => {
67
+ const retainedTabByIdentity = /* @__PURE__ */ new Map();
68
+ const retainedIdByOriginalId = /* @__PURE__ */ new Map();
69
+ restoredState.tabsList.forEach((tab) => {
70
+ var _a2;
78
71
  const normalizedUrl = normalizeTabUrl(tab.url);
79
- if (!normalizedUrl) return;
80
- const retainedTab = retainedTabByUrl.get(normalizedUrl);
72
+ if (!normalizedUrl)
73
+ return;
74
+ const relationKey = tab.relationKey ?? ((_a2 = tab.menuItem) == null ? void 0 : _a2.relationKey);
75
+ const identity = urlSyncIdentity === "relationKey" && hasRelationKey(relationKey) ? `relationKey:${typeof relationKey}:${String(relationKey)}` : `url:${normalizedUrl}`;
76
+ const retainedTab = retainedTabByIdentity.get(identity);
81
77
  if (retainedTab) {
78
+ retainedTabByIdentity.set(identity, { ...retainedTab, url: normalizedUrl });
82
79
  retainedIdByOriginalId.set(tab.id, retainedTab.id);
83
80
  return;
84
81
  }
85
- const normalizedTab = {
86
- ...tab,
87
- url: normalizedUrl
88
- };
89
- retainedTabByUrl.set(normalizedUrl, normalizedTab);
82
+ const normalizedTab = { ...tab, url: normalizedUrl };
83
+ retainedTabByIdentity.set(identity, normalizedTab);
90
84
  retainedIdByOriginalId.set(tab.id, normalizedTab.id);
91
85
  });
92
- restoredState.tabsList = Array.from(retainedTabByUrl.values());
93
- restoredState.activeKey = retainedIdByOriginalId.get(restoredState.activeKey) || restoredState.tabsList[0]?.id || '';
86
+ restoredState.tabsList = Array.from(retainedTabByIdentity.values());
87
+ restoredState.activeKey = retainedIdByOriginalId.get(restoredState.activeKey) || ((_a = restoredState.tabsList[0]) == null ? void 0 : _a.id) || "";
94
88
  }
95
- restoredState.activeTabInfo = restoredState.tabsList.find(tab => tab.id === restoredState.activeKey);
96
- restoredState.activeComponent = restoredState.activeTabInfo ? restoredState.activeTabInfo.menuItem?.code || restoredState.activeTabInfo.id : '';
89
+ restoredState.activeTabInfo = restoredState.tabsList.find(
90
+ (tab) => tab.id === restoredState.activeKey
91
+ );
92
+ restoredState.activeComponent = restoredState.activeTabInfo ? ((_b = restoredState.activeTabInfo.menuItem) == null ? void 0 : _b.code) || restoredState.activeTabInfo.id : "";
97
93
  setState(restoredState);
98
94
  }
99
95
  setIsInitialized(true);
100
- }, [restoreFromCache, urlSyncEnabled]);
101
- const lastActiveKeyRef = useRef('');
96
+ }, [restoreFromCache, urlSyncEnabled, urlSyncIdentity]);
97
+ const lastActiveKeyRef = useRef("");
102
98
  const shouldSkipSaveRef = useRef(false);
103
99
  const initialTabsAppliedRef = useRef(false);
104
-
105
- // 保存状态到缓存
106
100
  useEffect(() => {
107
- if (!isInitialized) return;
108
-
109
- // 如果标记了跳过保存(清空缓存后),则跳过本次保存
101
+ if (!isInitialized)
102
+ return;
110
103
  if (shouldSkipSaveRef.current) {
111
104
  shouldSkipSaveRef.current = false;
112
105
  return;
113
106
  }
114
-
115
- // 处理 onTabChange 调用 - 支持空状态和正常切换
116
107
  if (finalConfig.onTabChange && lastActiveKeyRef.current !== state.activeKey) {
117
108
  lastActiveKeyRef.current = state.activeKey;
118
109
  if (state.activeKey) {
119
- // 正常的标签页切换
120
- const activeTab = state.tabsList.find(tab => tab.id === state.activeKey);
110
+ const activeTab = state.tabsList.find((tab) => tab.id === state.activeKey);
121
111
  if (activeTab) {
122
112
  finalConfig.onTabChange(state.activeKey, activeTab, state.tabsList);
123
113
  }
124
114
  } else {
125
- // 空状态 - 所有标签页都被关闭
126
- finalConfig.onTabChange('', undefined, state.tabsList);
115
+ finalConfig.onTabChange("", void 0, state.tabsList);
127
116
  }
128
117
  }
129
-
130
- // 如果 tabsList 为空且 activeKey 为空,说明是清空状态,不保存缓存
131
118
  if (state.tabsList.length === 0 && !state.activeKey) {
132
119
  return;
133
120
  }
134
-
135
- // 保存状态到缓存
136
121
  saveToCache(state);
137
122
  }, [state, saveToCache, finalConfig, isInitialized]);
138
-
139
- /**
140
- * 检查是否可以添加标签页(用于在菜单点击时判断是否应该激活菜单)
141
- */
142
- const canAddTab = useCallback((menuItem, options) => {
143
- const {
144
- forceNew = false
145
- } = options || {};
146
-
147
- // 非叶子节点默认不入签,仅根节点特例可入签
148
- if (!canOpenAsTab(menuItem)) {
149
- return false;
150
- }
151
-
152
- // 检查是否需要外部跳转
153
- if (shouldOpenExternal(menuItem)) {
154
- return false;
155
- }
156
-
157
- // URL 同步模式下完整 URL 始终唯一,forceNew 不能绕过身份匹配。
158
- if (urlSyncEnabled || !forceNew) {
159
- const existingTab = findExistingTab(state.tabsList, menuItem, {
160
- urlSync: urlSyncEnabled
161
- });
162
- if (existingTab) {
163
- // 如果已存在,可以添加(会切换到已存在的标签页)
164
- return true;
123
+ const canAddTab = useCallback(
124
+ (menuItem, options2) => {
125
+ const { forceNew = false } = options2 || {};
126
+ if (!canOpenAsTab(menuItem)) {
127
+ return false;
165
128
  }
166
- }
167
-
168
- // 检查是否超出限制(只有在需要创建新标签页时才检查)
169
- if (checkTabLimit(state.tabsList, finalConfig.max)) {
170
- // 达到最大值时,不能添加新标签页
171
- return false;
172
- }
173
- return true;
174
- }, [state.tabsList, finalConfig, urlSyncEnabled]);
175
-
176
- /**
177
- * 添加标签页
178
- */
179
- const addTab = useCallback((menuItem, options) => {
180
- const {
181
- forceNew = false,
182
- silent = false
183
- } = options || {};
184
- setState(prevState => {
185
- if (!canOpenAsTab(menuItem)) return prevState;
186
129
  if (shouldOpenExternal(menuItem)) {
187
- const externalUrl = getMenuRoute(menuItem);
188
- if (!urlSyncEnabled || isSafeHttpUrl(externalUrl)) {
189
- handleExternalOpen(menuItem, urlSyncEnabled);
190
- }
191
- return prevState;
130
+ return false;
192
131
  }
193
- const rawUrl = getMenuRoute(menuItem);
194
- const normalizedUrl = urlSyncEnabled ? normalizeTabUrl(rawUrl) : undefined;
195
- if (urlSyncEnabled && rawUrl && !normalizedUrl) {
196
- if (isSafeExternalUrl(rawUrl)) {
197
- handleExternalOpen(menuItem, true);
132
+ if (urlSyncEnabled || !forceNew) {
133
+ const existingTab = findExistingTab(state.tabsList, menuItem, {
134
+ urlSync: urlSyncEnabled,
135
+ identity: urlSyncIdentity
136
+ });
137
+ if (existingTab) {
138
+ return true;
198
139
  }
199
- return prevState;
200
140
  }
201
- const resolvedMenuItem = normalizedUrl ? {
202
- ...menuItem,
203
- url: normalizedUrl,
204
- redirectUrl: undefined
205
- } : menuItem;
206
-
207
- // 非强制新建时,查找已存在的标签页并切换
208
- const existingTab = urlSyncEnabled || !forceNew ? findExistingTab(prevState.tabsList, resolvedMenuItem, {
209
- urlSync: urlSyncEnabled
210
- }) : undefined;
211
- if (existingTab) {
212
- // 若来源菜单明确标记 closable: false 而已有 tab 未继承,则修正
213
- const correctedTab = resolvedMenuItem.closable === false && existingTab.closable !== false ? {
214
- ...existingTab,
215
- closable: false
216
- } : existingTab;
217
- const updatedTabsList = correctedTab !== existingTab ? prevState.tabsList.map(t => t.id === existingTab.id ? correctedTab : t) : prevState.tabsList;
141
+ if (checkTabLimit(state.tabsList, finalConfig.max)) {
142
+ return false;
143
+ }
144
+ return true;
145
+ },
146
+ [state.tabsList, finalConfig, urlSyncEnabled, urlSyncIdentity]
147
+ );
148
+ const addTab = useCallback(
149
+ (menuItem, options2) => {
150
+ const { forceNew = false, silent = false } = options2 || {};
151
+ setState((prevState) => {
152
+ var _a;
153
+ if (!canOpenAsTab(menuItem))
154
+ return prevState;
155
+ if (shouldOpenExternal(menuItem)) {
156
+ const externalUrl = getMenuRoute(menuItem);
157
+ if (!urlSyncEnabled || isSafeHttpUrl(externalUrl)) {
158
+ handleExternalOpen(menuItem, urlSyncEnabled);
159
+ }
160
+ return prevState;
161
+ }
162
+ const rawUrl = getMenuRoute(menuItem);
163
+ const normalizedUrl = urlSyncEnabled ? normalizeTabUrl(rawUrl) : void 0;
164
+ if (urlSyncEnabled && rawUrl && !normalizedUrl) {
165
+ if (isSafeExternalUrl(rawUrl)) {
166
+ handleExternalOpen(menuItem, true);
167
+ }
168
+ return prevState;
169
+ }
170
+ const resolvedMenuItem = normalizedUrl ? { ...menuItem, url: normalizedUrl, redirectUrl: void 0 } : menuItem;
171
+ const existingTab = urlSyncEnabled || !forceNew ? findExistingTab(prevState.tabsList, resolvedMenuItem, {
172
+ urlSync: urlSyncEnabled,
173
+ identity: urlSyncIdentity
174
+ }) : void 0;
175
+ if (existingTab) {
176
+ const shouldFixClosable = resolvedMenuItem.closable === false && existingTab.closable !== false;
177
+ const shouldUpdateUrl = urlSyncIdentity === "relationKey" && normalizedUrl !== void 0 && existingTab.url !== normalizedUrl;
178
+ const correctedTab = shouldFixClosable || shouldUpdateUrl ? {
179
+ ...existingTab,
180
+ ...shouldFixClosable ? { closable: false } : {},
181
+ ...shouldUpdateUrl ? { url: normalizedUrl } : {}
182
+ } : existingTab;
183
+ const updatedTabsList = correctedTab !== existingTab ? prevState.tabsList.map((t) => t.id === existingTab.id ? correctedTab : t) : prevState.tabsList;
184
+ return {
185
+ ...prevState,
186
+ tabsList: updatedTabsList,
187
+ activeKey: existingTab.id,
188
+ activeTabInfo: correctedTab,
189
+ activeComponent: ((_a = existingTab.menuItem) == null ? void 0 : _a.code) || existingTab.id
190
+ };
191
+ }
192
+ if (checkTabLimit(prevState.tabsList, finalConfig.max)) {
193
+ message.info(
194
+ formatMessage(locale.ProLayout.tabMaxLimitMessage, { max: finalConfig.max })
195
+ );
196
+ return prevState;
197
+ }
198
+ const existingIds = prevState.tabsList.map((tab) => tab.id);
199
+ const tabId = generateTabId(resolvedMenuItem, existingIds);
200
+ const newTab = createTabFromMenu(resolvedMenuItem, prevState.newTabIndex);
201
+ newTab.id = tabId;
202
+ const pinnedBoundary = getPinnedBoundary(prevState.tabsList);
203
+ const nextTabsList = derivePinned(newTab) ? [
204
+ ...prevState.tabsList.slice(0, pinnedBoundary),
205
+ newTab,
206
+ ...prevState.tabsList.slice(pinnedBoundary)
207
+ ] : [...prevState.tabsList, newTab];
208
+ const shouldActivate = !silent || prevState.activeKey === "";
218
209
  return {
219
210
  ...prevState,
220
- tabsList: updatedTabsList,
221
- activeKey: existingTab.id,
222
- activeTabInfo: correctedTab,
223
- activeComponent: existingTab.menuItem?.code || existingTab.id
211
+ tabsList: nextTabsList,
212
+ activeKey: shouldActivate ? tabId : prevState.activeKey,
213
+ activeTabInfo: shouldActivate ? newTab : prevState.activeTabInfo,
214
+ newTabIndex: prevState.newTabIndex + 1,
215
+ activeComponent: shouldActivate ? resolvedMenuItem.code || tabId : prevState.activeComponent
224
216
  };
225
- }
226
- if (checkTabLimit(prevState.tabsList, finalConfig.max)) {
227
- message.info(formatMessage(locale.ProLayout.tabMaxLimitMessage, {
228
- max: finalConfig.max
229
- }));
230
- return prevState;
231
- }
232
- const existingIds = prevState.tabsList.map(tab => tab.id);
233
- const tabId = generateTabId(resolvedMenuItem, existingIds);
234
- const newTab = createTabFromMenu(resolvedMenuItem, prevState.newTabIndex);
235
- newTab.id = tabId;
236
- const pinnedBoundary = getPinnedBoundary(prevState.tabsList);
237
- const nextTabsList = derivePinned(newTab) ? [...prevState.tabsList.slice(0, pinnedBoundary), newTab, ...prevState.tabsList.slice(pinnedBoundary)] : [...prevState.tabsList, newTab];
238
-
239
- // silent=true 时,若已有 active 则保留;无 active(首次进入)仍激活以保留默认行为
240
- const shouldActivate = !silent || prevState.activeKey === '';
241
- return {
242
- ...prevState,
243
- tabsList: nextTabsList,
244
- activeKey: shouldActivate ? tabId : prevState.activeKey,
245
- activeTabInfo: shouldActivate ? newTab : prevState.activeTabInfo,
246
- newTabIndex: prevState.newTabIndex + 1,
247
- activeComponent: shouldActivate ? resolvedMenuItem.code || tabId : prevState.activeComponent
248
- };
249
- });
250
- }, [finalConfig, urlSyncEnabled]);
251
-
252
- // 普通初始标签只在当前 TabsManager 挂载周期应用一次。
253
- // 缓存恢复已有标签时只消费默认值;closeAll 后 ref 保持 true,避免再次补签。
217
+ });
218
+ },
219
+ [finalConfig, urlSyncEnabled, urlSyncIdentity]
220
+ );
254
221
  useEffect(() => {
255
222
  const initialTabs = finalConfig.initialTabs;
256
223
  if (!isInitialized || !cacheEnabled || initialTabsAppliedRef.current || !initialTabs || initialTabs.length === 0) {
257
224
  return;
258
225
  }
259
226
  initialTabsAppliedRef.current = true;
260
- if (state.tabsList.length > 0) return;
261
- const sourceMenus = Array.isArray(dataSource?.menus) ? dataSource.menus : [];
262
- initialTabs.forEach(params => {
263
- addTab(resolveTabMenuItem(params, sourceMenus), {
264
- silent: true
265
- });
227
+ if (state.tabsList.length > 0)
228
+ return;
229
+ const sourceMenus = Array.isArray(dataSource == null ? void 0 : dataSource.menus) ? dataSource.menus : [];
230
+ initialTabs.forEach((params) => {
231
+ addTab(resolveTabMenuItem(params, sourceMenus), { silent: true });
266
232
  });
267
- }, [isInitialized, cacheEnabled, finalConfig.initialTabs, dataSource, state.tabsList.length, addTab]);
268
-
269
- /**
270
- * 更新已存在标签页的展示信息(保持 tab.id 不变 → 子组件不会 unmount)
271
- * - 仅允许更新 name / icon / extra / closable
272
- * - extra 为替换语义(直接覆盖原 extra)
273
- * - tabId 不存在时 no-op
274
- */
233
+ }, [
234
+ isInitialized,
235
+ cacheEnabled,
236
+ finalConfig.initialTabs,
237
+ dataSource,
238
+ state.tabsList.length,
239
+ addTab
240
+ ]);
275
241
  const updateTab = useCallback((tabId, updates) => {
276
- setState(prevState => {
277
- const targetIndex = prevState.tabsList.findIndex(tab => tab.id === tabId);
278
- if (targetIndex === -1) return prevState;
242
+ setState((prevState) => {
243
+ const targetIndex = prevState.tabsList.findIndex((tab) => tab.id === tabId);
244
+ if (targetIndex === -1)
245
+ return prevState;
279
246
  const target = prevState.tabsList[targetIndex];
280
247
  const nextMenuItem = target.menuItem ? {
281
248
  ...target.menuItem,
282
- ...(updates.name !== undefined && {
283
- name: updates.name
284
- }),
285
- ...(updates.icon !== undefined && {
286
- icon: updates.icon
287
- }),
288
- ...(updates.extra !== undefined && {
289
- extra: updates.extra
290
- }),
291
- ...(updates.closable !== undefined && {
292
- closable: updates.closable
293
- }),
294
- ...(updates.pinned !== undefined && {
295
- pinned: updates.pinned
296
- })
249
+ ...updates.name !== void 0 && { name: updates.name },
250
+ ...updates.icon !== void 0 && { icon: updates.icon },
251
+ ...updates.extra !== void 0 && { extra: updates.extra },
252
+ ...updates.closable !== void 0 && { closable: updates.closable },
253
+ ...updates.pinned !== void 0 && { pinned: updates.pinned }
297
254
  } : target.menuItem;
298
255
  const nextTab = {
299
256
  ...target,
300
- ...(updates.name !== undefined && {
301
- name: updates.name,
302
- title: updates.name
303
- }),
304
- ...(updates.icon !== undefined && {
305
- icon: updates.icon
306
- }),
307
- ...(updates.closable !== undefined && {
308
- closable: updates.closable
309
- }),
310
- ...(updates.pinned !== undefined && {
311
- pinned: updates.pinned
312
- }),
257
+ ...updates.name !== void 0 && { name: updates.name, title: updates.name },
258
+ ...updates.icon !== void 0 && { icon: updates.icon },
259
+ ...updates.closable !== void 0 && { closable: updates.closable },
260
+ ...updates.pinned !== void 0 && { pinned: updates.pinned },
313
261
  menuItem: nextMenuItem
314
262
  };
315
263
  const newTabsList = [...prevState.tabsList];
@@ -321,105 +269,89 @@ export const useTabsState = options => {
321
269
  };
322
270
  });
323
271
  }, []);
324
-
325
- /**
326
- * 移除标签页
327
- */
328
- const removeTab = useCallback(tabId => {
329
- setState(prevState => {
330
- const tabToRemove = prevState.tabsList.find(tab => tab.id === tabId);
331
- if (!tabToRemove || !tabToRemove.closable) {
332
- return prevState;
333
- }
334
- const newTabs = prevState.tabsList.filter(tab => tab.id !== tabId);
335
- let newActiveKey = prevState.activeKey;
336
- let newActiveTabInfo = prevState.activeTabInfo;
337
- let newActiveComponent = prevState.activeComponent;
338
-
339
- // 如果移除的是当前活跃标签页,需要选择新的活跃标签页
340
- if (prevState.activeKey === tabId && newTabs.length > 0) {
341
- const currentIndex = prevState.tabsList.findIndex(tab => tab.id === tabId);
342
- const newActiveIndex = Math.min(currentIndex, newTabs.length - 1);
343
- newActiveTabInfo = newTabs[newActiveIndex];
344
- newActiveKey = newActiveTabInfo.id;
345
- newActiveComponent = newActiveTabInfo.menuItem?.code || newActiveTabInfo.id;
346
- } else if (prevState.activeKey === tabId) {
347
- // 如果删除后没有标签页了
348
- newActiveKey = '';
349
- newActiveTabInfo = undefined;
350
- newActiveComponent = '';
351
- }
352
-
353
- // 如果删除后没有标签页了,清空缓存
354
- if (newTabs.length === 0) {
355
- // 标记跳过下次保存,避免清空后又被重新保存
356
- shouldSkipSaveRef.current = true;
357
- clearCache();
358
-
359
- // 直接调用 onTabChange,因为 useEffect 会被跳过
360
- if (finalConfig.onTabChange) {
361
- setTimeout(() => {
362
- finalConfig.onTabChange('', undefined, []);
363
- }, 0);
272
+ const removeTab = useCallback(
273
+ (tabId) => {
274
+ setState((prevState) => {
275
+ var _a;
276
+ const tabToRemove = prevState.tabsList.find((tab) => tab.id === tabId);
277
+ if (!tabToRemove || !tabToRemove.closable) {
278
+ return prevState;
364
279
  }
365
- }
366
- return {
367
- ...prevState,
368
- tabsList: newTabs,
369
- activeKey: newActiveKey,
370
- activeTabInfo: newActiveTabInfo,
371
- activeComponent: newActiveComponent
372
- };
373
- });
374
- }, [clearCache, finalConfig]);
375
-
376
- /**
377
- * 切换标签页
378
- */
379
- const switchTab = useCallback(tabId => {
380
- setState(prevState => {
381
- const targetTab = prevState.tabsList.find(tab => tab.id === tabId);
382
- if (!targetTab) return prevState;
280
+ const newTabs = prevState.tabsList.filter((tab) => tab.id !== tabId);
281
+ let newActiveKey = prevState.activeKey;
282
+ let newActiveTabInfo = prevState.activeTabInfo;
283
+ let newActiveComponent = prevState.activeComponent;
284
+ if (prevState.activeKey === tabId && newTabs.length > 0) {
285
+ const currentIndex = prevState.tabsList.findIndex((tab) => tab.id === tabId);
286
+ const newActiveIndex = Math.min(currentIndex, newTabs.length - 1);
287
+ newActiveTabInfo = newTabs[newActiveIndex];
288
+ newActiveKey = newActiveTabInfo.id;
289
+ newActiveComponent = ((_a = newActiveTabInfo.menuItem) == null ? void 0 : _a.code) || newActiveTabInfo.id;
290
+ } else if (prevState.activeKey === tabId) {
291
+ newActiveKey = "";
292
+ newActiveTabInfo = void 0;
293
+ newActiveComponent = "";
294
+ }
295
+ if (newTabs.length === 0) {
296
+ shouldSkipSaveRef.current = true;
297
+ clearCache();
298
+ if (finalConfig.onTabChange) {
299
+ setTimeout(() => {
300
+ finalConfig.onTabChange("", void 0, []);
301
+ }, 0);
302
+ }
303
+ }
304
+ return {
305
+ ...prevState,
306
+ tabsList: newTabs,
307
+ activeKey: newActiveKey,
308
+ activeTabInfo: newActiveTabInfo,
309
+ activeComponent: newActiveComponent
310
+ };
311
+ });
312
+ },
313
+ [clearCache, finalConfig]
314
+ );
315
+ const switchTab = useCallback((tabId) => {
316
+ setState((prevState) => {
317
+ var _a;
318
+ const targetTab = prevState.tabsList.find((tab) => tab.id === tabId);
319
+ if (!targetTab)
320
+ return prevState;
383
321
  const newState = {
384
322
  ...prevState,
385
323
  activeKey: tabId,
386
324
  activeTabInfo: targetTab,
387
- activeComponent: targetTab.menuItem?.code || tabId
325
+ activeComponent: ((_a = targetTab.menuItem) == null ? void 0 : _a.code) || tabId
388
326
  };
389
327
  return newState;
390
328
  });
391
329
  }, []);
392
-
393
- /**
394
- * Router blocker 拒绝 URL 导航时,将激活状态还原到上一个已提交页签。
395
- * 首次打开页签就被拦截时,同时移除未提交的新页签。
396
- */
397
- const rollbackTabActivation = useCallback((previousTabId, attemptedTabId, removeAttemptedTab) => {
398
- setState(prevState => {
399
- if (prevState.activeKey !== attemptedTabId) return prevState;
400
- const nextTabsList = removeAttemptedTab ? prevState.tabsList.filter(tab => tab.id !== attemptedTabId) : prevState.tabsList;
401
- const previousTab = nextTabsList.find(tab => tab.id === previousTabId);
402
- return {
403
- ...prevState,
404
- tabsList: nextTabsList,
405
- activeKey: previousTab?.id || '',
406
- activeTabInfo: previousTab,
407
- activeComponent: previousTab ? previousTab.menuItem?.code || previousTab.id : ''
408
- };
409
- });
410
- }, []);
411
-
412
- /**
413
- * 更新页签当前 URL,保持 tab.id 和 menuItem 的菜单基础路由不变。
414
- */
330
+ const rollbackTabActivation = useCallback(
331
+ (previousTabId, attemptedTabId, removeAttemptedTab) => {
332
+ setState((prevState) => {
333
+ var _a;
334
+ if (prevState.activeKey !== attemptedTabId)
335
+ return prevState;
336
+ const nextTabsList = removeAttemptedTab ? prevState.tabsList.filter((tab) => tab.id !== attemptedTabId) : prevState.tabsList;
337
+ const previousTab = nextTabsList.find((tab) => tab.id === previousTabId);
338
+ return {
339
+ ...prevState,
340
+ tabsList: nextTabsList,
341
+ activeKey: (previousTab == null ? void 0 : previousTab.id) || "",
342
+ activeTabInfo: previousTab,
343
+ activeComponent: previousTab ? ((_a = previousTab.menuItem) == null ? void 0 : _a.code) || previousTab.id : ""
344
+ };
345
+ });
346
+ },
347
+ []
348
+ );
415
349
  const updateTabUrl = useCallback((tabId, url) => {
416
- setState(prevState => {
417
- const targetIndex = prevState.tabsList.findIndex(tab => tab.id === tabId);
418
- if (targetIndex === -1 || prevState.tabsList[targetIndex].url === url) return prevState;
419
- const nextTab = {
420
- ...prevState.tabsList[targetIndex],
421
- url
422
- };
350
+ setState((prevState) => {
351
+ const targetIndex = prevState.tabsList.findIndex((tab) => tab.id === tabId);
352
+ if (targetIndex === -1 || prevState.tabsList[targetIndex].url === url)
353
+ return prevState;
354
+ const nextTab = { ...prevState.tabsList[targetIndex], url };
423
355
  const nextTabsList = [...prevState.tabsList];
424
356
  nextTabsList[targetIndex] = nextTab;
425
357
  return {
@@ -429,150 +361,113 @@ export const useTabsState = options => {
429
361
  };
430
362
  });
431
363
  }, []);
432
-
433
- /**
434
- * 关闭其他标签页
435
- */
436
- const closeOtherTabs = useCallback(currentTabId => {
437
- setState(prevState => {
438
- const currentTab = prevState.tabsList.find(tab => tab.id === currentTabId);
439
- if (!currentTab) return prevState;
440
-
441
- // 只保留当前标签页和不可关闭的标签页
442
- const newTabs = prevState.tabsList.filter(tab => tab.id === currentTabId || !tab.closable);
364
+ const closeOtherTabs = useCallback((currentTabId) => {
365
+ setState((prevState) => {
366
+ var _a;
367
+ const currentTab = prevState.tabsList.find((tab) => tab.id === currentTabId);
368
+ if (!currentTab)
369
+ return prevState;
370
+ const newTabs = prevState.tabsList.filter((tab) => tab.id === currentTabId || !tab.closable);
443
371
  return {
444
372
  ...prevState,
445
373
  tabsList: newTabs,
446
374
  activeKey: currentTabId,
447
375
  activeTabInfo: currentTab,
448
- activeComponent: currentTab.menuItem?.code || currentTabId
376
+ activeComponent: ((_a = currentTab.menuItem) == null ? void 0 : _a.code) || currentTabId
449
377
  };
450
378
  });
451
379
  }, []);
452
-
453
- /**
454
- * 关闭右侧标签页
455
- */
456
- const closeRightTabs = useCallback(currentTabId => {
457
- setState(prevState => {
380
+ const closeRightTabs = useCallback((currentTabId) => {
381
+ setState((prevState) => {
458
382
  const rightTabs = getRightTabs(prevState.tabsList, currentTabId);
459
- const tabsToKeep = prevState.tabsList.filter(tab => !rightTabs.includes(tab) || !tab.closable);
383
+ const tabsToKeep = prevState.tabsList.filter(
384
+ (tab) => !rightTabs.includes(tab) || !tab.closable
385
+ );
460
386
  return {
461
387
  ...prevState,
462
388
  tabsList: tabsToKeep
463
389
  };
464
390
  });
465
391
  }, []);
466
-
467
- /**
468
- * 关闭全部标签页
469
- */
470
392
  const closeAllTabs = useCallback(() => {
471
- setState(prevState => {
472
- // 只保留不可关闭的标签页
473
- const newTabs = prevState.tabsList.filter(tab => !tab.closable);
474
- let newActiveKey = '';
475
- let newActiveComponent = '';
393
+ setState((prevState) => {
394
+ var _a;
395
+ const newTabs = prevState.tabsList.filter((tab) => !tab.closable);
396
+ let newActiveKey = "";
397
+ let newActiveComponent = "";
476
398
  if (newTabs.length > 0) {
477
399
  const firstTab = newTabs[0];
478
400
  newActiveKey = firstTab.id;
479
- newActiveComponent = firstTab.menuItem?.code || firstTab.id;
401
+ newActiveComponent = ((_a = firstTab.menuItem) == null ? void 0 : _a.code) || firstTab.id;
480
402
  }
481
-
482
- // 关闭全部标签页时,清空缓存
483
- // 标记跳过下次保存,避免清空后又被重新保存
484
403
  shouldSkipSaveRef.current = true;
485
404
  clearCache();
486
-
487
- // 直接调用 onTabChange(useEffect 因 shouldSkipSaveRef 会跳过)
488
405
  if (finalConfig.onTabChange) {
489
- const firstTab = newTabs.length > 0 ? newTabs[0] : undefined;
406
+ const firstTab = newTabs.length > 0 ? newTabs[0] : void 0;
490
407
  setTimeout(() => {
491
- finalConfig.onTabChange(firstTab?.id ?? '', firstTab, newTabs);
408
+ finalConfig.onTabChange((firstTab == null ? void 0 : firstTab.id) ?? "", firstTab, newTabs);
492
409
  }, 0);
493
410
  }
494
411
  return {
495
412
  ...prevState,
496
413
  tabsList: newTabs,
497
414
  activeKey: newActiveKey,
498
- activeTabInfo: newTabs.length > 0 ? newTabs[0] : undefined,
415
+ activeTabInfo: newTabs.length > 0 ? newTabs[0] : void 0,
499
416
  activeComponent: newActiveComponent
500
417
  };
501
418
  });
502
419
  }, [clearCache, finalConfig]);
503
-
504
- /**
505
- * 重排标签页顺序(拖拽结束后调用)
506
- * 应用固定分区约束:普通标签不可拖入固定区、固定标签不可拖出固定区
507
- */
508
420
  const reorderTabs = useCallback((activeId, overId) => {
509
- setState(prevState => {
421
+ setState((prevState) => {
510
422
  const nextTabsList = reorderWithPinConstraint(prevState.tabsList, activeId, overId);
511
- if (nextTabsList === prevState.tabsList) return prevState;
512
- return {
513
- ...prevState,
514
- tabsList: nextTabsList
515
- };
423
+ if (nextTabsList === prevState.tabsList)
424
+ return prevState;
425
+ return { ...prevState, tabsList: nextTabsList };
516
426
  });
517
427
  }, []);
518
-
519
- /**
520
- * 固定标签页:设为 pinned/不可关闭并移动到固定区末尾
521
- */
522
- const pinTab = useCallback(tabId => {
523
- setState(prevState => {
428
+ const pinTab = useCallback((tabId) => {
429
+ setState((prevState) => {
524
430
  const nextTabsList = pinTabInList(prevState.tabsList, tabId);
525
- if (nextTabsList === prevState.tabsList) return prevState;
526
- const nextActiveTabInfo = prevState.activeKey === tabId ? nextTabsList.find(tab => tab.id === tabId) : prevState.activeTabInfo;
527
- return {
528
- ...prevState,
529
- tabsList: nextTabsList,
530
- activeTabInfo: nextActiveTabInfo
531
- };
431
+ if (nextTabsList === prevState.tabsList)
432
+ return prevState;
433
+ const nextActiveTabInfo = prevState.activeKey === tabId ? nextTabsList.find((tab) => tab.id === tabId) : prevState.activeTabInfo;
434
+ return { ...prevState, tabsList: nextTabsList, activeTabInfo: nextActiveTabInfo };
532
435
  });
533
436
  }, []);
534
-
535
- /**
536
- * 取消固定标签页:设为可关闭并移动到普通区最前
537
- */
538
- const unpinTab = useCallback(tabId => {
539
- setState(prevState => {
437
+ const unpinTab = useCallback((tabId) => {
438
+ setState((prevState) => {
540
439
  const nextTabsList = unpinTabInList(prevState.tabsList, tabId);
541
- if (nextTabsList === prevState.tabsList) return prevState;
542
- const nextActiveTabInfo = prevState.activeKey === tabId ? nextTabsList.find(tab => tab.id === tabId) : prevState.activeTabInfo;
543
- return {
544
- ...prevState,
545
- tabsList: nextTabsList,
546
- activeTabInfo: nextActiveTabInfo
547
- };
440
+ if (nextTabsList === prevState.tabsList)
441
+ return prevState;
442
+ const nextActiveTabInfo = prevState.activeKey === tabId ? nextTabsList.find((tab) => tab.id === tabId) : prevState.activeTabInfo;
443
+ return { ...prevState, tabsList: nextTabsList, activeTabInfo: nextActiveTabInfo };
548
444
  });
549
445
  }, []);
550
-
551
- /**
552
- * 重置状态
553
- */
554
446
  const resetTabs = useCallback(() => {
555
447
  setState({
556
448
  tabsList: [],
557
- activeKey: '',
449
+ activeKey: "",
558
450
  newTabIndex: 0,
559
- activeComponent: ''
451
+ activeComponent: ""
560
452
  });
561
453
  }, []);
562
-
563
- // URL 不同步模式保留旧有的 pathname -> Tabs 初始匹配,但不写回 URL。
564
454
  useEffect(() => {
565
- if (urlSyncEnabled) return;
566
- if (!dataSource || !('menus' in dataSource)) return;
455
+ if (urlSyncEnabled)
456
+ return;
457
+ if (!dataSource || !("menus" in dataSource))
458
+ return;
567
459
  const currentPath = window.location.pathname;
568
- const activeTab = state.tabsList.find(tab => tab.id === state.activeKey);
569
- if (activeTab && activeTab.url === currentPath) return;
460
+ const activeTab = state.tabsList.find((tab) => tab.id === state.activeKey);
461
+ if (activeTab && activeTab.url === currentPath)
462
+ return;
570
463
  const flatMenus = flattenMenuData(dataSource.menus || []);
571
- const targetMenu = flatMenus.find(item => getMenuRoute(item) === currentPath);
572
- if (!targetMenu || !canOpenAsTab(targetMenu)) return;
464
+ const targetMenu = flatMenus.find((item) => getMenuRoute(item) === currentPath);
465
+ if (!targetMenu || !canOpenAsTab(targetMenu))
466
+ return;
573
467
  const existingTab = findExistingTab(state.tabsList, targetMenu);
574
468
  if (existingTab) {
575
- if (state.activeKey !== existingTab.id) switchTab(existingTab.id);
469
+ if (state.activeKey !== existingTab.id)
470
+ switchTab(existingTab.id);
576
471
  return;
577
472
  }
578
473
  addTab(targetMenu);
@@ -595,4 +490,7 @@ export const useTabsState = options => {
595
490
  pinTab,
596
491
  unpinTab
597
492
  };
598
- };
493
+ };
494
+ export {
495
+ useTabsState
496
+ };