mall-components 1.0.0

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 (122) hide show
  1. package/README.md +128 -0
  2. package/build/_components-raw.css +791 -0
  3. package/build/_shims/antd.js +1 -0
  4. package/build/_shims/icons.js +1 -0
  5. package/build/_shims/moment.js +1 -0
  6. package/build/_shims/react-dom.js +1 -0
  7. package/build/_shims/react.js +1 -0
  8. package/build/adapters/DataSourceAdapter.d.ts +46 -0
  9. package/build/components/AdminLayout/AdminLayout.d.ts +5 -0
  10. package/build/components/AdminLayout/Breadcrumb.d.ts +8 -0
  11. package/build/components/AdminLayout/MainContent.d.ts +17 -0
  12. package/build/components/AdminLayout/Navbar.d.ts +10 -0
  13. package/build/components/AdminLayout/Sidebar.d.ts +14 -0
  14. package/build/components/AdminLayout/TabBar.d.ts +13 -0
  15. package/build/components/AdminLayout/TabPane.d.ts +4 -0
  16. package/build/components/AdminLayout/index.d.ts +3 -0
  17. package/build/components/AdminLayout/types.d.ts +42 -0
  18. package/build/components/CouponCard/CouponCard.d.ts +20 -0
  19. package/build/components/CouponCard/index.d.ts +1 -0
  20. package/build/components/OrderForm/OrderForm.d.ts +18 -0
  21. package/build/components/OrderForm/index.d.ts +1 -0
  22. package/build/components/OrderList/OrderList.d.ts +29 -0
  23. package/build/components/OrderList/index.d.ts +1 -0
  24. package/build/components/ProductForm/ProductForm.d.ts +18 -0
  25. package/build/components/ProductForm/index.d.ts +3 -0
  26. package/build/components/ProductList/ProductList.d.ts +47 -0
  27. package/build/components/ProductList/index.d.ts +3 -0
  28. package/build/components/PromotionCard/PromotionCard.d.ts +22 -0
  29. package/build/components/PromotionCard/index.d.ts +1 -0
  30. package/build/components/RoleCard/RoleCard.d.ts +18 -0
  31. package/build/components/RoleCard/index.d.ts +1 -0
  32. package/build/components/UserCard/UserCard.d.ts +17 -0
  33. package/build/components/UserCard/index.d.ts +1 -0
  34. package/build/entry-meta.d.ts +603 -0
  35. package/build/index.css +1 -0
  36. package/build/index.js +1 -0
  37. package/build/mall-components-meta.js +2563 -0
  38. package/build/mall-components.cdn.umd.css +1 -0
  39. package/build/mall-components.cdn.umd.js +8 -0
  40. package/build/mall-components.codesandbox.combined.js +1094 -0
  41. package/build/mall-components.codesandbox.css +401 -0
  42. package/build/mall-components.codesandbox.js +1080 -0
  43. package/build/mall-components.umd.css +1 -0
  44. package/build/mall-components.umd.js +8 -0
  45. package/build/meta/adminLayoutMeta.d.ts +3 -0
  46. package/build/meta/couponCardMeta.d.ts +128 -0
  47. package/build/meta/icons.d.ts +10 -0
  48. package/build/meta/orderFormMeta.d.ts +111 -0
  49. package/build/meta/orderListMeta.d.ts +170 -0
  50. package/build/meta/productFormMeta.d.ts +3 -0
  51. package/build/meta/productListMeta.d.ts +200 -0
  52. package/build/meta/promotionCardMeta.d.ts +129 -0
  53. package/build/meta/roleCardMeta.d.ts +3 -0
  54. package/build/meta/tabPaneMeta.d.ts +3 -0
  55. package/build/meta/userCardMeta.d.ts +3 -0
  56. package/build/meta.d.ts +605 -0
  57. package/build/setters/RestApiTester.d.ts +11 -0
  58. package/build/types/common.d.ts +17 -0
  59. package/build/types/marketing.d.ts +128 -0
  60. package/build/types/order.d.ts +174 -0
  61. package/build/types/permission.d.ts +101 -0
  62. package/build/types/product.d.ts +47 -0
  63. package/package.json +1 -0
  64. package/src/adapters/DataSourceAdapter.ts +445 -0
  65. package/src/components/AdminLayout/AdminLayout.scss +447 -0
  66. package/src/components/AdminLayout/AdminLayout.tsx +681 -0
  67. package/src/components/AdminLayout/Breadcrumb.tsx +60 -0
  68. package/src/components/AdminLayout/MainContent.tsx +54 -0
  69. package/src/components/AdminLayout/Navbar.tsx +76 -0
  70. package/src/components/AdminLayout/Sidebar.tsx +256 -0
  71. package/src/components/AdminLayout/TabBar.tsx +177 -0
  72. package/src/components/AdminLayout/TabPane.tsx +29 -0
  73. package/src/components/AdminLayout/index.ts +3 -0
  74. package/src/components/AdminLayout/types.ts +46 -0
  75. package/src/components/CouponCard/CouponCard.scss +55 -0
  76. package/src/components/CouponCard/CouponCard.tsx +687 -0
  77. package/src/components/CouponCard/index.ts +1 -0
  78. package/src/components/OrderForm/OrderForm.scss +148 -0
  79. package/src/components/OrderForm/OrderForm.tsx +503 -0
  80. package/src/components/OrderForm/index.ts +1 -0
  81. package/src/components/OrderList/OrderList.scss +160 -0
  82. package/src/components/OrderList/OrderList.tsx +885 -0
  83. package/src/components/OrderList/index.ts +1 -0
  84. package/src/components/ProductForm/ProductForm.scss +23 -0
  85. package/src/components/ProductForm/ProductForm.tsx +442 -0
  86. package/src/components/ProductForm/index.ts +3 -0
  87. package/src/components/ProductList/ProductList.scss +293 -0
  88. package/src/components/ProductList/ProductList.tsx +454 -0
  89. package/src/components/ProductList/index.ts +3 -0
  90. package/src/components/PromotionCard/PromotionCard.scss +71 -0
  91. package/src/components/PromotionCard/PromotionCard.tsx +579 -0
  92. package/src/components/PromotionCard/index.ts +1 -0
  93. package/src/components/RoleCard/RoleCard.scss +77 -0
  94. package/src/components/RoleCard/RoleCard.tsx +463 -0
  95. package/src/components/RoleCard/index.ts +1 -0
  96. package/src/components/UserCard/UserCard.scss +51 -0
  97. package/src/components/UserCard/UserCard.tsx +432 -0
  98. package/src/components/UserCard/index.ts +1 -0
  99. package/src/entry-components.ts +39 -0
  100. package/src/entry-meta.ts +23 -0
  101. package/src/index.scss +4 -0
  102. package/src/index.ts +36 -0
  103. package/src/index.tsx +17 -0
  104. package/src/meta/adminLayoutMeta.ts +154 -0
  105. package/src/meta/couponCardMeta.ts +287 -0
  106. package/src/meta/icons.ts +41 -0
  107. package/src/meta/orderFormMeta.ts +279 -0
  108. package/src/meta/orderListMeta.ts +443 -0
  109. package/src/meta/productFormMeta.ts +253 -0
  110. package/src/meta/productListMeta.ts +434 -0
  111. package/src/meta/promotionCardMeta.ts +276 -0
  112. package/src/meta/roleCardMeta.ts +142 -0
  113. package/src/meta/tabPaneMeta.ts +69 -0
  114. package/src/meta/userCardMeta.ts +128 -0
  115. package/src/meta.ts +25 -0
  116. package/src/setters/RestApiTester.tsx +219 -0
  117. package/src/shims/require.js +8 -0
  118. package/src/types/common.ts +19 -0
  119. package/src/types/marketing.ts +124 -0
  120. package/src/types/order.ts +169 -0
  121. package/src/types/permission.ts +102 -0
  122. package/src/types/product.ts +49 -0
@@ -0,0 +1,1080 @@
1
+ // src/components/AdminLayout/AdminLayout.tsx
2
+ import React6, { useState as useState3, useCallback, useMemo, useEffect as useEffect2, useRef as useRef2, Children, isValidElement } from "react";
3
+
4
+ // src/components/AdminLayout/Sidebar.tsx
5
+ import React, { useState } from "react";
6
+ import { Menu, Tag } from "antd";
7
+ import {
8
+ UserOutlined,
9
+ SafetyCertificateOutlined,
10
+ ShoppingOutlined,
11
+ FileTextOutlined,
12
+ TeamOutlined,
13
+ SettingOutlined,
14
+ TagsOutlined,
15
+ InboxOutlined,
16
+ DollarOutlined,
17
+ GiftOutlined,
18
+ ThunderboltOutlined,
19
+ FireOutlined,
20
+ DashboardOutlined
21
+ } from "@ant-design/icons";
22
+ var IS_CDN = false;
23
+ var { SubMenu } = Menu;
24
+ var defaultMenuItems = [
25
+ {
26
+ key: "dashboard",
27
+ label: "\u5DE5\u4F5C\u53F0",
28
+ icon: /* @__PURE__ */ React.createElement(DashboardOutlined, null),
29
+ path: "/dashboard"
30
+ },
31
+ {
32
+ key: "permission",
33
+ label: "\u6743\u9650\u7BA1\u7406",
34
+ icon: /* @__PURE__ */ React.createElement(SafetyCertificateOutlined, null),
35
+ children: [
36
+ {
37
+ key: "permission/users",
38
+ label: "\u7528\u6237\u7BA1\u7406",
39
+ icon: /* @__PURE__ */ React.createElement(UserOutlined, null),
40
+ path: "/permission/users"
41
+ },
42
+ {
43
+ key: "permission/roles",
44
+ label: "\u89D2\u8272\u7BA1\u7406",
45
+ icon: /* @__PURE__ */ React.createElement(TeamOutlined, null),
46
+ path: "/permission/roles"
47
+ },
48
+ {
49
+ key: "permission/resources",
50
+ label: "\u8D44\u6E90\u7BA1\u7406",
51
+ icon: /* @__PURE__ */ React.createElement(SettingOutlined, null),
52
+ path: "/permission/resources"
53
+ },
54
+ {
55
+ key: "permission/menus",
56
+ label: "\u83DC\u5355\u7BA1\u7406",
57
+ icon: /* @__PURE__ */ React.createElement(FileTextOutlined, null),
58
+ path: "/permission/menus"
59
+ }
60
+ ]
61
+ },
62
+ {
63
+ key: "product",
64
+ label: "\u5546\u54C1\u7BA1\u7406",
65
+ icon: /* @__PURE__ */ React.createElement(ShoppingOutlined, null),
66
+ children: [
67
+ {
68
+ key: "product/list",
69
+ label: "\u5546\u54C1\u5217\u8868",
70
+ icon: /* @__PURE__ */ React.createElement(InboxOutlined, null),
71
+ path: "/product/list"
72
+ },
73
+ {
74
+ key: "product/add",
75
+ label: "\u6DFB\u52A0\u5546\u54C1",
76
+ icon: /* @__PURE__ */ React.createElement(ShoppingOutlined, null),
77
+ path: "/product/add"
78
+ },
79
+ {
80
+ key: "product/category",
81
+ label: "\u5546\u54C1\u5206\u7C7B",
82
+ icon: /* @__PURE__ */ React.createElement(TagsOutlined, null),
83
+ path: "/product/category"
84
+ },
85
+ {
86
+ key: "product/brand",
87
+ label: "\u54C1\u724C\u7BA1\u7406",
88
+ path: "/product/brand"
89
+ },
90
+ {
91
+ key: "product/attribute",
92
+ label: "\u5546\u54C1\u5C5E\u6027",
93
+ path: "/product/attribute"
94
+ }
95
+ ]
96
+ },
97
+ {
98
+ key: "order",
99
+ label: "\u8BA2\u5355\u7BA1\u7406",
100
+ icon: /* @__PURE__ */ React.createElement(FileTextOutlined, null),
101
+ children: [
102
+ {
103
+ key: "order/list",
104
+ label: "\u8BA2\u5355\u5217\u8868",
105
+ icon: /* @__PURE__ */ React.createElement(FileTextOutlined, null),
106
+ path: "/order/list"
107
+ },
108
+ {
109
+ key: "order/setting",
110
+ label: "\u8BA2\u5355\u8BBE\u7F6E",
111
+ icon: /* @__PURE__ */ React.createElement(SettingOutlined, null),
112
+ path: "/order/setting"
113
+ },
114
+ {
115
+ key: "order/return",
116
+ label: "\u9000\u8D27\u7533\u8BF7",
117
+ path: "/order/return"
118
+ },
119
+ {
120
+ key: "order/reason",
121
+ label: "\u9000\u8D27\u539F\u56E0",
122
+ path: "/order/reason"
123
+ }
124
+ ]
125
+ },
126
+ {
127
+ key: "marketing",
128
+ label: "\u8425\u9500\u7BA1\u7406",
129
+ icon: /* @__PURE__ */ React.createElement(GiftOutlined, null),
130
+ children: [
131
+ {
132
+ key: "marketing/coupon",
133
+ label: "\u4F18\u60E0\u5238\u7BA1\u7406",
134
+ icon: /* @__PURE__ */ React.createElement(GiftOutlined, null),
135
+ path: "/marketing/coupon"
136
+ },
137
+ {
138
+ key: "marketing/promotion",
139
+ label: "\u4FC3\u9500\u6D3B\u52A8",
140
+ icon: /* @__PURE__ */ React.createElement(DollarOutlined, null),
141
+ path: "/marketing/promotion"
142
+ },
143
+ {
144
+ key: "marketing/flash",
145
+ label: "\u79D2\u6740\u6D3B\u52A8",
146
+ icon: /* @__PURE__ */ React.createElement(ThunderboltOutlined, null),
147
+ path: "/marketing/flash"
148
+ },
149
+ {
150
+ key: "marketing/new",
151
+ label: "\u65B0\u54C1\u63A8\u8350",
152
+ icon: /* @__PURE__ */ React.createElement(FireOutlined, null),
153
+ path: "/marketing/new"
154
+ },
155
+ {
156
+ key: "marketing/hot",
157
+ label: "\u4EBA\u6C14\u63A8\u8350",
158
+ icon: /* @__PURE__ */ React.createElement(FireOutlined, null),
159
+ path: "/marketing/hot"
160
+ },
161
+ {
162
+ key: "marketing/advertise",
163
+ label: "\u5E7F\u544A\u7BA1\u7406",
164
+ path: "/marketing/advertise"
165
+ },
166
+ {
167
+ key: "marketing/subject",
168
+ label: "\u4E13\u9898\u7BA1\u7406",
169
+ path: "/marketing/subject"
170
+ },
171
+ {
172
+ key: "marketing/brand",
173
+ label: "\u54C1\u724C\u63A8\u8350",
174
+ path: "/marketing/brand"
175
+ }
176
+ ]
177
+ }
178
+ ];
179
+ var Sidebar = ({
180
+ collapsed,
181
+ selectedKey,
182
+ openKeys,
183
+ onMenuClick,
184
+ onOpenChange,
185
+ menuItems: customMenuItems
186
+ }) => {
187
+ const items = customMenuItems || defaultMenuItems;
188
+ const [internalOpenKeys, setInternalOpenKeys] = useState(
189
+ items.filter((item) => item.children).map((item) => item.key)
190
+ );
191
+ const handleOpenChange = (keys) => {
192
+ const latestKey = keys[keys.length - 1];
193
+ if (latestKey && items.some((item) => item.key === latestKey)) {
194
+ setInternalOpenKeys(keys);
195
+ onOpenChange(keys);
196
+ } else {
197
+ setInternalOpenKeys(latestKey ? [latestKey] : []);
198
+ onOpenChange(latestKey ? [latestKey] : []);
199
+ }
200
+ };
201
+ const handleClick = ({ key }) => {
202
+ onMenuClick(key);
203
+ };
204
+ return /* @__PURE__ */ React.createElement("div", { className: `sidebar-container ${collapsed ? "collapsed" : ""}` }, /* @__PURE__ */ React.createElement("div", { className: "sidebar-logo" }, !collapsed && /* @__PURE__ */ React.createElement("span", { className: "logo-text" }, "Mall Admin@", IS_CDN && /* @__PURE__ */ React.createElement(Tag, { color: "orange", style: { marginLeft: 8, fontSize: 10 } }, "CDN")), collapsed && /* @__PURE__ */ React.createElement("span", { className: "logo-icon" }, "M")), /* @__PURE__ */ React.createElement(
205
+ Menu,
206
+ {
207
+ mode: "inline",
208
+ theme: "dark",
209
+ inlineCollapsed: collapsed,
210
+ selectedKeys: [selectedKey],
211
+ defaultOpenKeys: internalOpenKeys,
212
+ openKeys: openKeys.length > 0 ? openKeys : internalOpenKeys,
213
+ onClick: handleClick,
214
+ onOpenChange: handleOpenChange,
215
+ items: items.map((item) => {
216
+ if (item.children && item.children.length > 0) {
217
+ return {
218
+ key: item.key,
219
+ icon: item.icon,
220
+ label: item.label,
221
+ children: item.children.map((child) => ({
222
+ key: child.key,
223
+ icon: child.icon,
224
+ label: child.label
225
+ }))
226
+ };
227
+ }
228
+ return {
229
+ key: item.key,
230
+ icon: item.icon,
231
+ label: item.label
232
+ };
233
+ })
234
+ }
235
+ ));
236
+ };
237
+ var Sidebar_default = Sidebar;
238
+
239
+ // src/components/AdminLayout/Navbar.tsx
240
+ import React3 from "react";
241
+ import { Dropdown, Avatar, Space, Menu as Menu2 } from "antd";
242
+ import {
243
+ MenuFoldOutlined,
244
+ MenuUnfoldOutlined,
245
+ UserOutlined as UserOutlined2,
246
+ SettingOutlined as SettingOutlined2,
247
+ LogoutOutlined
248
+ } from "@ant-design/icons";
249
+
250
+ // src/components/AdminLayout/Breadcrumb.tsx
251
+ import React2 from "react";
252
+ import { Breadcrumb } from "antd";
253
+ var labelMap = {
254
+ dashboard: "\u5DE5\u4F5C\u53F0",
255
+ permission: "\u6743\u9650\u7BA1\u7406",
256
+ product: "\u5546\u54C1\u7BA1\u7406",
257
+ order: "\u8BA2\u5355\u7BA1\u7406",
258
+ marketing: "\u8425\u9500\u7BA1\u7406",
259
+ users: "\u7528\u6237\u7BA1\u7406",
260
+ roles: "\u89D2\u8272\u7BA1\u7406",
261
+ resources: "\u8D44\u6E90\u7BA1\u7406",
262
+ menus: "\u83DC\u5355\u7BA1\u7406",
263
+ list: "\u5217\u8868",
264
+ add: "\u6DFB\u52A0",
265
+ category: "\u5206\u7C7B",
266
+ brand: "\u54C1\u724C",
267
+ attribute: "\u5C5E\u6027",
268
+ setting: "\u8BBE\u7F6E",
269
+ return: "\u9000\u8D27",
270
+ reason: "\u539F\u56E0",
271
+ coupon: "\u4F18\u60E0\u5238",
272
+ promotion: "\u4FC3\u9500",
273
+ flash: "\u79D2\u6740",
274
+ new: "\u65B0\u54C1",
275
+ hot: "\u4EBA\u6C14",
276
+ advertise: "\u5E7F\u544A",
277
+ subject: "\u4E13\u9898"
278
+ };
279
+ var BreadcrumbNav = ({ items, onNavigate }) => {
280
+ const getLabel = (key) => {
281
+ const parts = key.split("/");
282
+ return parts.map((part) => labelMap[part] || part).join(" / ");
283
+ };
284
+ if (!items || items.length === 0) {
285
+ return null;
286
+ }
287
+ return /* @__PURE__ */ React2.createElement(Breadcrumb, null, items.map((item) => /* @__PURE__ */ React2.createElement(Breadcrumb.Item, { key: item.key }, /* @__PURE__ */ React2.createElement("a", { onClick: () => onNavigate(item.key) }, item.label || getLabel(item.key)))));
288
+ };
289
+ var Breadcrumb_default = BreadcrumbNav;
290
+
291
+ // src/components/AdminLayout/Navbar.tsx
292
+ var Navbar = ({ collapsed, onToggleCollapse, breadcrumbItems, onNavigate }) => {
293
+ const userMenuItems = [
294
+ {
295
+ key: "profile",
296
+ icon: /* @__PURE__ */ React3.createElement(UserOutlined2, null),
297
+ label: "\u4E2A\u4EBA\u4E2D\u5FC3"
298
+ },
299
+ {
300
+ key: "settings",
301
+ icon: /* @__PURE__ */ React3.createElement(SettingOutlined2, null),
302
+ label: "\u7CFB\u7EDF\u8BBE\u7F6E"
303
+ },
304
+ {
305
+ type: "divider"
306
+ },
307
+ {
308
+ key: "logout",
309
+ icon: /* @__PURE__ */ React3.createElement(LogoutOutlined, null),
310
+ label: "\u9000\u51FA\u767B\u5F55",
311
+ danger: true
312
+ }
313
+ ];
314
+ const handleUserMenuClick = ({ key }) => {
315
+ if (key === "logout") {
316
+ console.log("User logged out");
317
+ }
318
+ };
319
+ const menu = /* @__PURE__ */ React3.createElement(Menu2, { items: userMenuItems, onClick: handleUserMenuClick });
320
+ return /* @__PURE__ */ React3.createElement("div", { className: "navbar-container" }, /* @__PURE__ */ React3.createElement("div", { className: "navbar-left" }, /* @__PURE__ */ React3.createElement("button", { className: "hamburger-btn", onClick: onToggleCollapse }, collapsed ? /* @__PURE__ */ React3.createElement(MenuUnfoldOutlined, null) : /* @__PURE__ */ React3.createElement(MenuFoldOutlined, null)), /* @__PURE__ */ React3.createElement(Breadcrumb_default, { items: breadcrumbItems, onNavigate })), /* @__PURE__ */ React3.createElement("div", { className: "navbar-right" }, /* @__PURE__ */ React3.createElement(Dropdown, { overlay: menu, placement: "bottomRight" }, /* @__PURE__ */ React3.createElement("div", { className: "user-info" }, /* @__PURE__ */ React3.createElement(Avatar, { size: 32, icon: /* @__PURE__ */ React3.createElement(UserOutlined2, null), className: "user-avatar" }), /* @__PURE__ */ React3.createElement(Space, { size: 4, className: "username" }, /* @__PURE__ */ React3.createElement("span", null, "\u7BA1\u7406\u5458"))))));
321
+ };
322
+ var Navbar_default = Navbar;
323
+
324
+ // src/components/AdminLayout/MainContent.tsx
325
+ import React5 from "react";
326
+
327
+ // src/components/AdminLayout/TabBar.tsx
328
+ import React4, { useState as useState2, useRef, useEffect } from "react";
329
+ import { Dropdown as Dropdown2, Menu as Menu3 } from "antd";
330
+ import { CloseOutlined, ReloadOutlined, CloseCircleOutlined } from "@ant-design/icons";
331
+ var TabBar = ({
332
+ tabs,
333
+ activeTabKey,
334
+ onTabClick,
335
+ onCloseTab,
336
+ onCloseOther,
337
+ onCloseAll,
338
+ closableTabs = true
339
+ }) => {
340
+ const [hoveredKey, setHoveredKey] = useState2(null);
341
+ const [contextMenuVisible, setContextMenuVisible] = useState2(false);
342
+ const [contextMenuKey, setContextMenuKey] = useState2("");
343
+ const [menuPosition, setMenuPosition] = useState2({ x: 0, y: 0 });
344
+ const scrollContainerRef = useRef(null);
345
+ useEffect(() => {
346
+ if (scrollContainerRef.current && activeTabKey) {
347
+ const activeElement = scrollContainerRef.current.querySelector(`[data-tab-key="${activeTabKey}"]`);
348
+ if (activeElement) {
349
+ activeElement.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "center" });
350
+ }
351
+ }
352
+ }, [activeTabKey]);
353
+ useEffect(() => {
354
+ const handleClick = () => setContextMenuVisible(false);
355
+ if (contextMenuVisible) {
356
+ document.addEventListener("click", handleClick);
357
+ return () => document.removeEventListener("click", handleClick);
358
+ }
359
+ }, [contextMenuVisible]);
360
+ const handleContextMenu = (e, tabKey) => {
361
+ e.preventDefault();
362
+ e.stopPropagation();
363
+ setContextMenuKey(tabKey);
364
+ setMenuPosition({ x: e.clientX, y: e.clientY });
365
+ setContextMenuVisible(true);
366
+ };
367
+ const handleMenuClick = (key) => {
368
+ setContextMenuVisible(false);
369
+ switch (key) {
370
+ case "close":
371
+ onCloseTab(contextMenuKey);
372
+ break;
373
+ case "closeOther":
374
+ onCloseOther(contextMenuKey);
375
+ break;
376
+ case "closeAll":
377
+ onCloseAll();
378
+ break;
379
+ case "refresh":
380
+ window.location.reload();
381
+ break;
382
+ }
383
+ };
384
+ if (!tabs || tabs.length === 0) {
385
+ return null;
386
+ }
387
+ const contextMenuItems = [
388
+ {
389
+ key: "refresh",
390
+ icon: /* @__PURE__ */ React4.createElement(ReloadOutlined, null),
391
+ label: "\u5237\u65B0\u5F53\u524D\u9875"
392
+ },
393
+ {
394
+ key: "close",
395
+ icon: /* @__PURE__ */ React4.createElement(CloseOutlined, null),
396
+ label: "\u5173\u95ED\u5F53\u524D",
397
+ disabled: !closableTabs || tabs.find((t) => t.key === contextMenuKey)?.closable === false
398
+ },
399
+ {
400
+ type: "divider"
401
+ },
402
+ {
403
+ key: "closeOther",
404
+ icon: /* @__PURE__ */ React4.createElement(CloseCircleOutlined, null),
405
+ label: "\u5173\u95ED\u5176\u4ED6",
406
+ disabled: tabs.length <= 1
407
+ },
408
+ {
409
+ key: "closeAll",
410
+ icon: /* @__PURE__ */ React4.createElement(CloseCircleOutlined, null),
411
+ label: "\u5173\u95ED\u6240\u6709"
412
+ }
413
+ ];
414
+ const menu = /* @__PURE__ */ React4.createElement(Menu3, { items: contextMenuItems, onClick: ({ key }) => handleMenuClick(key) });
415
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement("div", { className: "tab-bar-container" }, /* @__PURE__ */ React4.createElement("div", { className: "tab-bar-scroll", ref: scrollContainerRef }, tabs.map((tab) => /* @__PURE__ */ React4.createElement(
416
+ "div",
417
+ {
418
+ key: tab.key,
419
+ "data-tab-key": tab.key,
420
+ className: `tab-item ${activeTabKey === tab.key ? "active" : ""} ${hoveredKey === tab.key ? "hovered" : ""}`,
421
+ onClick: () => onTabClick(tab.key),
422
+ onMouseEnter: () => setHoveredKey(tab.key),
423
+ onMouseLeave: () => setHoveredKey(null),
424
+ onContextMenu: (e) => handleContextMenu(e, tab.key)
425
+ },
426
+ tab.icon && /* @__PURE__ */ React4.createElement("span", { className: "tab-icon" }, tab.icon),
427
+ /* @__PURE__ */ React4.createElement("span", { className: "tab-label" }, tab.label),
428
+ closableTabs && tab.closable && /* @__PURE__ */ React4.createElement(
429
+ "span",
430
+ {
431
+ className: `tab-close-btn ${hoveredKey === tab.key || activeTabKey === tab.key ? "visible" : ""}`,
432
+ onClick: (e) => {
433
+ e.stopPropagation();
434
+ onCloseTab(tab.key);
435
+ }
436
+ },
437
+ /* @__PURE__ */ React4.createElement(CloseOutlined, { style: { fontSize: 10 } })
438
+ )
439
+ ))), closableTabs && tabs.length > 1 && /* @__PURE__ */ React4.createElement("div", { className: "tab-actions" }, /* @__PURE__ */ React4.createElement(
440
+ "button",
441
+ {
442
+ className: "close-all-btn",
443
+ onClick: onCloseAll,
444
+ title: "\u5173\u95ED\u5168\u90E8\u6807\u7B7E"
445
+ },
446
+ /* @__PURE__ */ React4.createElement(CloseCircleOutlined, null)
447
+ ))), contextMenuVisible && /* @__PURE__ */ React4.createElement(
448
+ "div",
449
+ {
450
+ style: {
451
+ position: "fixed",
452
+ left: menuPosition.x,
453
+ top: menuPosition.y,
454
+ zIndex: 1e3
455
+ }
456
+ },
457
+ /* @__PURE__ */ React4.createElement(
458
+ Dropdown2,
459
+ {
460
+ overlay: menu,
461
+ visible: contextMenuVisible,
462
+ onVisibleChange: setContextMenuVisible,
463
+ trigger: ["click"]
464
+ },
465
+ /* @__PURE__ */ React4.createElement("div", { style: { width: 0, height: 0 } })
466
+ )
467
+ ));
468
+ };
469
+ var TabBar_default = TabBar;
470
+
471
+ // src/components/AdminLayout/MainContent.tsx
472
+ var MainContent = ({
473
+ children,
474
+ pageKey,
475
+ tabs,
476
+ activeTabKey,
477
+ onTabClick,
478
+ onCloseTab,
479
+ onCloseOther,
480
+ onCloseAll,
481
+ enableTabs = true,
482
+ closableTabs = true,
483
+ className = ""
484
+ }) => {
485
+ return /* @__PURE__ */ React5.createElement("main", { className: `main-content ${className}` }, enableTabs && tabs.length > 0 && /* @__PURE__ */ React5.createElement(
486
+ TabBar_default,
487
+ {
488
+ tabs,
489
+ activeTabKey,
490
+ onTabClick,
491
+ onCloseTab,
492
+ onCloseOther,
493
+ onCloseAll,
494
+ closableTabs
495
+ }
496
+ ), /* @__PURE__ */ React5.createElement("div", { className: "content-wrapper" }, /* @__PURE__ */ React5.createElement("div", { className: "page-container", key: pageKey }, children)));
497
+ };
498
+ var MainContent_default = MainContent;
499
+
500
+ // src/components/AdminLayout/AdminLayout.tsx
501
+ var SCENARIO_NAME = "general";
502
+ var saveSchemaToLocalStorage = () => {
503
+ try {
504
+ const engine = window.AliLowCodeEngine;
505
+ if (!engine?.project)
506
+ return;
507
+ const schema = engine.project.exportSchema("save");
508
+ const key = `${SCENARIO_NAME}:projectSchema`;
509
+ localStorage.setItem(key, JSON.stringify(schema));
510
+ console.log("[AdminLayout] \u{1F4BE} Schema saved to localStorage");
511
+ } catch (e) {
512
+ console.error("[AdminLayout] Failed to save schema:", e);
513
+ }
514
+ };
515
+ var findMenuItem = (items, key) => {
516
+ for (const item of items) {
517
+ if (item.key === key)
518
+ return item;
519
+ if (item.children) {
520
+ const found = findMenuItem(item.children, key);
521
+ if (found)
522
+ return found;
523
+ }
524
+ }
525
+ return void 0;
526
+ };
527
+ var getLabelFromKey = (key) => {
528
+ const parts = key.split("/");
529
+ const labelMap2 = {
530
+ dashboard: "\u5DE5\u4F5C\u53F0",
531
+ permission: "\u6743\u9650\u7BA1\u7406",
532
+ product: "\u5546\u54C1\u7BA1\u7406",
533
+ order: "\u8BA2\u5355\u7BA1\u7406",
534
+ marketing: "\u8425\u9500\u7BA1\u7406",
535
+ users: "\u7528\u6237\u7BA1\u7406",
536
+ roles: "\u89D2\u8272\u7BA1\u7406",
537
+ resources: "\u8D44\u6E90\u7BA1\u7406",
538
+ menus: "\u83DC\u5355\u7BA1\u7406",
539
+ list: "\u5217\u8868",
540
+ add: "\u6DFB\u52A0",
541
+ category: "\u5206\u7C7B",
542
+ brand: "\u54C1\u724C",
543
+ attribute: "\u5C5E\u6027",
544
+ setting: "\u8BBE\u7F6E",
545
+ return: "\u9000\u8D27\u7533\u8BF7",
546
+ reason: "\u9000\u8D27\u539F\u56E0",
547
+ coupon: "\u4F18\u60E0\u5238\u7BA1\u7406",
548
+ promotion: "\u4FC3\u9500\u6D3B\u52A8",
549
+ flash: "\u79D2\u6740\u6D3B\u52A8",
550
+ new: "\u65B0\u54C1\u63A8\u8350",
551
+ hot: "\u4EBA\u6C14\u63A8\u8350",
552
+ advertise: "\u5E7F\u544A\u7BA1\u7406",
553
+ subject: "\u4E13\u9898\u7BA1\u7406"
554
+ };
555
+ return labelMap2[parts[parts.length - 1]] || parts[parts.length - 1];
556
+ };
557
+ var AdminLayout = ({
558
+ defaultSelectedKey = "dashboard",
559
+ defaultOpenKeys,
560
+ collapsible = true,
561
+ enableTabs = true,
562
+ maxTabs = 10,
563
+ closableTabs = true,
564
+ logoText = "Mall Admin@",
565
+ menuItems: customMenuItems,
566
+ style,
567
+ className,
568
+ children,
569
+ __designMode,
570
+ componentId
571
+ }) => {
572
+ const items = customMenuItems || defaultMenuItems;
573
+ const [collapsed, setCollapsed] = useState3(false);
574
+ const [selectedKey, setSelectedKey] = useState3(defaultSelectedKey);
575
+ const [openKeys, setOpenKeys] = useState3(defaultOpenKeys || []);
576
+ const [tabs, setTabs] = useState3(() => {
577
+ const initialItem = findMenuItem(items, defaultSelectedKey);
578
+ return [{
579
+ key: defaultSelectedKey,
580
+ label: initialItem?.label || getLabelFromKey(defaultSelectedKey),
581
+ icon: initialItem?.icon,
582
+ closable: false,
583
+ path: initialItem?.path || `/${defaultSelectedKey}`
584
+ }];
585
+ });
586
+ const [activeTabKey, setActiveTabKey] = useState3(defaultSelectedKey);
587
+ const activeTabKeyRef = useRef2(activeTabKey);
588
+ activeTabKeyRef.current = activeTabKey;
589
+ const initializedRef = useRef2(false);
590
+ useEffect2(() => {
591
+ if (__designMode !== "design" || !componentId || initializedRef.current)
592
+ return;
593
+ const timer = setTimeout(() => {
594
+ try {
595
+ const engine = window.AliLowCodeEngine;
596
+ if (!engine?.project?.currentDocument)
597
+ return;
598
+ const documentModel = engine.project.currentDocument;
599
+ const adminLayoutNode = documentModel.getNodeById(componentId);
600
+ if (!adminLayoutNode) {
601
+ console.log("[AdminLayout] \u26A0\uFE0F AdminLayout node not found");
602
+ return;
603
+ }
604
+ const schemaChildren = adminLayoutNode.schema?.children || [];
605
+ console.log("[AdminLayout] \u{1F50D} Schema children:", schemaChildren.length, schemaChildren.map((c) => c.componentName));
606
+ const existingTabPanes = schemaChildren.filter((child) => child.componentName === "TabPane");
607
+ console.log("[AdminLayout] \u{1F50D} Found existing TabPanes:", existingTabPanes.length);
608
+ if (existingTabPanes.length > 0) {
609
+ const restoredTabs = existingTabPanes.map((tpSchema) => {
610
+ const tabKey = tpSchema.props?.tabKey || "unknown";
611
+ const tabLabel = tpSchema.props?.tab || getLabelFromKey(tabKey);
612
+ const menuItem = findMenuItem(items, tabKey);
613
+ console.log("[AdminLayout] \u{1F4CB} Restoring tab:", tabKey, tabLabel);
614
+ return {
615
+ key: tabKey,
616
+ label: tabLabel,
617
+ icon: menuItem?.icon,
618
+ closable: tabKey !== "dashboard",
619
+ path: menuItem?.path || `/${tabKey}`
620
+ };
621
+ });
622
+ console.log("[AdminLayout] \u{1F4CB} Restored tabs from schema:", restoredTabs.map((t) => t.key));
623
+ setTabs(restoredTabs);
624
+ const currentActiveTab = restoredTabs[restoredTabs.length - 1];
625
+ if (currentActiveTab) {
626
+ setActiveTabKey(currentActiveTab.key);
627
+ setSelectedKey(currentActiveTab.key);
628
+ }
629
+ } else {
630
+ console.log("[AdminLayout] \u{1F4CB} No TabPane found, creating default dashboard TabPane");
631
+ const tabPaneNode = documentModel.createNode({
632
+ componentName: "TabPane",
633
+ props: {
634
+ tab: "\u5DE5\u4F5C\u53F0",
635
+ tabKey: "dashboard",
636
+ activeTabKey: "dashboard"
637
+ }
638
+ });
639
+ if (tabPaneNode) {
640
+ documentModel.insertNode(adminLayoutNode, tabPaneNode);
641
+ console.log("[AdminLayout] \u2705 Created default TabPane for dashboard");
642
+ }
643
+ }
644
+ initializedRef.current = true;
645
+ } catch (e) {
646
+ console.error("[AdminLayout] Init TabPane error:", e);
647
+ }
648
+ }, 100);
649
+ return () => clearTimeout(timer);
650
+ }, [componentId, __designMode, items]);
651
+ useEffect2(() => {
652
+ if (__designMode !== "design")
653
+ return;
654
+ const engine = window.AliLowCodeEngine;
655
+ if (!engine?.project?.currentDocument)
656
+ return;
657
+ const documentModel = engine.project.currentDocument;
658
+ let saveTimer = null;
659
+ const debouncedSave = () => {
660
+ if (saveTimer)
661
+ clearTimeout(saveTimer);
662
+ saveTimer = setTimeout(() => {
663
+ saveSchemaToLocalStorage();
664
+ }, 500);
665
+ };
666
+ const offAddNode = documentModel.onAddNode?.(() => {
667
+ console.log("[AdminLayout] \u{1F4CC} onAddNode triggered");
668
+ debouncedSave();
669
+ });
670
+ const offRemoveNode = documentModel.onRemoveNode?.(() => {
671
+ console.log("[AdminLayout] \u{1F4CC} onRemoveNode triggered");
672
+ debouncedSave();
673
+ });
674
+ const offMountNode = documentModel.onMountNode?.(() => {
675
+ console.log("[AdminLayout] \u{1F4CC} onMountNode triggered");
676
+ debouncedSave();
677
+ });
678
+ return () => {
679
+ if (saveTimer)
680
+ clearTimeout(saveTimer);
681
+ offAddNode?.();
682
+ offRemoveNode?.();
683
+ offMountNode?.();
684
+ };
685
+ }, [__designMode]);
686
+ useEffect2(() => {
687
+ if (__designMode !== "design" || !componentId)
688
+ return;
689
+ try {
690
+ const engine = window.AliLowCodeEngine;
691
+ if (!engine?.project?.currentDocument)
692
+ return;
693
+ const documentModel = engine.project.currentDocument;
694
+ const adminLayoutNode = documentModel.getNodeById(componentId);
695
+ if (adminLayoutNode?.children) {
696
+ const childrenArr = Array.isArray(adminLayoutNode.children) ? adminLayoutNode.children : adminLayoutNode.children.toArray ? adminLayoutNode.children.toArray() : [];
697
+ childrenArr.forEach((child) => {
698
+ if (child.componentName === "TabPane") {
699
+ child.setPropValue("activeTabKey", activeTabKey);
700
+ }
701
+ });
702
+ }
703
+ } catch (e) {
704
+ }
705
+ }, [activeTabKey, componentId, __designMode]);
706
+ const handleToggleCollapse = useCallback(() => {
707
+ if (collapsible)
708
+ setCollapsed((prev) => !prev);
709
+ }, [collapsible]);
710
+ const createTabPane = useCallback((tabKey, tabLabel) => {
711
+ if (typeof window === "undefined")
712
+ return false;
713
+ try {
714
+ const engine = window.AliLowCodeEngine;
715
+ if (!engine?.project?.currentDocument)
716
+ return false;
717
+ const documentModel = engine.project.currentDocument;
718
+ const adminLayoutNode = componentId ? documentModel.getNodeById(componentId) : null;
719
+ if (!adminLayoutNode)
720
+ return false;
721
+ const allChildren = Array.isArray(adminLayoutNode.children) ? adminLayoutNode.children : adminLayoutNode.children?.toArray ? adminLayoutNode.children.toArray() : [];
722
+ console.log(
723
+ "[AdminLayout] \u{1F50D} All children before create:",
724
+ allChildren.map((c) => ({ id: c.id, name: c.componentName, tabKey: c.props?.tabKey }))
725
+ );
726
+ for (const child of allChildren) {
727
+ const ck = child.props?.tabKey || child.getPropValue?.("tabKey");
728
+ if (child.componentName === "TabPane" && ck === tabKey) {
729
+ console.log("[AdminLayout] \u26A0\uFE0F Found existing TabPane, removing first:", child.id);
730
+ if (child.children) {
731
+ const grandChildren = Array.isArray(child.children) ? [...child.children] : child.children.toArray ? [...child.children.toArray()] : [];
732
+ console.log("[AdminLayout] \u{1F5D1}\uFE0F Removing", grandChildren.length, "children from existing TabPane");
733
+ for (const gc of grandChildren) {
734
+ try {
735
+ documentModel.removeNode(gc);
736
+ } catch (e) {
737
+ }
738
+ }
739
+ }
740
+ documentModel.removeNode(child);
741
+ break;
742
+ }
743
+ }
744
+ const tabPaneNode = documentModel.createNode({
745
+ componentName: "TabPane",
746
+ props: {
747
+ tab: tabLabel,
748
+ tabKey,
749
+ activeTabKey: activeTabKeyRef.current
750
+ }
751
+ });
752
+ if (!tabPaneNode)
753
+ return false;
754
+ documentModel.insertNode(adminLayoutNode, tabPaneNode);
755
+ console.log("[AdminLayout] \u2705 Created new TabPane:", tabKey, "nodeId:", tabPaneNode.id);
756
+ setTimeout(() => saveSchemaToLocalStorage(), 100);
757
+ return true;
758
+ } catch (error) {
759
+ console.error("[AdminLayout] createTabPane error:", error);
760
+ return false;
761
+ }
762
+ }, [componentId]);
763
+ const removeTabPane = useCallback((tabKey) => {
764
+ if (typeof window === "undefined")
765
+ return false;
766
+ let removed = false;
767
+ try {
768
+ const engine = window.AliLowCodeEngine;
769
+ if (!engine?.project?.currentDocument)
770
+ return false;
771
+ const documentModel = engine.project.currentDocument;
772
+ const adminLayoutNode = componentId ? documentModel.getNodeById(componentId) : null;
773
+ console.log("[AdminLayout] \u{1F5D1}\uFE0F removeTabPane called:", tabKey);
774
+ console.log("[AdminLayout] componentId:", componentId);
775
+ console.log("[AdminLayout] adminLayoutNode:", adminLayoutNode ? "found" : "NOT FOUND");
776
+ console.log("[AdminLayout] adminLayoutNode.id:", adminLayoutNode?.id);
777
+ console.log("[AdminLayout] adminLayoutNode.componentName:", adminLayoutNode?.componentName);
778
+ if (!adminLayoutNode)
779
+ return false;
780
+ let childrenArr = [];
781
+ if (adminLayoutNode.children) {
782
+ if (Array.isArray(adminLayoutNode.children)) {
783
+ childrenArr = adminLayoutNode.children;
784
+ } else if (typeof adminLayoutNode.children.toArray === "function") {
785
+ childrenArr = adminLayoutNode.children.toArray();
786
+ } else if (typeof adminLayoutNode.children.map === "function") {
787
+ childrenArr = adminLayoutNode.children.map((c) => c);
788
+ }
789
+ }
790
+ if (childrenArr.length === 0 && adminLayoutNode.schema?.children) {
791
+ console.log("[AdminLayout] Trying schema.children...");
792
+ const schemaChildren = adminLayoutNode.schema.children;
793
+ if (Array.isArray(schemaChildren)) {
794
+ childrenArr = schemaChildren.map((childSchema) => {
795
+ return documentModel.getNodeById(childSchema.id);
796
+ }).filter(Boolean);
797
+ }
798
+ }
799
+ if (childrenArr.length === 0) {
800
+ console.log("[AdminLayout] Trying documentModel.getRoot()...");
801
+ const root = documentModel.getRoot();
802
+ console.log("[AdminLayout] Root node:", root?.componentName);
803
+ const findNode = (node, targetId) => {
804
+ if (!targetId)
805
+ return null;
806
+ if (node.id === targetId)
807
+ return node;
808
+ if (node.children) {
809
+ const arr = Array.isArray(node.children) ? node.children : node.children.toArray ? node.children.toArray() : [];
810
+ for (const child of arr) {
811
+ const found = findNode(child, targetId);
812
+ if (found)
813
+ return found;
814
+ }
815
+ }
816
+ return null;
817
+ };
818
+ const foundNode = findNode(root, componentId);
819
+ if (foundNode && foundNode.children) {
820
+ childrenArr = Array.isArray(foundNode.children) ? foundNode.children : foundNode.children.toArray ? foundNode.children.toArray() : [];
821
+ }
822
+ }
823
+ console.log("[AdminLayout] Final children count:", childrenArr.length);
824
+ console.log(
825
+ "[AdminLayout] Children details:",
826
+ childrenArr.map((c) => ({
827
+ id: c?.id,
828
+ name: c?.componentName,
829
+ tabKey: c?.props?.tabKey || c?.getPropValue?.("tabKey"),
830
+ childrenCount: c?.children ? Array.isArray(c.children) ? c.children.length : c.children.toArray ? c.children.toArray().length : 0 : 0
831
+ }))
832
+ );
833
+ childrenArr.forEach((c, idx) => {
834
+ console.log(`[AdminLayout] Child[${idx}] ${c?.componentName}:`, {
835
+ id: c?.id,
836
+ tabKey: c?.props?.tabKey || c?.getPropValue?.("tabKey"),
837
+ hasChildren: !!c?.children,
838
+ childrenType: c?.children ? Array.isArray(c.children) ? "array" : typeof c.children.toArray === "function" ? "array-like" : typeof c.children : "none"
839
+ });
840
+ if (c?.componentName === "TabPane" && c?.children) {
841
+ const tpChildren = Array.isArray(c.children) ? c.children : c.children.toArray ? c.children.toArray() : [];
842
+ console.log(
843
+ `[AdminLayout] TabPane children:`,
844
+ tpChildren.map((gc) => ({ id: gc?.id, name: gc?.componentName }))
845
+ );
846
+ if (tpChildren.length === 0) {
847
+ console.log(`[AdminLayout] Trying alternative methods...`);
848
+ if (c.schema?.children) {
849
+ console.log(`[AdminLayout] schema.children:`, c.schema.children);
850
+ }
851
+ if (typeof c.getChildren === "function") {
852
+ const gChildren = c.getChildren();
853
+ console.log(`[AdminLayout] getChildren():`, gChildren);
854
+ }
855
+ if (c.slots) {
856
+ console.log(`[AdminLayout] slots:`, c.slots);
857
+ }
858
+ }
859
+ }
860
+ if (c?.componentName !== "TabPane") {
861
+ console.log(`[AdminLayout] \u26A0\uFE0F Found non-TabPane child! This might be a dragged component.`);
862
+ }
863
+ });
864
+ for (const child of childrenArr) {
865
+ if (!child)
866
+ continue;
867
+ const childTabKey = child.props?.tabKey || child.getPropValue?.("tabKey");
868
+ if (child.componentName === "TabPane" && childTabKey === tabKey) {
869
+ console.log("[AdminLayout] \u2705 Found TabPane to remove:", child.id);
870
+ const schemaChildren = child.schema?.children;
871
+ if (schemaChildren && Array.isArray(schemaChildren) && schemaChildren.length > 0) {
872
+ console.log("[AdminLayout] Removing", schemaChildren.length, "grandchildren from schema.children");
873
+ for (let i = schemaChildren.length - 1; i >= 0; i--) {
874
+ const childSchema = schemaChildren[i];
875
+ const grandChildNode = documentModel.getNodeById(childSchema.id);
876
+ if (grandChildNode) {
877
+ try {
878
+ documentModel.removeNode(grandChildNode);
879
+ console.log("[AdminLayout] \u2713 Removed grandchild:", grandChildNode.id, grandChildNode.componentName);
880
+ } catch (e) {
881
+ console.warn("[AdminLayout] \u2717 Failed to remove grandchild:", e);
882
+ }
883
+ }
884
+ }
885
+ } else {
886
+ console.log("[AdminLayout] No grandchildren to remove");
887
+ }
888
+ try {
889
+ documentModel.removeNode(child);
890
+ removed = true;
891
+ console.log("[AdminLayout] \u2705 Removed TabPane node:", tabKey);
892
+ setTimeout(() => saveSchemaToLocalStorage(), 100);
893
+ } catch (e) {
894
+ console.error("[AdminLayout] Failed to remove TabPane:", e);
895
+ }
896
+ break;
897
+ }
898
+ }
899
+ if (!removed) {
900
+ console.warn("[AdminLayout] \u26A0\uFE0F TabPane not found for key:", tabKey);
901
+ }
902
+ return removed;
903
+ } catch (error) {
904
+ console.error("[AdminLayout] removeTabPane error:", error);
905
+ return false;
906
+ }
907
+ }, [componentId]);
908
+ const handleMenuClick = useCallback((key) => {
909
+ setSelectedKey(key);
910
+ const existingTab = tabs.find((tab) => tab.key === key);
911
+ if (!existingTab) {
912
+ const menuItem = findMenuItem(items, key);
913
+ const newTab = {
914
+ key,
915
+ label: menuItem?.label || getLabelFromKey(key),
916
+ icon: menuItem?.icon,
917
+ closable: key !== "dashboard",
918
+ path: menuItem?.path || `/${key}`
919
+ };
920
+ setTabs((prev) => {
921
+ if (prev.length >= maxTabs) {
922
+ const filtered = prev.filter((t) => t.closable);
923
+ if (filtered.length > 0) {
924
+ return [...prev.filter((t) => t.key !== filtered[0].key), newTab];
925
+ }
926
+ }
927
+ return [...prev, newTab];
928
+ });
929
+ if (__designMode === "design") {
930
+ setTimeout(() => createTabPane(key, menuItem?.label || getLabelFromKey(key)), 0);
931
+ }
932
+ }
933
+ setActiveTabKey(key);
934
+ }, [tabs, items, maxTabs, __designMode, createTabPane]);
935
+ const handleOpenChange = useCallback((keys) => setOpenKeys(keys), []);
936
+ const handleNavigate = useCallback((key) => {
937
+ setSelectedKey(key);
938
+ setActiveTabKey(key);
939
+ }, []);
940
+ const handleTabClick = useCallback((key) => {
941
+ setSelectedKey(key);
942
+ setActiveTabKey(key);
943
+ }, []);
944
+ const handleCloseTab = useCallback((key) => {
945
+ if (key === "dashboard")
946
+ return;
947
+ removeTabPane(key);
948
+ setTabs((prev) => prev.filter((tab) => tab.key !== key));
949
+ if (key === activeTabKey) {
950
+ const remainingTabs = tabs.filter((tab) => tab.key !== key);
951
+ if (remainingTabs.length > 0) {
952
+ const currentIndex = tabs.findIndex((tab) => tab.key === key);
953
+ const nextTab = remainingTabs[currentIndex] || remainingTabs[remainingTabs.length - 1];
954
+ setSelectedKey(nextTab.key);
955
+ setActiveTabKey(nextTab.key);
956
+ }
957
+ }
958
+ }, [tabs, activeTabKey, removeTabPane]);
959
+ const handleCloseOther = useCallback((keepKey) => {
960
+ tabs.forEach((tab) => {
961
+ if (tab.key !== keepKey && tab.key !== "dashboard") {
962
+ removeTabPane(tab.key);
963
+ }
964
+ });
965
+ setTabs((prev) => prev.filter((tab) => tab.key === keepKey || tab.key === "dashboard"));
966
+ setSelectedKey(keepKey);
967
+ setActiveTabKey(keepKey);
968
+ }, [tabs, removeTabPane]);
969
+ const handleCloseAll = useCallback(() => {
970
+ tabs.forEach((tab) => {
971
+ if (tab.key !== "dashboard") {
972
+ removeTabPane(tab.key);
973
+ }
974
+ });
975
+ const dashboardTab = tabs.find((tab) => tab.key === "dashboard");
976
+ if (dashboardTab) {
977
+ setTabs([dashboardTab]);
978
+ setSelectedKey("dashboard");
979
+ setActiveTabKey("dashboard");
980
+ }
981
+ }, [tabs, removeTabPane]);
982
+ const breadcrumbItems = useMemo(() => {
983
+ if (selectedKey === "dashboard")
984
+ return [];
985
+ const parts = selectedKey.split("/");
986
+ if (parts.length === 1)
987
+ return [{ key: selectedKey, label: "", path: selectedKey }];
988
+ return [{ key: selectedKey, label: "", path: selectedKey }];
989
+ }, [selectedKey]);
990
+ const filteredChildren = useMemo(() => {
991
+ if (!children)
992
+ return null;
993
+ if (__designMode === "design") {
994
+ const childArray = Children.toArray(children);
995
+ const activeTabPane = childArray.find((child) => {
996
+ if (isValidElement(child)) {
997
+ const childProps = child.props;
998
+ return childProps?.tabKey === activeTabKey;
999
+ }
1000
+ return false;
1001
+ });
1002
+ return activeTabPane || null;
1003
+ }
1004
+ return children;
1005
+ }, [children, activeTabKey, __designMode]);
1006
+ const defaultContent = /* @__PURE__ */ React6.createElement("div", { style: { padding: 24, color: "#999" } }, "\u70B9\u51FB\u4FA7\u8FB9\u680F\u83DC\u5355\u521B\u5EFA\u9009\u9879\u5361\uFF0C\u7136\u540E\u62D6\u62FD\u7EC4\u4EF6\u5230\u5BF9\u5E94\u9762\u677F");
1007
+ const content = filteredChildren || defaultContent;
1008
+ return /* @__PURE__ */ React6.createElement("div", { className: `admin-layout ${collapsed ? "is-collapse" : ""} ${className || ""}`, style, "data-active-tab": activeTabKey }, /* @__PURE__ */ React6.createElement(
1009
+ Sidebar_default,
1010
+ {
1011
+ collapsed,
1012
+ selectedKey,
1013
+ openKeys,
1014
+ onMenuClick: handleMenuClick,
1015
+ onOpenChange: handleOpenChange,
1016
+ menuItems: items
1017
+ }
1018
+ ), /* @__PURE__ */ React6.createElement("div", { className: "layout-right" }, /* @__PURE__ */ React6.createElement(
1019
+ Navbar_default,
1020
+ {
1021
+ collapsed,
1022
+ onToggleCollapse: handleToggleCollapse,
1023
+ breadcrumbItems,
1024
+ onNavigate: handleNavigate
1025
+ }
1026
+ ), /* @__PURE__ */ React6.createElement(
1027
+ MainContent_default,
1028
+ {
1029
+ pageKey: selectedKey,
1030
+ tabs,
1031
+ activeTabKey,
1032
+ onTabClick: handleTabClick,
1033
+ onCloseTab: handleCloseTab,
1034
+ onCloseOther: handleCloseOther,
1035
+ onCloseAll: handleCloseAll,
1036
+ enableTabs,
1037
+ closableTabs,
1038
+ className: collapsed ? "collapsed" : ""
1039
+ },
1040
+ content
1041
+ )), collapsible && /* @__PURE__ */ React6.createElement(
1042
+ "div",
1043
+ {
1044
+ className: `mobile-overlay ${!collapsed ? "visible" : ""}`,
1045
+ onClick: handleToggleCollapse
1046
+ }
1047
+ ));
1048
+ };
1049
+ var AdminLayout_default = AdminLayout;
1050
+
1051
+ // src/components/AdminLayout/TabPane.tsx
1052
+ import React7 from "react";
1053
+ var TabPane = ({
1054
+ tab,
1055
+ tabKey,
1056
+ activeTabKey,
1057
+ children,
1058
+ className,
1059
+ style
1060
+ }) => {
1061
+ const isActive = activeTabKey === tabKey;
1062
+ return /* @__PURE__ */ React7.createElement(
1063
+ "div",
1064
+ {
1065
+ className: `tab-pane ${isActive ? "tab-pane--active" : ""} ${className || ""}`,
1066
+ style: {
1067
+ ...style,
1068
+ display: isActive ? void 0 : "none"
1069
+ },
1070
+ "data-tab-key": tabKey,
1071
+ "data-active": isActive ? "true" : "false"
1072
+ },
1073
+ children
1074
+ );
1075
+ };
1076
+ var TabPane_default = TabPane;
1077
+ export {
1078
+ AdminLayout_default as AdminLayout,
1079
+ TabPane_default as TabPane
1080
+ };