@donglegeyu/company-ui 1.2.39 → 1.2.40
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.
- package/dist/cjs/shared-components/SvgIcon/index.js +10 -1
- package/dist/cjs/template-components/AdminLayoutTemplate/index.js +18 -1
- package/dist/cjs/template-components/AdminLayoutTemplate/index.scss +2 -0
- package/dist/cjs/template-components/CompanySidebar/FirstSidebar.d.ts +2 -1
- package/dist/cjs/template-components/CompanySidebar/FirstSidebar.js +2 -1
- package/dist/cjs/template-components/CompanySidebar/index.js +36 -3
- package/dist/cjs/template-components/CompanySidebar/menuIconMap.js +11 -2
- package/dist/cjs/template-components/DetailPageTemplate/index.scss +1 -0
- package/dist/cjs/template-components/FormPageTemplate/index.scss +1 -0
- package/dist/cjs/template-components/StatisticsListPage/index.scss +3 -0
- package/dist/es/shared-components/SvgIcon/index.js +12 -0
- package/dist/es/template-components/AdminLayoutTemplate/index.js +13 -1
- package/dist/es/template-components/AdminLayoutTemplate/index.scss +2 -0
- package/dist/es/template-components/CompanySidebar/FirstSidebar.d.ts +2 -1
- package/dist/es/template-components/CompanySidebar/FirstSidebar.js +2 -1
- package/dist/es/template-components/CompanySidebar/index.js +43 -7
- package/dist/es/template-components/CompanySidebar/menuIconMap.js +8 -1
- package/dist/es/template-components/DetailPageTemplate/index.scss +1 -0
- package/dist/es/template-components/FormPageTemplate/index.scss +1 -0
- package/dist/es/template-components/StatisticsListPage/index.scss +3 -0
- package/package.json +3 -2
|
@@ -24,6 +24,7 @@ __export(SvgIcon_exports, {
|
|
|
24
24
|
module.exports = __toCommonJS(SvgIcon_exports);
|
|
25
25
|
var import_icons = require("./icons");
|
|
26
26
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
27
|
+
var FALLBACK_ICON = "folder-open";
|
|
27
28
|
function toCssSize(size, fallback) {
|
|
28
29
|
if (size === void 0 || size === null)
|
|
29
30
|
return fallback;
|
|
@@ -40,7 +41,15 @@ function SvgIcon({
|
|
|
40
41
|
onClick
|
|
41
42
|
}) {
|
|
42
43
|
const key = name ?? href;
|
|
43
|
-
|
|
44
|
+
let icon = key ? (0, import_icons.getIconDefinition)(key) : void 0;
|
|
45
|
+
if (!icon && name) {
|
|
46
|
+
if (process.env.NODE_ENV !== "production") {
|
|
47
|
+
console.warn(
|
|
48
|
+
`[SvgIcon] 未注册的图标 name "${name}",已回退为 "${FALLBACK_ICON}"。请使用内置图标集(/icon-library 精选)中的键。`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
icon = (0, import_icons.getIconDefinition)(FALLBACK_ICON);
|
|
52
|
+
}
|
|
44
53
|
const dimension = toCssSize(size, 16);
|
|
45
54
|
const mergedStyle = {
|
|
46
55
|
width: dimension,
|
|
@@ -348,6 +348,12 @@ function AdminLayoutTemplate({
|
|
|
348
348
|
(menu) => {
|
|
349
349
|
var _a2;
|
|
350
350
|
setActiveKey(menu.key);
|
|
351
|
+
const parentModule = businessMenus.find((m) => findMenuByKey(m.children ?? [], menu.key));
|
|
352
|
+
if (parentModule && parentModule.key !== activeFirstMenu) {
|
|
353
|
+
setActiveFirstMenu(parentModule.key);
|
|
354
|
+
setExpandedKeys(collectParentKeys(parentModule.children ?? []));
|
|
355
|
+
onActiveFirstMenuChange == null ? void 0 : onActiveFirstMenuChange(parentModule.key);
|
|
356
|
+
}
|
|
351
357
|
if ((_a2 = menu.children) == null ? void 0 : _a2.length)
|
|
352
358
|
return;
|
|
353
359
|
if (systemMenuKeys.has(menu.key)) {
|
|
@@ -363,7 +369,18 @@ function AdminLayoutTemplate({
|
|
|
363
369
|
openTab(menu.key, (page == null ? void 0 : page.label) ?? menu.label, (page == null ? void 0 : page.path) ?? menu.path, page == null ? void 0 : page.closable);
|
|
364
370
|
onMenuOpen == null ? void 0 : onMenuOpen(menu);
|
|
365
371
|
},
|
|
366
|
-
[
|
|
372
|
+
[
|
|
373
|
+
businessMenus,
|
|
374
|
+
activeFirstMenu,
|
|
375
|
+
systemMenuKeys,
|
|
376
|
+
homeTab,
|
|
377
|
+
isTabActiveControlled,
|
|
378
|
+
onActiveTabChange,
|
|
379
|
+
onActiveFirstMenuChange,
|
|
380
|
+
onMenuOpen,
|
|
381
|
+
pages,
|
|
382
|
+
openTab
|
|
383
|
+
]
|
|
367
384
|
);
|
|
368
385
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `admin-layout-template${className ? ` ${className}` : ""}`, style, children: [
|
|
369
386
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
display: flex;
|
|
20
20
|
flex-direction: column;
|
|
21
21
|
overflow: hidden;
|
|
22
|
+
|
|
22
23
|
/* 主区灰底与 SmartListTemplate 等业务模板的 --color-bg-layout 对齐,
|
|
23
24
|
页签栏与内容未充满处不露出白底 */
|
|
24
25
|
background: var(--color-bg-layout, #f5f5f5);
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
/* 间距契约:内容区只做滚动容器,禁止加 padding/margin/background(业务模板自带)。
|
|
32
33
|
纵向 flex 让 SmartListTemplate(flex-grow:1 + align-self:stretch)充满剩余高度 */
|
|
33
34
|
.admin-layout-content {
|
|
35
|
+
position: relative; /* 为 FormPageTemplate/DetailPageTemplate 等 absolute+inset:0 模板提供定位上下文,防止逃逸到全屏祖先 */
|
|
34
36
|
flex: 1;
|
|
35
37
|
min-height: 0;
|
|
36
38
|
overflow: auto;
|
|
@@ -12,6 +12,7 @@ export interface FirstSidebarProps {
|
|
|
12
12
|
businessMenus: SidebarMenuItem[];
|
|
13
13
|
customNavMenus: SidebarMenuItem[];
|
|
14
14
|
activeKey: string;
|
|
15
|
+
activeFirstMenu: string;
|
|
15
16
|
visibleMenuCount?: number;
|
|
16
17
|
domainPopoverOpen: boolean;
|
|
17
18
|
adminPopoverOpen: boolean;
|
|
@@ -25,4 +26,4 @@ export interface FirstSidebarProps {
|
|
|
25
26
|
onThemeSettings?: () => void;
|
|
26
27
|
onLogout?: () => void;
|
|
27
28
|
}
|
|
28
|
-
export default function FirstSidebar({ domains, currentDomainId, userInfo, logo, brandName, firstMenus, systemBottomMenus, businessMenus, customNavMenus, activeKey, visibleMenuCount, domainPopoverOpen, adminPopoverOpen, onDomainPopoverOpenChange, onAdminPopoverOpenChange, onDomainChange, onMenuClick, onBusinessMenuEnter, onBusinessMenuLeave, onOpenMore, onThemeSettings, onLogout, }: FirstSidebarProps): import("react").JSX.Element;
|
|
29
|
+
export default function FirstSidebar({ domains, currentDomainId, userInfo, logo, brandName, firstMenus, systemBottomMenus, businessMenus, customNavMenus, activeKey, activeFirstMenu, visibleMenuCount, domainPopoverOpen, adminPopoverOpen, onDomainPopoverOpenChange, onAdminPopoverOpenChange, onDomainChange, onMenuClick, onBusinessMenuEnter, onBusinessMenuLeave, onOpenMore, onThemeSettings, onLogout, }: FirstSidebarProps): import("react").JSX.Element;
|
|
@@ -37,6 +37,7 @@ function FirstSidebar({
|
|
|
37
37
|
businessMenus,
|
|
38
38
|
customNavMenus,
|
|
39
39
|
activeKey,
|
|
40
|
+
activeFirstMenu,
|
|
40
41
|
visibleMenuCount = 6,
|
|
41
42
|
domainPopoverOpen,
|
|
42
43
|
adminPopoverOpen,
|
|
@@ -108,7 +109,7 @@ function FirstSidebar({
|
|
|
108
109
|
displayMenus.map((menu) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
109
110
|
"div",
|
|
110
111
|
{
|
|
111
|
-
className: `business-menu-item${activeKey === menu.key ? " active" : ""}`,
|
|
112
|
+
className: `business-menu-item${activeFirstMenu === menu.key || activeKey === menu.key ? " active" : ""}`,
|
|
112
113
|
onClick: () => onMenuClick(menu),
|
|
113
114
|
onMouseEnter: () => onBusinessMenuEnter(menu),
|
|
114
115
|
onMouseLeave: onBusinessMenuLeave,
|
|
@@ -41,6 +41,24 @@ var import_menuIconMap = require("./menuIconMap");
|
|
|
41
41
|
var import_default_logo = require("./default-logo");
|
|
42
42
|
var import_index = require("./index.scss");
|
|
43
43
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
44
|
+
function buildLeafToFirstKeyMap(menus) {
|
|
45
|
+
const map = /* @__PURE__ */ new Map();
|
|
46
|
+
const walk = (items, firstKey) => {
|
|
47
|
+
(items || []).forEach((item) => {
|
|
48
|
+
var _a;
|
|
49
|
+
map.set(item.key, firstKey);
|
|
50
|
+
if ((_a = item.children) == null ? void 0 : _a.length)
|
|
51
|
+
walk(item.children, firstKey);
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
(menus || []).forEach((menu) => {
|
|
55
|
+
var _a;
|
|
56
|
+
map.set(menu.key, menu.key);
|
|
57
|
+
if ((_a = menu.children) == null ? void 0 : _a.length)
|
|
58
|
+
walk(menu.children, menu.key);
|
|
59
|
+
});
|
|
60
|
+
return map;
|
|
61
|
+
}
|
|
44
62
|
function DefaultFallback() {
|
|
45
63
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "company-sidebar-error", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "导航加载失败" }) });
|
|
46
64
|
}
|
|
@@ -89,6 +107,17 @@ function CompanySidebar({
|
|
|
89
107
|
const resolvedBusinessMenus = (0, import_react.useMemo)(() => (0, import_menuIconMap.resolveMenuIcons)(businessMenus), [businessMenus]);
|
|
90
108
|
const resolvedSecondMenus = (0, import_react.useMemo)(() => (0, import_menuIconMap.resolveMenuIcons)(secondMenus), [secondMenus]);
|
|
91
109
|
const resolvedCustomNavMenus = (0, import_react.useMemo)(() => (0, import_menuIconMap.resolveMenuIcons)(customNavMenus), [customNavMenus]);
|
|
110
|
+
const leafToFirstKeyMap = (0, import_react.useMemo)(() => buildLeafToFirstKeyMap(businessMenus), [businessMenus]);
|
|
111
|
+
const handleLeafMenuClick = (0, import_react.useCallback)(
|
|
112
|
+
(menu) => {
|
|
113
|
+
const firstKey = leafToFirstKeyMap.get(menu.key);
|
|
114
|
+
if (firstKey && firstKey !== activeFirstMenu) {
|
|
115
|
+
onFirstMenuSelect(firstKey);
|
|
116
|
+
}
|
|
117
|
+
onMenuClick(menu);
|
|
118
|
+
},
|
|
119
|
+
[leafToFirstKeyMap, activeFirstMenu, onFirstMenuSelect, onMenuClick]
|
|
120
|
+
);
|
|
92
121
|
(0, import_react.useEffect)(() => {
|
|
93
122
|
setState((prev) => ({ ...prev, localExpandedKeys: expandedKeys }));
|
|
94
123
|
}, [expandedKeys]);
|
|
@@ -126,10 +155,13 @@ function CompanySidebar({
|
|
|
126
155
|
}, [delayHideSidebar]);
|
|
127
156
|
const handleFirstMenuClick = (0, import_react.useCallback)(
|
|
128
157
|
(menu) => {
|
|
129
|
-
|
|
158
|
+
const firstKey = leafToFirstKeyMap.get(menu.key) || menu.key;
|
|
159
|
+
if (firstKey !== activeFirstMenu) {
|
|
160
|
+
onFirstMenuSelect(firstKey);
|
|
161
|
+
}
|
|
130
162
|
onMenuClick(menu);
|
|
131
163
|
},
|
|
132
|
-
[onFirstMenuSelect, onMenuClick]
|
|
164
|
+
[leafToFirstKeyMap, activeFirstMenu, onFirstMenuSelect, onMenuClick]
|
|
133
165
|
);
|
|
134
166
|
const handleMoreSelect = (0, import_react.useCallback)(
|
|
135
167
|
(menu, child) => {
|
|
@@ -185,6 +217,7 @@ function CompanySidebar({
|
|
|
185
217
|
businessMenus: resolvedBusinessMenus,
|
|
186
218
|
customNavMenus: resolvedCustomNavMenus,
|
|
187
219
|
activeKey,
|
|
220
|
+
activeFirstMenu,
|
|
188
221
|
visibleMenuCount,
|
|
189
222
|
domainPopoverOpen: state.domainPopoverOpen,
|
|
190
223
|
adminPopoverOpen: state.adminPopoverOpen,
|
|
@@ -211,7 +244,7 @@ function CompanySidebar({
|
|
|
211
244
|
expandedKeys: state.localExpandedKeys,
|
|
212
245
|
emptyImage,
|
|
213
246
|
onMenuClick: (menu) => {
|
|
214
|
-
|
|
247
|
+
handleLeafMenuClick(menu);
|
|
215
248
|
if (!secondSidebarFixed) {
|
|
216
249
|
delayHideSidebar();
|
|
217
250
|
}
|
|
@@ -24,6 +24,8 @@ __export(menuIconMap_exports, {
|
|
|
24
24
|
resolveMenuIcons: () => resolveMenuIcons
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(menuIconMap_exports);
|
|
27
|
+
var import_icons = require("../../shared-components/SvgIcon/icons");
|
|
28
|
+
var VALID_ICONS = new Set(import_icons.iconNames);
|
|
27
29
|
var KEYWORD_ICON_MAP = [
|
|
28
30
|
{ keywords: ["商品", "货品", "物料", "spu", "sku", "product"], icon: "commodity" },
|
|
29
31
|
{ keywords: ["采购", "进货", "供应商", "purchase"], icon: "buy" },
|
|
@@ -47,8 +49,15 @@ var KEYWORD_ICON_MAP = [
|
|
|
47
49
|
];
|
|
48
50
|
var DEFAULT_ICON = "folder-open";
|
|
49
51
|
function getMenuIcon(menu) {
|
|
50
|
-
if (menu.icon)
|
|
51
|
-
|
|
52
|
+
if (menu.icon) {
|
|
53
|
+
if (VALID_ICONS.has(menu.icon))
|
|
54
|
+
return menu.icon;
|
|
55
|
+
if (process.env.NODE_ENV !== "production") {
|
|
56
|
+
console.warn(
|
|
57
|
+
`[CompanySidebar] 菜单 "${menu.label}" 的 icon "${menu.icon}" 不在内置图标集中,已回退为关键词匹配。内置图标键可查阅文档站 /icon-library 精选集。`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
52
61
|
const label = (menu.label || "").toLowerCase();
|
|
53
62
|
for (const { keywords, icon } of KEYWORD_ICON_MAP) {
|
|
54
63
|
if (keywords.some((kw) => label.includes(kw.toLowerCase()))) {
|
|
@@ -171,6 +171,9 @@
|
|
|
171
171
|
justify-content: flex-end;
|
|
172
172
|
padding: calc(var(--spacing-md, 16) * 1px);
|
|
173
173
|
border-top: 1px solid var(--color-border-secondary, rgba(5, 5, 5, 0.06));
|
|
174
|
+
|
|
175
|
+
/* 吸底:表格高度由 scroll.y 控制不一定填满 wrapper,margin-top:auto 保证分页器始终贴白卡底部(对齐 SmartListTemplate 视觉契约) */
|
|
176
|
+
margin-top: auto;
|
|
174
177
|
}
|
|
175
178
|
}
|
|
176
179
|
}
|
|
@@ -5,7 +5,10 @@ function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key i
|
|
|
5
5
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
|
|
6
6
|
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
7
7
|
import { getIconDefinition } from "./icons";
|
|
8
|
+
|
|
9
|
+
// 未注册图标键的兜底图标,保证任何输入都有可见输出(业务环境无 iconpark sprite,不能依赖 <use> 静默回退)
|
|
8
10
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
var FALLBACK_ICON = "folder-open";
|
|
9
12
|
function toCssSize(size, fallback) {
|
|
10
13
|
if (size === undefined || size === null) return fallback;
|
|
11
14
|
return typeof size === "number" ? "".concat(size, "px") : size;
|
|
@@ -23,6 +26,15 @@ export default function SvgIcon(_ref) {
|
|
|
23
26
|
onClick = _ref.onClick;
|
|
24
27
|
var key = name !== null && name !== void 0 ? name : href;
|
|
25
28
|
var icon = key ? getIconDefinition(key) : undefined;
|
|
29
|
+
|
|
30
|
+
// name 未注册:dev 警告并兜底渲染,避免业务环境静默空白
|
|
31
|
+
// (href 未注册不警告,IconParkGallery 全量库走 <use> sprite 是合法路径)
|
|
32
|
+
if (!icon && name) {
|
|
33
|
+
if (process.env.NODE_ENV !== "production") {
|
|
34
|
+
console.warn("[SvgIcon] \u672A\u6CE8\u518C\u7684\u56FE\u6807 name \"".concat(name, "\"\uFF0C\u5DF2\u56DE\u9000\u4E3A \"").concat(FALLBACK_ICON, "\"\u3002\u8BF7\u4F7F\u7528\u5185\u7F6E\u56FE\u6807\u96C6\uFF08/icon-library \u7CBE\u9009\uFF09\u4E2D\u7684\u952E\u3002"));
|
|
35
|
+
}
|
|
36
|
+
icon = getIconDefinition(FALLBACK_ICON);
|
|
37
|
+
}
|
|
26
38
|
var dimension = toCssSize(size, 16);
|
|
27
39
|
var mergedStyle = _objectSpread(_objectSpread({
|
|
28
40
|
width: dimension,
|
|
@@ -447,6 +447,18 @@ export default function AdminLayoutTemplate(_ref) {
|
|
|
447
447
|
var handleMenuClick = useCallback(function (menu) {
|
|
448
448
|
var _menu$children5, _page$label2, _page$path2;
|
|
449
449
|
setActiveKey(menu.key);
|
|
450
|
+
// 反向同步一级菜单高亮:从收藏/更多应用/自定义导航面板点击叶子菜单时,
|
|
451
|
+
// activeFirstMenu 可能停留在其他模块(与 handleTabChange 的反向同步保持一致)
|
|
452
|
+
var parentModule = businessMenus.find(function (m) {
|
|
453
|
+
var _m$children2;
|
|
454
|
+
return findMenuByKey((_m$children2 = m.children) !== null && _m$children2 !== void 0 ? _m$children2 : [], menu.key);
|
|
455
|
+
});
|
|
456
|
+
if (parentModule && parentModule.key !== activeFirstMenu) {
|
|
457
|
+
var _parentModule$childre2;
|
|
458
|
+
setActiveFirstMenu(parentModule.key);
|
|
459
|
+
setExpandedKeys(collectParentKeys((_parentModule$childre2 = parentModule.children) !== null && _parentModule$childre2 !== void 0 ? _parentModule$childre2 : []));
|
|
460
|
+
onActiveFirstMenuChange === null || onActiveFirstMenuChange === void 0 || onActiveFirstMenuChange(parentModule.key);
|
|
461
|
+
}
|
|
450
462
|
// 父级菜单只负责展开(展开交互由 CompanySidebar 内部处理)
|
|
451
463
|
if ((_menu$children5 = menu.children) !== null && _menu$children5 !== void 0 && _menu$children5.length) return;
|
|
452
464
|
// 一级系统菜单(首页/收藏/系统设置)不开页签;首页激活 homeTab
|
|
@@ -467,7 +479,7 @@ export default function AdminLayoutTemplate(_ref) {
|
|
|
467
479
|
});
|
|
468
480
|
openTab(menu.key, (_page$label2 = page === null || page === void 0 ? void 0 : page.label) !== null && _page$label2 !== void 0 ? _page$label2 : menu.label, (_page$path2 = page === null || page === void 0 ? void 0 : page.path) !== null && _page$path2 !== void 0 ? _page$path2 : menu.path, page === null || page === void 0 ? void 0 : page.closable);
|
|
469
481
|
onMenuOpen === null || onMenuOpen === void 0 || onMenuOpen(menu);
|
|
470
|
-
}, [systemMenuKeys, homeTab, isTabActiveControlled, onActiveTabChange, onMenuOpen, pages, openTab]);
|
|
482
|
+
}, [businessMenus, activeFirstMenu, systemMenuKeys, homeTab, isTabActiveControlled, onActiveTabChange, onActiveFirstMenuChange, onMenuOpen, pages, openTab]);
|
|
471
483
|
return /*#__PURE__*/_jsxs("div", {
|
|
472
484
|
className: "admin-layout-template".concat(className ? " ".concat(className) : ""),
|
|
473
485
|
style: style,
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
display: flex;
|
|
20
20
|
flex-direction: column;
|
|
21
21
|
overflow: hidden;
|
|
22
|
+
|
|
22
23
|
/* 主区灰底与 SmartListTemplate 等业务模板的 --color-bg-layout 对齐,
|
|
23
24
|
页签栏与内容未充满处不露出白底 */
|
|
24
25
|
background: var(--color-bg-layout, #f5f5f5);
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
/* 间距契约:内容区只做滚动容器,禁止加 padding/margin/background(业务模板自带)。
|
|
32
33
|
纵向 flex 让 SmartListTemplate(flex-grow:1 + align-self:stretch)充满剩余高度 */
|
|
33
34
|
.admin-layout-content {
|
|
35
|
+
position: relative; /* 为 FormPageTemplate/DetailPageTemplate 等 absolute+inset:0 模板提供定位上下文,防止逃逸到全屏祖先 */
|
|
34
36
|
flex: 1;
|
|
35
37
|
min-height: 0;
|
|
36
38
|
overflow: auto;
|
|
@@ -12,6 +12,7 @@ export interface FirstSidebarProps {
|
|
|
12
12
|
businessMenus: SidebarMenuItem[];
|
|
13
13
|
customNavMenus: SidebarMenuItem[];
|
|
14
14
|
activeKey: string;
|
|
15
|
+
activeFirstMenu: string;
|
|
15
16
|
visibleMenuCount?: number;
|
|
16
17
|
domainPopoverOpen: boolean;
|
|
17
18
|
adminPopoverOpen: boolean;
|
|
@@ -25,4 +26,4 @@ export interface FirstSidebarProps {
|
|
|
25
26
|
onThemeSettings?: () => void;
|
|
26
27
|
onLogout?: () => void;
|
|
27
28
|
}
|
|
28
|
-
export default function FirstSidebar({ domains, currentDomainId, userInfo, logo, brandName, firstMenus, systemBottomMenus, businessMenus, customNavMenus, activeKey, visibleMenuCount, domainPopoverOpen, adminPopoverOpen, onDomainPopoverOpenChange, onAdminPopoverOpenChange, onDomainChange, onMenuClick, onBusinessMenuEnter, onBusinessMenuLeave, onOpenMore, onThemeSettings, onLogout, }: FirstSidebarProps): import("react").JSX.Element;
|
|
29
|
+
export default function FirstSidebar({ domains, currentDomainId, userInfo, logo, brandName, firstMenus, systemBottomMenus, businessMenus, customNavMenus, activeKey, activeFirstMenu, visibleMenuCount, domainPopoverOpen, adminPopoverOpen, onDomainPopoverOpenChange, onAdminPopoverOpenChange, onDomainChange, onMenuClick, onBusinessMenuEnter, onBusinessMenuLeave, onOpenMore, onThemeSettings, onLogout, }: FirstSidebarProps): import("react").JSX.Element;
|
|
@@ -15,6 +15,7 @@ export default function FirstSidebar(_ref) {
|
|
|
15
15
|
businessMenus = _ref.businessMenus,
|
|
16
16
|
customNavMenus = _ref.customNavMenus,
|
|
17
17
|
activeKey = _ref.activeKey,
|
|
18
|
+
activeFirstMenu = _ref.activeFirstMenu,
|
|
18
19
|
_ref$visibleMenuCount = _ref.visibleMenuCount,
|
|
19
20
|
visibleMenuCount = _ref$visibleMenuCount === void 0 ? 6 : _ref$visibleMenuCount,
|
|
20
21
|
domainPopoverOpen = _ref.domainPopoverOpen,
|
|
@@ -120,7 +121,7 @@ export default function FirstSidebar(_ref) {
|
|
|
120
121
|
className: "business-menus",
|
|
121
122
|
children: [displayMenus.map(function (menu) {
|
|
122
123
|
return /*#__PURE__*/_jsxs("div", {
|
|
123
|
-
className: "business-menu-item".concat(activeKey === menu.key ? " active" : ""),
|
|
124
|
+
className: "business-menu-item".concat(activeFirstMenu === menu.key || activeKey === menu.key ? " active" : ""),
|
|
124
125
|
onClick: function onClick() {
|
|
125
126
|
return onMenuClick(menu);
|
|
126
127
|
},
|
|
@@ -18,9 +18,27 @@ import CustomNavPanel from "./CustomNavPanel";
|
|
|
18
18
|
import { resolveMenuIcons } from "./menuIconMap";
|
|
19
19
|
import { DEFAULT_LOGO } from "./default-logo";
|
|
20
20
|
import "./index.scss";
|
|
21
|
+
|
|
22
|
+
// 反查表:任意叶子菜单 key -> 所属一级业务菜单 key(选中二级时同步高亮一级)
|
|
21
23
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
22
24
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
23
25
|
import { Fragment as _Fragment } from "react/jsx-runtime";
|
|
26
|
+
function buildLeafToFirstKeyMap(menus) {
|
|
27
|
+
var map = new Map();
|
|
28
|
+
var walk = function walk(items, firstKey) {
|
|
29
|
+
(items || []).forEach(function (item) {
|
|
30
|
+
var _item$children;
|
|
31
|
+
map.set(item.key, firstKey);
|
|
32
|
+
if ((_item$children = item.children) !== null && _item$children !== void 0 && _item$children.length) walk(item.children, firstKey);
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
(menus || []).forEach(function (menu) {
|
|
36
|
+
var _menu$children;
|
|
37
|
+
map.set(menu.key, menu.key);
|
|
38
|
+
if ((_menu$children = menu.children) !== null && _menu$children !== void 0 && _menu$children.length) walk(menu.children, menu.key);
|
|
39
|
+
});
|
|
40
|
+
return map;
|
|
41
|
+
}
|
|
24
42
|
function DefaultFallback() {
|
|
25
43
|
return /*#__PURE__*/_jsx("div", {
|
|
26
44
|
className: "company-sidebar-error",
|
|
@@ -52,7 +70,7 @@ export default function CompanySidebar(_ref) {
|
|
|
52
70
|
activeFirstMenu = _ref.activeFirstMenu,
|
|
53
71
|
activeKey = _ref.activeKey,
|
|
54
72
|
onFirstMenuSelect = _ref.onFirstMenuSelect,
|
|
55
|
-
|
|
73
|
+
onMenuClick = _ref.onMenuClick,
|
|
56
74
|
expandedKeys = _ref.expandedKeys,
|
|
57
75
|
onExpandedKeysChange = _ref.onExpandedKeysChange,
|
|
58
76
|
secondSidebarFixed = _ref.secondSidebarFixed,
|
|
@@ -84,6 +102,20 @@ export default function CompanySidebar(_ref) {
|
|
|
84
102
|
var resolvedCustomNavMenus = useMemo(function () {
|
|
85
103
|
return resolveMenuIcons(customNavMenus);
|
|
86
104
|
}, [customNavMenus]);
|
|
105
|
+
|
|
106
|
+
// 叶子 key -> 一级菜单 key 反查表(业务菜单树全量)
|
|
107
|
+
var leafToFirstKeyMap = useMemo(function () {
|
|
108
|
+
return buildLeafToFirstKeyMap(businessMenus);
|
|
109
|
+
}, [businessMenus]);
|
|
110
|
+
|
|
111
|
+
// 内部统一的叶子菜单点击处理:命中业务菜单时同步 activeFirstMenu,保证一级导航同步高亮
|
|
112
|
+
var handleLeafMenuClick = useCallback(function (menu) {
|
|
113
|
+
var firstKey = leafToFirstKeyMap.get(menu.key);
|
|
114
|
+
if (firstKey && firstKey !== activeFirstMenu) {
|
|
115
|
+
onFirstMenuSelect(firstKey);
|
|
116
|
+
}
|
|
117
|
+
onMenuClick(menu);
|
|
118
|
+
}, [leafToFirstKeyMap, activeFirstMenu, onFirstMenuSelect, onMenuClick]);
|
|
87
119
|
useEffect(function () {
|
|
88
120
|
setState(function (prev) {
|
|
89
121
|
return _objectSpread(_objectSpread({}, prev), {}, {
|
|
@@ -133,19 +165,22 @@ export default function CompanySidebar(_ref) {
|
|
|
133
165
|
delayHideSidebar();
|
|
134
166
|
}, [delayHideSidebar]);
|
|
135
167
|
var handleFirstMenuClick = useCallback(function (menu) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
168
|
+
var firstKey = leafToFirstKeyMap.get(menu.key) || menu.key;
|
|
169
|
+
if (firstKey !== activeFirstMenu) {
|
|
170
|
+
onFirstMenuSelect(firstKey);
|
|
171
|
+
}
|
|
172
|
+
onMenuClick(menu);
|
|
173
|
+
}, [leafToFirstKeyMap, activeFirstMenu, onFirstMenuSelect, onMenuClick]);
|
|
139
174
|
var handleMoreSelect = useCallback(function (menu, child) {
|
|
140
175
|
var target = child || menu;
|
|
141
176
|
onFirstMenuSelect(menu.key);
|
|
142
|
-
|
|
177
|
+
onMenuClick(target);
|
|
143
178
|
setState(function (prev) {
|
|
144
179
|
return _objectSpread(_objectSpread({}, prev), {}, {
|
|
145
180
|
moreDrawerOpen: false
|
|
146
181
|
});
|
|
147
182
|
});
|
|
148
|
-
}, [onFirstMenuSelect,
|
|
183
|
+
}, [onFirstMenuSelect, onMenuClick]);
|
|
149
184
|
var handleOpenCustomNav = useCallback(function () {
|
|
150
185
|
setState(function (prev) {
|
|
151
186
|
return _objectSpread(_objectSpread({}, prev), {}, {
|
|
@@ -192,6 +227,7 @@ export default function CompanySidebar(_ref) {
|
|
|
192
227
|
businessMenus: resolvedBusinessMenus,
|
|
193
228
|
customNavMenus: resolvedCustomNavMenus,
|
|
194
229
|
activeKey: activeKey,
|
|
230
|
+
activeFirstMenu: activeFirstMenu,
|
|
195
231
|
visibleMenuCount: visibleMenuCount,
|
|
196
232
|
domainPopoverOpen: state.domainPopoverOpen,
|
|
197
233
|
adminPopoverOpen: state.adminPopoverOpen,
|
|
@@ -232,7 +268,7 @@ export default function CompanySidebar(_ref) {
|
|
|
232
268
|
expandedKeys: state.localExpandedKeys,
|
|
233
269
|
emptyImage: emptyImage,
|
|
234
270
|
onMenuClick: function onMenuClick(menu) {
|
|
235
|
-
|
|
271
|
+
handleLeafMenuClick(menu);
|
|
236
272
|
if (!secondSidebarFixed) {
|
|
237
273
|
delayHideSidebar();
|
|
238
274
|
}
|
|
@@ -7,6 +7,8 @@ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e
|
|
|
7
7
|
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
|
|
8
8
|
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
9
9
|
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
10
|
+
import { iconNames } from "../../shared-components/SvgIcon/icons";
|
|
11
|
+
var VALID_ICONS = new Set(iconNames);
|
|
10
12
|
var KEYWORD_ICON_MAP = [{
|
|
11
13
|
keywords: ["商品", "货品", "物料", "spu", "sku", "product"],
|
|
12
14
|
icon: "commodity"
|
|
@@ -67,7 +69,12 @@ var KEYWORD_ICON_MAP = [{
|
|
|
67
69
|
}];
|
|
68
70
|
var DEFAULT_ICON = "folder-open";
|
|
69
71
|
export function getMenuIcon(menu) {
|
|
70
|
-
if (menu.icon)
|
|
72
|
+
if (menu.icon) {
|
|
73
|
+
if (VALID_ICONS.has(menu.icon)) return menu.icon;
|
|
74
|
+
if (process.env.NODE_ENV !== "production") {
|
|
75
|
+
console.warn("[CompanySidebar] \u83DC\u5355 \"".concat(menu.label, "\" \u7684 icon \"").concat(menu.icon, "\" \u4E0D\u5728\u5185\u7F6E\u56FE\u6807\u96C6\u4E2D\uFF0C\u5DF2\u56DE\u9000\u4E3A\u5173\u952E\u8BCD\u5339\u914D\u3002\u5185\u7F6E\u56FE\u6807\u952E\u53EF\u67E5\u9605\u6587\u6863\u7AD9 /icon-library \u7CBE\u9009\u96C6\u3002"));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
71
78
|
var label = (menu.label || "").toLowerCase();
|
|
72
79
|
var _iterator = _createForOfIteratorHelper(KEYWORD_ICON_MAP),
|
|
73
80
|
_step;
|
|
@@ -171,6 +171,9 @@
|
|
|
171
171
|
justify-content: flex-end;
|
|
172
172
|
padding: calc(var(--spacing-md, 16) * 1px);
|
|
173
173
|
border-top: 1px solid var(--color-border-secondary, rgba(5, 5, 5, 0.06));
|
|
174
|
+
|
|
175
|
+
/* 吸底:表格高度由 scroll.y 控制不一定填满 wrapper,margin-top:auto 保证分页器始终贴白卡底部(对齐 SmartListTemplate 视觉契约) */
|
|
176
|
+
margin-top: auto;
|
|
174
177
|
}
|
|
175
178
|
}
|
|
176
179
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@donglegeyu/company-ui",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.40",
|
|
4
4
|
"main": "dist/cjs/index.js",
|
|
5
5
|
"module": "dist/es/index.js",
|
|
6
6
|
"types": "dist/es/index.d.ts",
|
|
@@ -31,7 +31,8 @@
|
|
|
31
31
|
"test:run": "vitest run",
|
|
32
32
|
"test:coverage": "vitest run --coverage",
|
|
33
33
|
"prepare": "husky",
|
|
34
|
-
"prepublishOnly": "bash scripts/check-clean.sh && npm run build"
|
|
34
|
+
"prepublishOnly": "bash scripts/check-clean.sh && npm run build",
|
|
35
|
+
"verify:skill-examples": "node scripts/verify-skill-examples.mjs"
|
|
35
36
|
},
|
|
36
37
|
"keywords": [
|
|
37
38
|
"antd",
|