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