aldehyde 0.2.159 → 0.2.161

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 (210) hide show
  1. package/lib/controls/action/index.js +1 -1
  2. package/lib/controls/action/index.js.map +1 -1
  3. package/lib/controls/action/utils.d.ts +2 -2
  4. package/lib/controls/action/utils.d.ts.map +1 -1
  5. package/lib/controls/action/utils.js +5 -5
  6. package/lib/controls/action/utils.js.map +1 -1
  7. package/lib/controls/entry-control.d.ts.map +1 -1
  8. package/lib/controls/entry-control.js +5 -8
  9. package/lib/controls/entry-control.js.map +1 -1
  10. package/lib/controls/file-export/select-code-export.d.ts +13 -0
  11. package/lib/controls/file-export/select-code-export.d.ts.map +1 -0
  12. package/lib/controls/file-export/select-code-export.js +14 -0
  13. package/lib/controls/file-export/select-code-export.js.map +1 -0
  14. package/lib/detail/button/edit-button.d.ts +11 -0
  15. package/lib/detail/button/edit-button.d.ts.map +1 -0
  16. package/lib/detail/button/edit-button.js +23 -0
  17. package/lib/detail/button/edit-button.js.map +1 -0
  18. package/lib/detail/view/act-dtmpl-view.d.ts +3 -1
  19. package/lib/detail/view/act-dtmpl-view.d.ts.map +1 -1
  20. package/lib/detail/view/act-dtmpl-view.js +9 -3
  21. package/lib/detail/view/act-dtmpl-view.js.map +1 -1
  22. package/lib/{exportor → export}/export-frame.d.ts +4 -0
  23. package/lib/export/export-frame.d.ts.map +1 -0
  24. package/lib/{exportor → export}/export-frame.js +6 -4
  25. package/lib/export/export-frame.js.map +1 -0
  26. package/lib/export/select-code-export-frame.d.ts +49 -0
  27. package/lib/export/select-code-export-frame.d.ts.map +1 -0
  28. package/lib/export/select-code-export-frame.js +145 -0
  29. package/lib/export/select-code-export-frame.js.map +1 -0
  30. package/lib/form/criteria-form.d.ts.map +1 -1
  31. package/lib/form/criteria-form.js +26 -2
  32. package/lib/form/criteria-form.js.map +1 -1
  33. package/lib/hooks/useVarCssColor.d.ts +2 -0
  34. package/lib/hooks/useVarCssColor.d.ts.map +1 -0
  35. package/lib/hooks/useVarCssColor.js +7 -0
  36. package/lib/hooks/useVarCssColor.js.map +1 -0
  37. package/lib/index.d.ts +1 -1
  38. package/lib/index.d.ts.map +1 -1
  39. package/lib/index.js +1 -1
  40. package/lib/index.js.map +1 -1
  41. package/lib/layout/MainPage.d.ts.map +1 -1
  42. package/lib/layout/MainPage.js.map +1 -1
  43. package/lib/layout/menu/block.css +1 -1
  44. package/lib/layout/menu/block.d.ts.map +1 -1
  45. package/lib/layout/menu/block.js +1 -1
  46. package/lib/layout/menu/block.js.map +1 -1
  47. package/lib/layout2/components/userButton.d.ts +5 -0
  48. package/lib/layout2/components/userButton.d.ts.map +1 -0
  49. package/lib/layout2/components/userButton.js +133 -0
  50. package/lib/layout2/components/userButton.js.map +1 -0
  51. package/lib/layout2/css/header.css +38 -0
  52. package/lib/layout2/header.d.ts +12 -0
  53. package/lib/layout2/header.d.ts.map +1 -0
  54. package/lib/layout2/header.js +218 -0
  55. package/lib/layout2/header.js.map +1 -0
  56. package/lib/layout2/imgs/1.png +0 -0
  57. package/lib/layout2/imgs/2.png +0 -0
  58. package/lib/layout2/imgs/3.png +0 -0
  59. package/lib/layout2/imgs/4.png +0 -0
  60. package/lib/layout2/imgs/5.png +0 -0
  61. package/lib/layout2/imgs/6.png +0 -0
  62. package/lib/layout2/imgs/home.png +0 -0
  63. package/lib/layout2/main.d.ts +9 -0
  64. package/lib/layout2/main.d.ts.map +1 -0
  65. package/lib/layout2/main.js +14 -0
  66. package/lib/layout2/main.js.map +1 -0
  67. package/lib/layout2/page.d.ts +7 -0
  68. package/lib/layout2/page.d.ts.map +1 -0
  69. package/lib/layout2/page.js +120 -0
  70. package/lib/layout2/page.js.map +1 -0
  71. package/lib/layout2/sider.d.ts +10 -0
  72. package/lib/layout2/sider.d.ts.map +1 -0
  73. package/lib/layout2/sider.js +259 -0
  74. package/lib/layout2/sider.js.map +1 -0
  75. package/lib/layout2/type/layout.type.d.ts +10 -0
  76. package/lib/layout2/type/layout.type.d.ts.map +1 -0
  77. package/lib/layout2/type/layout.type.js +2 -0
  78. package/lib/layout2/type/layout.type.js.map +1 -0
  79. package/lib/layout2/util/menu.util.d.ts +28 -0
  80. package/lib/layout2/util/menu.util.d.ts.map +1 -0
  81. package/lib/layout2/util/menu.util.js +76 -0
  82. package/lib/layout2/util/menu.util.js.map +1 -0
  83. package/lib/login2/Login.d.ts +10 -0
  84. package/lib/login2/Login.d.ts.map +1 -0
  85. package/lib/login2/Login.js +63 -0
  86. package/lib/login2/Login.js.map +1 -0
  87. package/lib/login2/LoginPage.d.ts +4 -0
  88. package/lib/login2/LoginPage.d.ts.map +1 -0
  89. package/lib/login2/LoginPage.js +42 -0
  90. package/lib/login2/LoginPage.js.map +1 -0
  91. package/lib/login2/img/login-bg.png +0 -0
  92. package/lib/login2/index.d.ts +4 -0
  93. package/lib/login2/index.d.ts.map +1 -0
  94. package/lib/login2/index.js +4 -0
  95. package/lib/login2/index.js.map +1 -0
  96. package/lib/module/ltmpl-table.d.ts +4 -2
  97. package/lib/module/ltmpl-table.d.ts.map +1 -1
  98. package/lib/module/ltmpl-table.js +10 -8
  99. package/lib/module/ltmpl-table.js.map +1 -1
  100. package/lib/routable/dtmpl-route.d.ts +3 -2
  101. package/lib/routable/dtmpl-route.d.ts.map +1 -1
  102. package/lib/routable/dtmpl-route.js +20 -16
  103. package/lib/routable/dtmpl-route.js.map +1 -1
  104. package/lib/routable/import-route.d.ts +3 -2
  105. package/lib/routable/import-route.d.ts.map +1 -1
  106. package/lib/routable/import-route.js +10 -6
  107. package/lib/routable/import-route.js.map +1 -1
  108. package/lib/routable/ltmpl-route.d.ts +1 -0
  109. package/lib/routable/ltmpl-route.d.ts.map +1 -1
  110. package/lib/routable/ltmpl-route.js +21 -15
  111. package/lib/routable/ltmpl-route.js.map +1 -1
  112. package/lib/routable/ttmpl-route.d.ts +3 -2
  113. package/lib/routable/ttmpl-route.d.ts.map +1 -1
  114. package/lib/routable/ttmpl-route.js +13 -9
  115. package/lib/routable/ttmpl-route.js.map +1 -1
  116. package/lib/routable/withroute.d.ts +1 -1
  117. package/lib/routable/withroute.d.ts.map +1 -1
  118. package/lib/routable/withroute.js +3 -3
  119. package/lib/routable/withroute.js.map +1 -1
  120. package/lib/table/act-table.d.ts +6 -3
  121. package/lib/table/act-table.d.ts.map +1 -1
  122. package/lib/table/act-table.js +110 -88
  123. package/lib/table/act-table.js.map +1 -1
  124. package/lib/table/index.css +4 -4
  125. package/lib/table/query-table.d.ts +1 -1
  126. package/lib/table/query-table.d.ts.map +1 -1
  127. package/lib/table/query-table.js +24 -16
  128. package/lib/table/query-table.js.map +1 -1
  129. package/lib/table/relation-table.d.ts +2 -2
  130. package/lib/table/relation-table.d.ts.map +1 -1
  131. package/lib/table/relation-table.js +5 -5
  132. package/lib/table/relation-table.js.map +1 -1
  133. package/lib/table/select-table.js +2 -2
  134. package/lib/table/select-table.js.map +1 -1
  135. package/lib/tmpl/hc-data-source.d.ts.map +1 -1
  136. package/lib/tmpl/hc-data-source.js +2 -3
  137. package/lib/tmpl/hc-data-source.js.map +1 -1
  138. package/lib/tmpl/hcservice-v3.d.ts +3 -2
  139. package/lib/tmpl/hcservice-v3.d.ts.map +1 -1
  140. package/lib/tmpl/hcservice-v3.js +11 -2
  141. package/lib/tmpl/hcservice-v3.js.map +1 -1
  142. package/lib/tmpl/interface.d.ts +41 -6
  143. package/lib/tmpl/interface.d.ts.map +1 -1
  144. package/lib/tmpl/tmpl-config-analysis.d.ts.map +1 -1
  145. package/lib/tmpl/tmpl-config-analysis.js +33 -27
  146. package/lib/tmpl/tmpl-config-analysis.js.map +1 -1
  147. package/lib/tree/tmpl-tree.d.ts.map +1 -1
  148. package/lib/tree/tmpl-tree.js +2 -1
  149. package/lib/tree/tmpl-tree.js.map +1 -1
  150. package/lib/welcome/HCWelcome.d.ts +1 -1
  151. package/lib/welcome/HCWelcome.js +254 -169
  152. package/lib/welcome/HCWelcome.js.map +1 -1
  153. package/lib/welcome/img/welcome.png +0 -0
  154. package/package.json +1 -1
  155. package/src/aldehyde/controls/action/index.tsx +1 -1
  156. package/src/aldehyde/controls/action/utils.tsx +4 -5
  157. package/src/aldehyde/controls/entry-control.tsx +5 -8
  158. package/src/aldehyde/controls/file-export/select-code-export.tsx +40 -0
  159. package/src/aldehyde/detail/button/edit-button.tsx +51 -0
  160. package/src/aldehyde/detail/view/act-dtmpl-view.tsx +14 -2
  161. package/src/aldehyde/{exportor → export}/export-frame.tsx +10 -6
  162. package/src/aldehyde/export/select-code-export-frame.tsx +218 -0
  163. package/src/aldehyde/form/criteria-form.tsx +35 -0
  164. package/src/aldehyde/hooks/useVarCssColor.ts +6 -0
  165. package/src/aldehyde/index.tsx +2 -2
  166. package/src/aldehyde/layout/MainPage.tsx +8 -6
  167. package/src/aldehyde/layout/menu/block.css +1 -1
  168. package/src/aldehyde/layout/menu/block.tsx +1 -0
  169. package/src/aldehyde/layout2/components/userButton.tsx +171 -0
  170. package/src/aldehyde/layout2/css/header.css +38 -0
  171. package/src/aldehyde/layout2/header.tsx +334 -0
  172. package/src/aldehyde/layout2/imgs/1.png +0 -0
  173. package/src/aldehyde/layout2/imgs/2.png +0 -0
  174. package/src/aldehyde/layout2/imgs/3.png +0 -0
  175. package/src/aldehyde/layout2/imgs/4.png +0 -0
  176. package/src/aldehyde/layout2/imgs/5.png +0 -0
  177. package/src/aldehyde/layout2/imgs/6.png +0 -0
  178. package/src/aldehyde/layout2/imgs/home.png +0 -0
  179. package/src/aldehyde/layout2/imgs/s.svg +3 -0
  180. package/src/aldehyde/layout2/main.tsx +27 -0
  181. package/src/aldehyde/layout2/page.tsx +169 -0
  182. package/src/aldehyde/layout2/sider.tsx +357 -0
  183. package/src/aldehyde/layout2/type/layout.type.ts +10 -0
  184. package/src/aldehyde/layout2/util/menu.util.tsx +112 -0
  185. package/src/aldehyde/login2/Login.tsx +110 -0
  186. package/src/aldehyde/login2/LoginPage.tsx +58 -0
  187. package/src/aldehyde/login2/img/login-bg.png +0 -0
  188. package/src/aldehyde/login2/index.tsx +4 -0
  189. package/src/aldehyde/module/ltmpl-table.tsx +12 -9
  190. package/src/aldehyde/routable/dtmpl-route.tsx +141 -121
  191. package/src/aldehyde/routable/import-route.tsx +28 -23
  192. package/src/aldehyde/routable/ltmpl-route.tsx +82 -56
  193. package/src/aldehyde/routable/ttmpl-route.tsx +73 -55
  194. package/src/aldehyde/routable/withroute.tsx +21 -18
  195. package/src/aldehyde/table/act-table.tsx +88 -66
  196. package/src/aldehyde/table/index.css +4 -4
  197. package/src/aldehyde/table/query-table.tsx +27 -20
  198. package/src/aldehyde/table/relation-table.tsx +7 -7
  199. package/src/aldehyde/table/select-table.tsx +2 -2
  200. package/src/aldehyde/tmpl/hc-data-source.tsx +373 -352
  201. package/src/aldehyde/tmpl/hcservice-v3.tsx +33 -17
  202. package/src/aldehyde/tmpl/interface.tsx +43 -6
  203. package/src/aldehyde/tmpl/tmpl-config-analysis.tsx +307 -247
  204. package/src/aldehyde/tree/tmpl-tree.tsx +2 -1
  205. package/src/aldehyde/welcome/HCWelcome.js +270 -235
  206. package/src/aldehyde/welcome/img/welcome.png +0 -0
  207. package/lib/exportor/export-frame.d.ts.map +0 -1
  208. package/lib/exportor/export-frame.js.map +0 -1
  209. /package/lib/{exportor → export}/export-frame.css +0 -0
  210. /package/src/aldehyde/{exportor → export}/export-frame.css +0 -0
@@ -0,0 +1,169 @@
1
+ import { Layout, theme } from "antd";
2
+ import React, {
3
+ HTMLAttributeAnchorTarget,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from "react";
8
+ import Header from "./header";
9
+ import Sider from "./sider";
10
+ import Main from "./main";
11
+ import HcserviceV3 from "../tmpl/hcservice-v3";
12
+ import { MenuType } from "./type/layout.type";
13
+ import { BlockType, MenuConfigAPIType } from "../tmpl/interface";
14
+ import { useVarCssColor } from "../hooks/useVarCssColor";
15
+ import { generate } from "@ant-design/colors";
16
+
17
+ type PagePropsType = {
18
+ children?: React.ReactNode;
19
+ };
20
+
21
+ const handleMenuItemUrl = (
22
+ id: string,
23
+ pageType: BlockType["pageType"],
24
+ query: { [key: string]: string } = {},
25
+ customPath?: string
26
+ ) => {
27
+ if (customPath) return customPath;
28
+
29
+ const queryParam = { ...query };
30
+ queryParam["menuId"] = id;
31
+
32
+ let routePath = "",
33
+ operator = "";
34
+
35
+ switch (pageType) {
36
+ case "列表":
37
+ routePath = "act-table";
38
+ break;
39
+ case "树":
40
+ routePath = "act-tree";
41
+ break;
42
+ case "添加":
43
+ routePath = "detail-edit";
44
+ operator = "new";
45
+ break;
46
+ case "编辑":
47
+ routePath = "detail-edit";
48
+ operator = "listop";
49
+ break;
50
+ case "编辑或添加":
51
+ routePath = "detail-edit";
52
+ operator = "listop-new";
53
+ break;
54
+ case "详情":
55
+ routePath = "detail-view";
56
+ operator = "listop";
57
+ break;
58
+ default:
59
+ routePath = "";
60
+ }
61
+
62
+ if (operator !== "") queryParam["codeSource"] = operator;
63
+ return `v2/${id}/${routePath}?${Object.entries(queryParam)
64
+ .map(([key, val]) => `${key}=${val}`)
65
+ .join("&")}`;
66
+ };
67
+
68
+ const handleMenuRes = (menuList: MenuConfigAPIType["blocks"]): MenuType[] => {
69
+ const retList: MenuType[] = [];
70
+
71
+ menuList.sort((a, b) => {
72
+ const aOrder = Number(a.order);
73
+ const bOrder = Number(b.order);
74
+ if (aOrder < bOrder) return -1;
75
+ if (aOrder > bOrder) return 1;
76
+ return 0;
77
+ });
78
+
79
+ for (const {
80
+ id,
81
+ title,
82
+ disabled,
83
+ hiddenOnDisabled,
84
+ customPath,
85
+ pageType,
86
+ linkTarget,
87
+ defaultCriteriaValue,
88
+ items,
89
+ } of menuList) {
90
+ if (
91
+ hiddenOnDisabled === true ||
92
+ hiddenOnDisabled === undefined ||
93
+ hiddenOnDisabled === null
94
+ ) {
95
+ const menu: MenuType = {
96
+ id,
97
+ label: title,
98
+ disabled: disabled === undefined ? false : disabled,
99
+ url: handleMenuItemUrl(id, pageType, defaultCriteriaValue, customPath),
100
+ linkTarget,
101
+ children: items?.length ? handleMenuRes(items) : [],
102
+ };
103
+
104
+ retList.push(menu);
105
+ }
106
+ }
107
+
108
+ return retList;
109
+ };
110
+
111
+ const getMenuConfig = async (): Promise<{
112
+ systemName: string;
113
+ menu: MenuType[];
114
+ }> => {
115
+ const res = await HcserviceV3.requestBlocks("", "");
116
+
117
+ const menuList: MenuType[] = handleMenuRes(res.blocks);
118
+
119
+ return {
120
+ menu: menuList,
121
+ systemName: res.programName,
122
+ };
123
+ };
124
+
125
+ const { useToken } = theme;
126
+
127
+ const Page: React.FC<PagePropsType> = (props: PagePropsType) => {
128
+ const {
129
+ token: { colorPrimary },
130
+ } = useToken();
131
+
132
+ const [systemName, setSystemName] = useState("");
133
+
134
+ const [menu, SetMenu] = useState<MenuType[]>([]);
135
+
136
+ useEffect(() => {
137
+ getMenuConfig().then(({ menu, systemName: name }) => {
138
+ setSystemName(name);
139
+ SetMenu(menu);
140
+ });
141
+ }, []);
142
+
143
+ // page ref
144
+ const pageRef = useRef<HTMLDivElement>();
145
+ useEffect(() => {
146
+ useVarCssColor(generate(colorPrimary));
147
+ }, []);
148
+
149
+ return (
150
+ <div
151
+ ref={pageRef}
152
+ style={{
153
+ width: "100%",
154
+ height: "100%",
155
+ position: "absolute",
156
+ }}
157
+ >
158
+ <Layout style={{ height: "100%" }}>
159
+ <Header systemName={systemName} menuList={menu}></Header>
160
+ <Layout>
161
+ <Sider menuList={menu}></Sider>
162
+ <Main>{props.children}</Main>
163
+ </Layout>
164
+ </Layout>
165
+ </div>
166
+ );
167
+ };
168
+
169
+ export default Page;
@@ -0,0 +1,357 @@
1
+ import { ConfigProvider, Layout, Menu, MenuProps, theme, Tooltip } from "antd";
2
+ import React, { useEffect, useRef, useState } from "react";
3
+ import { MenuType } from "./type/layout.type";
4
+ import { NavLink, useParams } from "react-router-dom";
5
+ import {
6
+ getLeftMostRouteInfo,
7
+ getTargetMenuItemIdRouteList,
8
+ handlePropsMenuToAntdMenu,
9
+ } from "./util/menu.util";
10
+ import { useLocale } from "../locale/useLocale";
11
+ import { generate } from "@ant-design/colors";
12
+
13
+ type SiderPropsType = {
14
+ menuList: MenuType[];
15
+ style?: typeof Layout.Sider.defaultProps.style;
16
+ };
17
+
18
+ type MenuItem = Required<MenuProps>["items"][number];
19
+
20
+ type MenuItemIdToFirstFloorIdxMapType = { [key: string]: number };
21
+
22
+ type SecoundFloorMenuList = MenuType[][];
23
+
24
+ const items: MenuItem[] = [
25
+ {
26
+ label: "Navigation One",
27
+ key: "mail",
28
+ },
29
+ {
30
+ label: "Navigation Two",
31
+ key: "app",
32
+ disabled: false,
33
+ },
34
+ {
35
+ label: "Navigation Two",
36
+ key: "app2",
37
+ disabled: false,
38
+ },
39
+ {
40
+ label: "Navigation Two",
41
+ key: "app3",
42
+ disabled: false,
43
+ },
44
+ {
45
+ label: "Navigation Two",
46
+ key: "app4",
47
+ disabled: true,
48
+ },
49
+ {
50
+ label: "Navigation Two",
51
+ key: "app5",
52
+ disabled: true,
53
+ },
54
+ {
55
+ label: "Navigation Two",
56
+ key: "app6",
57
+ disabled: true,
58
+ },
59
+ {
60
+ label: "Navigation Two",
61
+ key: "app7",
62
+ disabled: true,
63
+ },
64
+ {
65
+ label: "Navigation Two",
66
+ key: "app8",
67
+ disabled: true,
68
+ },
69
+ {
70
+ label: "Navigation Two",
71
+ key: "app9",
72
+ disabled: true,
73
+ },
74
+ {
75
+ label: "Navigation Two",
76
+ key: "app10",
77
+ disabled: true,
78
+ },
79
+ {
80
+ label: "Navigation Two",
81
+ key: "app11",
82
+ disabled: true,
83
+ },
84
+ {
85
+ label: "Navigation Two",
86
+ key: "app12",
87
+ disabled: false,
88
+ },
89
+ {
90
+ label: "Navigation Two",
91
+ key: "app13",
92
+ disabled: false,
93
+ },
94
+ {
95
+ label: "Navigation Two",
96
+ key: "app14",
97
+ disabled: false,
98
+ },
99
+ {
100
+ label: "Navigation Two",
101
+ key: "app15",
102
+ disabled: false,
103
+ },
104
+ {
105
+ label: "Navigation Two",
106
+ key: "app16",
107
+ disabled: false,
108
+ },
109
+ {
110
+ label: "Navigation Two",
111
+ key: "app17",
112
+ disabled: false,
113
+ },
114
+ {
115
+ label: "Navigation Two",
116
+ key: "app18",
117
+ disabled: false,
118
+ },
119
+ {
120
+ label: "Navigation Three - Submenu",
121
+ key: "SubMenu",
122
+ children: [
123
+ {
124
+ type: "group",
125
+ label: "Item 1",
126
+ children: [
127
+ { label: "Option 1", key: "setting:1" },
128
+ { label: "Option 2", key: "setting:2" },
129
+ ],
130
+ },
131
+ {
132
+ type: "group",
133
+ label: "Item 2",
134
+ children: [
135
+ { label: "Option 3", key: "setting:3" },
136
+ { label: "Option 4", key: "setting:4" },
137
+ ],
138
+ },
139
+ ],
140
+ },
141
+ {
142
+ key: "alipay",
143
+ label: (
144
+ <a href="https://ant.design" target="_blank" rel="noopener noreferrer">
145
+ Navigation Four - Link
146
+ </a>
147
+ ),
148
+ },
149
+ ];
150
+
151
+ /**
152
+ * @param menuList 自定义的menu
153
+ * @param isRoot 是否为根节点
154
+ * @param rootIdx 根节点层级
155
+ * @param mp menu item 对应的根节点 map
156
+ * @returns menu item 对应的根节点 map
157
+ * @desc 获取 menu item 每一项对应其根节点的 map
158
+ */
159
+ const getMenuItemIdToFirstFloorIdxMap = (
160
+ menuList: MenuType[],
161
+ isRoot: boolean,
162
+ rootIdx?: number,
163
+ mp: MenuItemIdToFirstFloorIdxMapType = {}
164
+ ): MenuItemIdToFirstFloorIdxMapType => {
165
+ for (let i = 0; i < menuList.length; i++) {
166
+ const menuItem = menuList[i];
167
+ if (isRoot)
168
+ Array.isArray(menuItem.children) &&
169
+ getMenuItemIdToFirstFloorIdxMap(menuItem.children, false, i, mp);
170
+ else {
171
+ mp[menuItem.id] = rootIdx;
172
+ Array.isArray(menuItem.children) &&
173
+ getMenuItemIdToFirstFloorIdxMap(menuItem.children, false, rootIdx, mp);
174
+ }
175
+ }
176
+
177
+ return mp;
178
+ };
179
+
180
+ /**
181
+ * @param menuList 自定义的menu
182
+ * @returns 下标为 n 对应第 n 个根节点对应的第二层级menu
183
+ * @desc 获取第二层级 menu 与其下标映射的数组
184
+ */
185
+ const getSecoundFloorMenuList = (
186
+ menuList: MenuType[]
187
+ ): SecoundFloorMenuList => {
188
+ const secoundFloorMenuList: SecoundFloorMenuList = Array.from({
189
+ length: menuList.length,
190
+ }).map(() =>
191
+ Array.from({
192
+ length: 0,
193
+ })
194
+ );
195
+
196
+ for (let i = 0; i < menuList.length; i++) {
197
+ const menuItem = menuList[i];
198
+
199
+ Array.isArray(menuItem.children) &&
200
+ (secoundFloorMenuList[i] = menuItem.children);
201
+ }
202
+
203
+ return secoundFloorMenuList;
204
+ };
205
+
206
+ const { useToken } = theme;
207
+
208
+ const Sider: React.FC<SiderPropsType> = ({ menuList, style }) => {
209
+ // token
210
+ const {
211
+ token: { colorPrimary },
212
+ } = useToken();
213
+ const colors = generate(colorPrimary);
214
+
215
+ // translate
216
+ const { translate } = useLocale();
217
+
218
+ const menuItemIdToFirstFloorIdxMap = useRef<
219
+ MenuItemIdToFirstFloorIdxMapType
220
+ >();
221
+ const secoundFloorMenuList = useRef<SecoundFloorMenuList>([]);
222
+ useEffect(() => {
223
+ menuItemIdToFirstFloorIdxMap.current = getMenuItemIdToFirstFloorIdxMap(
224
+ menuList,
225
+ true
226
+ );
227
+ secoundFloorMenuList.current = getSecoundFloorMenuList(menuList);
228
+ }, [menuList]);
229
+
230
+ // menu
231
+ const [menu, setMenu] = useState<MenuItem[]>([]);
232
+ const getMenuWithSecoundFloor = (
233
+ secoundFloorMenu: SecoundFloorMenuList[number]
234
+ ) => {
235
+ return handlePropsMenuToAntdMenu(secoundFloorMenu, (menuItem, floor) => {
236
+ const { disabled, label, children } = menuItem;
237
+
238
+ if (disabled)
239
+ return (
240
+ <div
241
+ style={{
242
+ color: "inherit",
243
+ width: "100%",
244
+ height: "100%",
245
+ display: "block",
246
+ }}
247
+ >
248
+ {translate("${" + label + "}")}
249
+ </div>
250
+ );
251
+
252
+ const { path, target } = getLeftMostRouteInfo(menuItem);
253
+
254
+ if (Array.isArray(children) && !children.length)
255
+ return (
256
+ <Tooltip title={translate("${" + label + "}")}>
257
+ <NavLink
258
+ to={`/${path}`}
259
+ target={target}
260
+ style={{
261
+ color: "inherit",
262
+ width: "100%",
263
+ height: "100%",
264
+ display: "block",
265
+ textOverflow: "ellipsis",
266
+ overflow: "hidden",
267
+ }}
268
+ >
269
+ {translate("${" + label + "}")}
270
+ </NavLink>
271
+ </Tooltip>
272
+ );
273
+
274
+ return label;
275
+ });
276
+ };
277
+
278
+ // menu select
279
+ const [selectedKeys, setSelectedKeys] = useState([]);
280
+ const { sourceId } = useParams();
281
+ useEffect(() => {
282
+ if (!menuList.length) {
283
+ setMenu([]);
284
+ return;
285
+ }
286
+
287
+ const curSiderMenuList =
288
+ secoundFloorMenuList.current[
289
+ menuItemIdToFirstFloorIdxMap.current[sourceId]
290
+ ];
291
+
292
+ if (curSiderMenuList) {
293
+ setMenu(getMenuWithSecoundFloor(curSiderMenuList));
294
+ setSelectedKeys(getTargetMenuItemIdRouteList(curSiderMenuList, sourceId));
295
+ }
296
+ }, [sourceId, menuList]);
297
+
298
+ // default select keys
299
+ useEffect(() => {
300
+ if (sourceId === undefined) {
301
+ if (secoundFloorMenuList.current[0] !== undefined) {
302
+ setMenu(getMenuWithSecoundFloor(secoundFloorMenuList.current[0]));
303
+ setSelectedKeys([]);
304
+ }
305
+ }
306
+ }, [menuList, sourceId]);
307
+
308
+ const menuClick = (openKeys) => {
309
+ setSelectedKeys([...openKeys]);
310
+ };
311
+
312
+ return (
313
+ <Layout.Sider
314
+ style={{
315
+ background: colors[0],
316
+ // color: "#FFFFFF",
317
+ borderInlineEnd: "1px solid rgba(5, 5, 5, 0.06)",
318
+ overflowY: "auto",
319
+ ...style,
320
+ }}
321
+ >
322
+ <ConfigProvider
323
+ theme={{
324
+ components: {
325
+ Menu: {
326
+ itemBg: "transparent",
327
+ // popupBg: "rgba(221, 240, 228)",
328
+ // subMenuItemBg: "rgba(221, 240, 228, .3)",
329
+ itemHoverColor: "#222",
330
+ itemColor: "#222",
331
+ itemSelectedBg: colors[1],
332
+ groupTitleColor: "#222",
333
+ // horizontalItemHoverColor: "rgba(221, 240, 228)",
334
+ // horizontalItemSelectedColor: "rgba(221, 240, 228)",
335
+ fontSize: 14,
336
+ },
337
+ },
338
+ }}
339
+ >
340
+ <Menu
341
+ mode="inline"
342
+ items={menu}
343
+ selectedKeys={selectedKeys}
344
+ openKeys={selectedKeys}
345
+ inlineCollapsed={false}
346
+ style={{
347
+ userSelect: "none",
348
+ borderInlineEnd: "none",
349
+ }}
350
+ onOpenChange={menuClick}
351
+ />
352
+ </ConfigProvider>
353
+ </Layout.Sider>
354
+ );
355
+ };
356
+
357
+ export default Sider;
@@ -0,0 +1,10 @@
1
+ import { HTMLAttributeAnchorTarget } from "react";
2
+
3
+ export type MenuType = {
4
+ id: string;
5
+ label: string; // 菜单标题
6
+ disabled: boolean; // 是否禁用
7
+ url: string; // 菜单链接
8
+ linkTarget?: HTMLAttributeAnchorTarget;
9
+ children?: MenuType[]; // 子菜单
10
+ };
@@ -0,0 +1,112 @@
1
+ import { ReactNode } from "react";
2
+ import { MenuProps } from "antd";
3
+ import { MenuType } from "../type/layout.type";
4
+
5
+ type AntdMenuItemType = Required<MenuProps>["items"][number];
6
+
7
+ /**
8
+ * @param menu 自定义的 menu 树
9
+ * @returns 最左子节点的路由信息: 链接跳转方式和路由路径
10
+ * @desc 获取最左子节点的路由信息
11
+ */
12
+ export const getLeftMostRouteInfo = (
13
+ menu: MenuType
14
+ ): {
15
+ target: MenuType["linkTarget"];
16
+ path: string;
17
+ } => {
18
+ if (Array.isArray(menu.children) && menu.children.length)
19
+ return getLeftMostRouteInfo(menu.children[0]);
20
+ return {
21
+ target: menu.linkTarget,
22
+ path: menu.url,
23
+ };
24
+ };
25
+
26
+ /**
27
+ * @param menuList 自定义的 menuList
28
+ * @returns antd 可以使用的 menuList
29
+ * @desc 将自定义的 menuList 处理成 antd 可以使用的 menuList
30
+ */
31
+ export const handlePropsMenuToAntdMenu = (
32
+ menuList: MenuType[],
33
+ customLabelFn: (
34
+ menuItem: MenuType,
35
+ floor: number
36
+ ) => string | number | ReactNode,
37
+ className?: string,
38
+ floor: number = 0
39
+ ): AntdMenuItemType[] => {
40
+ try {
41
+ const retList: AntdMenuItemType[] = [];
42
+
43
+ for (const item of menuList) {
44
+ const { id, label, disabled, url, linkTarget, children } = item;
45
+
46
+ const menu: AntdMenuItemType = {
47
+ label: customLabelFn(item, floor),
48
+ key: id,
49
+ disabled,
50
+ className,
51
+ children:
52
+ Array.isArray(children) && children.length
53
+ ? handlePropsMenuToAntdMenu(
54
+ children,
55
+ customLabelFn,
56
+ className,
57
+ floor + 1
58
+ )
59
+ : null,
60
+ };
61
+ retList.push(menu);
62
+ }
63
+
64
+ return retList;
65
+ } catch (err) {
66
+ console.log("handlePropsMenuToAntdMenu", err, `menu: ${menuList}`);
67
+ }
68
+ };
69
+
70
+ /**
71
+ * @param menuList 自定义的 menuList
72
+ * @param targetMenuId 目标 menu id
73
+ * @returns 从根节点到目标节点路径
74
+ * @desc 寻找从 menu 根节点到目标节点的路径
75
+ */
76
+ export const getTargetMenuItemIdRouteList = (
77
+ menuList: MenuType[],
78
+ targetMenuId: string
79
+ ): string[] => {
80
+ const routeList: string[] = [];
81
+
82
+ const root: MenuType = {
83
+ id: "",
84
+ label: "",
85
+ disabled: false,
86
+ url: "",
87
+ children: menuList,
88
+ };
89
+
90
+ const dfs = (menuItem: MenuType): boolean => {
91
+ routeList.push(menuItem.id);
92
+
93
+ if (menuItem.id === targetMenuId) return true;
94
+
95
+ let flag = false;
96
+
97
+ for (const menuItemChild of menuItem.children) {
98
+ if (!flag) flag = dfs(menuItemChild);
99
+ else break;
100
+ }
101
+
102
+ if (flag) return true;
103
+
104
+ routeList.pop();
105
+ return false;
106
+ };
107
+
108
+ dfs(root);
109
+
110
+ routeList.shift();
111
+ return routeList;
112
+ };