@zat-design/sisyphus-react 4.5.10-beta.2 → 4.6.0-beta.2
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/es/ProLayout/components/TabsManager/hooks/useTabsState.js +32 -15
- package/es/ProLayout/components/TabsManager/index.js +9 -1
- package/es/ProLayout/components/TabsManager/propTypes.d.ts +2 -2
- package/es/ProLayout/components/TabsManager/utils/index.d.ts +2 -1
- package/es/ProLayout/components/TabsManager/utils/index.js +8 -0
- package/es/ProLayout/propTypes.d.ts +17 -2
- package/es/ProSelect/index.js +23 -8
- package/es/ProSelect/utils/index.d.ts +3 -2
- package/es/ProSelect/utils/index.js +19 -9
- package/es/ProTable/components/RenderTabs/index.js +6 -2
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
flattenMenuData,
|
|
14
14
|
canOpenAsTab,
|
|
15
15
|
getMenuRoute,
|
|
16
|
+
hasRelationKey,
|
|
16
17
|
findExistingTab,
|
|
17
18
|
normalizeTabUrl,
|
|
18
19
|
isSafeExternalUrl,
|
|
@@ -28,6 +29,7 @@ const useTabsState = (options) => {
|
|
|
28
29
|
const { initialState = {}, config, dataSource, cacheEnabled = true } = options;
|
|
29
30
|
const finalConfig = { ...DEFAULT_TABS_CONFIG, ...config };
|
|
30
31
|
const urlSyncEnabled = finalConfig.urlSync === true || typeof finalConfig.urlSync === "object" && finalConfig.urlSync !== null;
|
|
32
|
+
const urlSyncIdentity = typeof finalConfig.urlSync === "object" && finalConfig.urlSync !== null ? finalConfig.urlSync.identity || "url" : "url";
|
|
31
33
|
const [state, setState] = useState(() => ({
|
|
32
34
|
tabsList: [],
|
|
33
35
|
activeKey: "",
|
|
@@ -62,22 +64,26 @@ const useTabsState = (options) => {
|
|
|
62
64
|
}));
|
|
63
65
|
restoredState.activeKey = restoredState.activeKey === void 0 || restoredState.activeKey === null ? "" : String(restoredState.activeKey);
|
|
64
66
|
if (urlSyncEnabled) {
|
|
65
|
-
const
|
|
67
|
+
const retainedTabByIdentity = /* @__PURE__ */ new Map();
|
|
66
68
|
const retainedIdByOriginalId = /* @__PURE__ */ new Map();
|
|
67
69
|
restoredState.tabsList.forEach((tab) => {
|
|
70
|
+
var _a2;
|
|
68
71
|
const normalizedUrl = normalizeTabUrl(tab.url);
|
|
69
72
|
if (!normalizedUrl)
|
|
70
73
|
return;
|
|
71
|
-
const
|
|
74
|
+
const relationKey = tab.relationKey ?? ((_a2 = tab.menuItem) == null ? void 0 : _a2.relationKey);
|
|
75
|
+
const identity = urlSyncIdentity === "relationKey" && hasRelationKey(relationKey) ? `relationKey:${typeof relationKey}:${String(relationKey)}` : `url:${normalizedUrl}`;
|
|
76
|
+
const retainedTab = retainedTabByIdentity.get(identity);
|
|
72
77
|
if (retainedTab) {
|
|
78
|
+
retainedTabByIdentity.set(identity, { ...retainedTab, url: normalizedUrl });
|
|
73
79
|
retainedIdByOriginalId.set(tab.id, retainedTab.id);
|
|
74
80
|
return;
|
|
75
81
|
}
|
|
76
82
|
const normalizedTab = { ...tab, url: normalizedUrl };
|
|
77
|
-
|
|
83
|
+
retainedTabByIdentity.set(identity, normalizedTab);
|
|
78
84
|
retainedIdByOriginalId.set(tab.id, normalizedTab.id);
|
|
79
85
|
});
|
|
80
|
-
restoredState.tabsList = Array.from(
|
|
86
|
+
restoredState.tabsList = Array.from(retainedTabByIdentity.values());
|
|
81
87
|
restoredState.activeKey = retainedIdByOriginalId.get(restoredState.activeKey) || ((_a = restoredState.tabsList[0]) == null ? void 0 : _a.id) || "";
|
|
82
88
|
}
|
|
83
89
|
restoredState.activeTabInfo = restoredState.tabsList.find(
|
|
@@ -87,7 +93,7 @@ const useTabsState = (options) => {
|
|
|
87
93
|
setState(restoredState);
|
|
88
94
|
}
|
|
89
95
|
setIsInitialized(true);
|
|
90
|
-
}, [restoreFromCache, urlSyncEnabled]);
|
|
96
|
+
}, [restoreFromCache, urlSyncEnabled, urlSyncIdentity]);
|
|
91
97
|
const lastActiveKeyRef = useRef("");
|
|
92
98
|
const shouldSkipSaveRef = useRef(false);
|
|
93
99
|
const initialTabsAppliedRef = useRef(false);
|
|
@@ -125,7 +131,8 @@ const useTabsState = (options) => {
|
|
|
125
131
|
}
|
|
126
132
|
if (urlSyncEnabled || !forceNew) {
|
|
127
133
|
const existingTab = findExistingTab(state.tabsList, menuItem, {
|
|
128
|
-
urlSync: urlSyncEnabled
|
|
134
|
+
urlSync: urlSyncEnabled,
|
|
135
|
+
identity: urlSyncIdentity
|
|
129
136
|
});
|
|
130
137
|
if (existingTab) {
|
|
131
138
|
return true;
|
|
@@ -136,7 +143,7 @@ const useTabsState = (options) => {
|
|
|
136
143
|
}
|
|
137
144
|
return true;
|
|
138
145
|
},
|
|
139
|
-
[state.tabsList, finalConfig, urlSyncEnabled]
|
|
146
|
+
[state.tabsList, finalConfig, urlSyncEnabled, urlSyncIdentity]
|
|
140
147
|
);
|
|
141
148
|
const addTab = useCallback(
|
|
142
149
|
(menuItem, options2) => {
|
|
@@ -161,9 +168,18 @@ const useTabsState = (options) => {
|
|
|
161
168
|
return prevState;
|
|
162
169
|
}
|
|
163
170
|
const resolvedMenuItem = normalizedUrl ? { ...menuItem, url: normalizedUrl, redirectUrl: void 0 } : menuItem;
|
|
164
|
-
const existingTab = urlSyncEnabled || !forceNew ? findExistingTab(prevState.tabsList, resolvedMenuItem, {
|
|
171
|
+
const existingTab = urlSyncEnabled || !forceNew ? findExistingTab(prevState.tabsList, resolvedMenuItem, {
|
|
172
|
+
urlSync: urlSyncEnabled,
|
|
173
|
+
identity: urlSyncIdentity
|
|
174
|
+
}) : void 0;
|
|
165
175
|
if (existingTab) {
|
|
166
|
-
const
|
|
176
|
+
const shouldFixClosable = resolvedMenuItem.closable === false && existingTab.closable !== false;
|
|
177
|
+
const shouldUpdateUrl = urlSyncIdentity === "relationKey" && normalizedUrl !== void 0 && existingTab.url !== normalizedUrl;
|
|
178
|
+
const correctedTab = shouldFixClosable || shouldUpdateUrl ? {
|
|
179
|
+
...existingTab,
|
|
180
|
+
...shouldFixClosable ? { closable: false } : {},
|
|
181
|
+
...shouldUpdateUrl ? { url: normalizedUrl } : {}
|
|
182
|
+
} : existingTab;
|
|
167
183
|
const updatedTabsList = correctedTab !== existingTab ? prevState.tabsList.map((t) => t.id === existingTab.id ? correctedTab : t) : prevState.tabsList;
|
|
168
184
|
return {
|
|
169
185
|
...prevState,
|
|
@@ -200,7 +216,7 @@ const useTabsState = (options) => {
|
|
|
200
216
|
};
|
|
201
217
|
});
|
|
202
218
|
},
|
|
203
|
-
[finalConfig, urlSyncEnabled]
|
|
219
|
+
[finalConfig, urlSyncEnabled, urlSyncIdentity]
|
|
204
220
|
);
|
|
205
221
|
useEffect(() => {
|
|
206
222
|
const initialTabs = finalConfig.initialTabs;
|
|
@@ -257,21 +273,22 @@ const useTabsState = (options) => {
|
|
|
257
273
|
(tabId) => {
|
|
258
274
|
setState((prevState) => {
|
|
259
275
|
var _a;
|
|
260
|
-
const
|
|
276
|
+
const targetTabId = tabId ?? prevState.activeKey;
|
|
277
|
+
const tabToRemove = prevState.tabsList.find((tab) => tab.id === targetTabId);
|
|
261
278
|
if (!tabToRemove || !tabToRemove.closable) {
|
|
262
279
|
return prevState;
|
|
263
280
|
}
|
|
264
|
-
const newTabs = prevState.tabsList.filter((tab) => tab.id !==
|
|
281
|
+
const newTabs = prevState.tabsList.filter((tab) => tab.id !== targetTabId);
|
|
265
282
|
let newActiveKey = prevState.activeKey;
|
|
266
283
|
let newActiveTabInfo = prevState.activeTabInfo;
|
|
267
284
|
let newActiveComponent = prevState.activeComponent;
|
|
268
|
-
if (prevState.activeKey ===
|
|
269
|
-
const currentIndex = prevState.tabsList.findIndex((tab) => tab.id ===
|
|
285
|
+
if (prevState.activeKey === targetTabId && newTabs.length > 0) {
|
|
286
|
+
const currentIndex = prevState.tabsList.findIndex((tab) => tab.id === targetTabId);
|
|
270
287
|
const newActiveIndex = Math.min(currentIndex, newTabs.length - 1);
|
|
271
288
|
newActiveTabInfo = newTabs[newActiveIndex];
|
|
272
289
|
newActiveKey = newActiveTabInfo.id;
|
|
273
290
|
newActiveComponent = ((_a = newActiveTabInfo.menuItem) == null ? void 0 : _a.code) || newActiveTabInfo.id;
|
|
274
|
-
} else if (prevState.activeKey ===
|
|
291
|
+
} else if (prevState.activeKey === targetTabId) {
|
|
275
292
|
newActiveKey = "";
|
|
276
293
|
newActiveTabInfo = void 0;
|
|
277
294
|
newActiveComponent = "";
|
|
@@ -13,7 +13,7 @@ import { createPortal } from "react-dom";
|
|
|
13
13
|
import { useTabsState } from "./hooks/useTabsState";
|
|
14
14
|
import { useTabsUrlSync } from "./hooks/useTabsUrlSync";
|
|
15
15
|
import { useIframeRoute } from "./hooks/useIframeRoute";
|
|
16
|
-
import { flattenMenuData, resolveTabMenuItem, derivePinned } from "./utils";
|
|
16
|
+
import { flattenMenuData, resolveTabMenuItem, derivePinned, normalizeTabUrl } from "./utils";
|
|
17
17
|
import { TabItemComponent } from "./components/TabItem";
|
|
18
18
|
import { TabsHeader } from "./components/TabsHeader";
|
|
19
19
|
import { TabsContext } from "./components/TabsContext";
|
|
@@ -234,6 +234,13 @@ const TabsManager = forwardRef(
|
|
|
234
234
|
removeTab(tabId);
|
|
235
235
|
},
|
|
236
236
|
updateTab,
|
|
237
|
+
updateTabUrl: (tabId, url) => {
|
|
238
|
+
const normalizedUrl = normalizeTabUrl(url);
|
|
239
|
+
if (!normalizedUrl)
|
|
240
|
+
return;
|
|
241
|
+
markTabInteraction();
|
|
242
|
+
updateTabUrl(tabId, normalizedUrl);
|
|
243
|
+
},
|
|
237
244
|
getTabInfo: () => ({
|
|
238
245
|
tabsList: state.tabsList,
|
|
239
246
|
activeTabInfo: state.tabsList.find((tab) => tab.id === state.activeKey),
|
|
@@ -248,6 +255,7 @@ const TabsManager = forwardRef(
|
|
|
248
255
|
markTabInteraction,
|
|
249
256
|
removeTab,
|
|
250
257
|
updateTab,
|
|
258
|
+
updateTabUrl,
|
|
251
259
|
state.tabsList,
|
|
252
260
|
state.activeKey,
|
|
253
261
|
state.activeComponent,
|
|
@@ -67,8 +67,8 @@ export interface UseTabsStateReturn {
|
|
|
67
67
|
addTab: (menuItem: MenusType, options?: AddTabOptions) => void;
|
|
68
68
|
/** 检查是否可以添加标签页 */
|
|
69
69
|
canAddTab: (menuItem: MenusType, options?: AddTabOptions) => boolean;
|
|
70
|
-
/**
|
|
71
|
-
removeTab: (tabId
|
|
70
|
+
/** 移除指定标签页;不传 tabId 时移除当前激活标签页 */
|
|
71
|
+
removeTab: (tabId?: string) => void;
|
|
72
72
|
/** 更新指定 id 的标签页字段(替换语义;找不到时 no-op) */
|
|
73
73
|
updateTab: (tabId: string, updates: UpdateTabParams) => void;
|
|
74
74
|
/** 更新页签当前 URL,保持 tab.id 不变 */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AddTabParams, TabItem, MenusType } from '../../../propTypes';
|
|
1
|
+
import { AddTabParams, TabItem, MenusType, TabsUrlSyncConfig } from '../../../propTypes';
|
|
2
2
|
/**
|
|
3
3
|
* 获取菜单实际用于路由/签页的路径
|
|
4
4
|
* 约定优先使用 redirectUrl,其次回退 url
|
|
@@ -17,6 +17,7 @@ export declare const getCurrentTabUrl: () => string;
|
|
|
17
17
|
export declare const getTabUrlPathname: (value?: string) => string | undefined;
|
|
18
18
|
export interface FindExistingTabOptions {
|
|
19
19
|
urlSync?: boolean;
|
|
20
|
+
identity?: TabsUrlSyncConfig['identity'];
|
|
20
21
|
}
|
|
21
22
|
export declare const findExistingTab: (tabsList: TabItem[], menuItem: MenusType, options?: FindExistingTabOptions) => TabItem | undefined;
|
|
22
23
|
/**
|
|
@@ -37,6 +37,14 @@ const getTabUrlPathname = (value) => {
|
|
|
37
37
|
};
|
|
38
38
|
const findExistingTab = (tabsList, menuItem, options = {}) => {
|
|
39
39
|
if (options.urlSync) {
|
|
40
|
+
if (options.identity === "relationKey" && hasRelationKey(menuItem.relationKey)) {
|
|
41
|
+
return tabsList.find(
|
|
42
|
+
(tab) => {
|
|
43
|
+
var _a;
|
|
44
|
+
return tab.relationKey === menuItem.relationKey || ((_a = tab.menuItem) == null ? void 0 : _a.relationKey) === menuItem.relationKey;
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
}
|
|
40
48
|
const targetUrl = normalizeTabUrl(getMenuRoute(menuItem));
|
|
41
49
|
if (!targetUrl)
|
|
42
50
|
return void 0;
|
|
@@ -368,6 +368,11 @@ export interface TabsUrlSyncConfig {
|
|
|
368
368
|
* @default 'replace'
|
|
369
369
|
*/
|
|
370
370
|
history?: 'replace' | 'push';
|
|
371
|
+
/**
|
|
372
|
+
* @description 页签复用身份。url 保持既有完整 URL 唯一语义;relationKey 在显式传入时优先按业务关联键复用
|
|
373
|
+
* @default 'url'
|
|
374
|
+
*/
|
|
375
|
+
identity?: 'url' | 'relationKey';
|
|
371
376
|
}
|
|
372
377
|
/**
|
|
373
378
|
* @description 添加标签页的业务参数
|
|
@@ -459,15 +464,25 @@ export interface ProLayoutTabsInstance {
|
|
|
459
464
|
*/
|
|
460
465
|
addTab: (params: AddTabParams, options?: AddTabOptions) => void;
|
|
461
466
|
/**
|
|
462
|
-
* @description
|
|
467
|
+
* @description 删除指定标签页;不传 tabId 时删除当前激活标签页
|
|
468
|
+
* @param tabId 目标标签页 id,省略时使用当前激活标签页
|
|
469
|
+
* @example
|
|
470
|
+
* ```tsx
|
|
471
|
+
* layoutTabs.removeTab();
|
|
472
|
+
* layoutTabs.removeTab('tab-id');
|
|
473
|
+
* ```
|
|
463
474
|
*/
|
|
464
|
-
removeTab: (tabId
|
|
475
|
+
removeTab: (tabId?: string) => void;
|
|
465
476
|
/**
|
|
466
477
|
* @description 更新已存在标签页的展示信息(不会卸载/重挂渲染组件)
|
|
467
478
|
* @param tabId 目标标签页 id
|
|
468
479
|
* @param updates 仅更新传入的字段,extra 为替换式覆盖
|
|
469
480
|
*/
|
|
470
481
|
updateTab: (tabId: string, updates: UpdateTabParams) => void;
|
|
482
|
+
/**
|
|
483
|
+
* @description 就地更新页签完整 URL,保持 tab id 与已挂载组件不变
|
|
484
|
+
*/
|
|
485
|
+
updateTabUrl: (tabId: string, url: string) => void;
|
|
471
486
|
/**
|
|
472
487
|
* @description 获取标签页信息
|
|
473
488
|
*/
|
package/es/ProSelect/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import React, {
|
|
|
14
14
|
import isFunction from "lodash/isFunction";
|
|
15
15
|
import omit from "lodash/omit";
|
|
16
16
|
import isNumber from "lodash/isNumber";
|
|
17
|
+
import isString from "lodash/isString";
|
|
17
18
|
import { useProConfig } from "../ProConfigProvider";
|
|
18
19
|
import Container from "../ProForm/components/Container";
|
|
19
20
|
import AdaptiveTooltip from "./components/AdaptiveTooltip";
|
|
@@ -190,9 +191,25 @@ const ProSelect = (props, ref) => {
|
|
|
190
191
|
const option = findOption(v);
|
|
191
192
|
if (!option)
|
|
192
193
|
return "-";
|
|
193
|
-
|
|
194
|
+
const optionLabel = option[label];
|
|
195
|
+
if (!selectProps.showCodeName)
|
|
196
|
+
return optionLabel;
|
|
197
|
+
if (isString(optionLabel) || isNumber(optionLabel)) {
|
|
198
|
+
return `${option[code]}-${optionLabel}`;
|
|
199
|
+
}
|
|
200
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
201
|
+
option[code],
|
|
202
|
+
"-",
|
|
203
|
+
optionLabel
|
|
204
|
+
] });
|
|
194
205
|
});
|
|
195
|
-
|
|
206
|
+
if (labelList.every((item) => isString(item) || isNumber(item))) {
|
|
207
|
+
return labelList.join("、");
|
|
208
|
+
}
|
|
209
|
+
return labelList.map((item, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
210
|
+
index > 0 ? "、" : null,
|
|
211
|
+
item
|
|
212
|
+
] }, `${String(value2[index] ?? "empty")}-${index}`));
|
|
196
213
|
};
|
|
197
214
|
const defaultFilterOption = useCallback(defaultFilterOptionFn, []);
|
|
198
215
|
const mergedShowSearch = useMemo(() => {
|
|
@@ -282,13 +299,11 @@ const ProSelect = (props, ref) => {
|
|
|
282
299
|
};
|
|
283
300
|
const isReactElement = (element) => isValidElement(element);
|
|
284
301
|
const selectOptionRender = (option) => {
|
|
285
|
-
var _a2, _b2
|
|
302
|
+
var _a2, _b2;
|
|
286
303
|
const currentRecord = ((_a2 = option == null ? void 0 : option.data) == null ? void 0 : _a2.record) || (option == null ? void 0 : option.record);
|
|
287
|
-
const
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
return /* @__PURE__ */ jsx(TooltipOption, { title: String(text), children: OptionRender ? /* @__PURE__ */ jsx("span", { children: OptionRender(currentRecord) }) : /* @__PURE__ */ jsx("span", { children: String(text) }) });
|
|
304
|
+
const optionLabel = ((_b2 = option == null ? void 0 : option.data) == null ? void 0 : _b2.label) ?? (option == null ? void 0 : option.label) ?? "";
|
|
305
|
+
const content = currentRecord && OptionRender ? OptionRender(currentRecord) : optionLabel;
|
|
306
|
+
return /* @__PURE__ */ jsx(TooltipOption, { children: /* @__PURE__ */ jsx("span", { children: content }) });
|
|
292
307
|
};
|
|
293
308
|
const mode = selectProps.mode;
|
|
294
309
|
const handleChange = (value2, rawOption) => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
1
2
|
import type { DataOptionType } from '../propsType';
|
|
2
3
|
/**
|
|
3
4
|
* 返回当前组件可以显示的数据源
|
|
@@ -27,7 +28,7 @@ export declare const getOptionText: ({ item, optionRender, showCodeName, code, l
|
|
|
27
28
|
showCodeName?: boolean;
|
|
28
29
|
code: string;
|
|
29
30
|
label: string;
|
|
30
|
-
}) =>
|
|
31
|
+
}) => ReactNode;
|
|
31
32
|
/** 构建单个 antd Select option 对象 */
|
|
32
33
|
export declare const buildOptionItem: (item: DataOptionType, index: number, config: {
|
|
33
34
|
optionRender?: (item: DataOptionType) => any;
|
|
@@ -36,7 +37,7 @@ export declare const buildOptionItem: (item: DataOptionType, index: number, conf
|
|
|
36
37
|
label: string;
|
|
37
38
|
}) => {
|
|
38
39
|
key: string;
|
|
39
|
-
label:
|
|
40
|
+
label: ReactNode;
|
|
40
41
|
value: any;
|
|
41
42
|
disabled: boolean;
|
|
42
43
|
title: string;
|
|
@@ -2,6 +2,7 @@ import difference from "lodash/difference";
|
|
|
2
2
|
import isNumber from "lodash/isNumber";
|
|
3
3
|
import isObject from "lodash/isObject";
|
|
4
4
|
import isString from "lodash/isString";
|
|
5
|
+
import { createElement, Fragment } from "react";
|
|
5
6
|
const findSelectNameValues = ({
|
|
6
7
|
list = [],
|
|
7
8
|
selectName,
|
|
@@ -130,22 +131,30 @@ const getOptionText = ({
|
|
|
130
131
|
code,
|
|
131
132
|
label
|
|
132
133
|
}) => {
|
|
134
|
+
const itemLabel = item[label];
|
|
133
135
|
if (optionRender) {
|
|
134
136
|
const rendered = optionRender(item);
|
|
135
|
-
return isString(rendered) ? rendered : String(
|
|
137
|
+
return isString(rendered) ? rendered : isObject(itemLabel) ? itemLabel : String(itemLabel ?? "");
|
|
136
138
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
if (!showCodeName) {
|
|
140
|
+
return isObject(itemLabel) ? itemLabel : String(itemLabel ?? "");
|
|
141
|
+
}
|
|
142
|
+
if (isString(itemLabel) || isNumber(itemLabel)) {
|
|
143
|
+
return `${item[code]}-${itemLabel}`;
|
|
144
|
+
}
|
|
145
|
+
return createElement(Fragment, null, item[code], "-", itemLabel);
|
|
139
146
|
};
|
|
140
147
|
const buildOptionItem = (item, index, config) => {
|
|
141
|
-
const
|
|
148
|
+
const optionLabel = getOptionText({ item, ...config });
|
|
149
|
+
const isTextLabel = isString(optionLabel) || isNumber(optionLabel);
|
|
150
|
+
const searchText = isTextLabel ? String(optionLabel) : isString(item[config.label]) || isNumber(item[config.label]) ? String(item[config.label]) : item[config.code] != null ? String(item[config.code]) : "";
|
|
142
151
|
return {
|
|
143
152
|
key: item[config.code] != null ? `${item[config.code]}-${index}` : `option-${index}`,
|
|
144
|
-
label:
|
|
153
|
+
label: optionLabel,
|
|
145
154
|
value: item[config.code] != null ? item[config.code] : void 0,
|
|
146
155
|
disabled: !!item.disabled,
|
|
147
|
-
title:
|
|
148
|
-
searchText
|
|
156
|
+
title: isTextLabel ? String(optionLabel) : void 0,
|
|
157
|
+
searchText,
|
|
149
158
|
record: item
|
|
150
159
|
};
|
|
151
160
|
};
|
|
@@ -156,9 +165,10 @@ const buildSelectOptions = (list, config) => {
|
|
|
156
165
|
return list.map((item, index) => {
|
|
157
166
|
const groupOptions = item.options;
|
|
158
167
|
if (Array.isArray(groupOptions)) {
|
|
168
|
+
const groupLabel = item[config.label];
|
|
159
169
|
return {
|
|
160
|
-
key: item[config.
|
|
161
|
-
label:
|
|
170
|
+
key: isString(groupLabel) || isNumber(groupLabel) ? String(groupLabel) : item[config.code] != null ? String(item[config.code]) : `group-${index}`,
|
|
171
|
+
label: groupLabel,
|
|
162
172
|
options: groupOptions.map(
|
|
163
173
|
(opt, optIndex) => buildOptionItem(opt, optIndex, config)
|
|
164
174
|
)
|
|
@@ -14,7 +14,8 @@ const RenderTabs = (props) => {
|
|
|
14
14
|
formTableProps,
|
|
15
15
|
transformParams
|
|
16
16
|
} = props;
|
|
17
|
-
const { form, onSearch } = formTableProps || {};
|
|
17
|
+
const { form, onSearch, loading } = formTableProps || {};
|
|
18
|
+
const requestLoading = Boolean(loading);
|
|
18
19
|
const [activeKey, setActiveKey] = useState(props.activeKey);
|
|
19
20
|
const [options] = useEnum(code || "__PRO_TABLE_NO_CODE__");
|
|
20
21
|
const fieldValue = Form.useWatch(name, form);
|
|
@@ -48,6 +49,8 @@ const RenderTabs = (props) => {
|
|
|
48
49
|
return null;
|
|
49
50
|
}
|
|
50
51
|
const handleChange = (key) => {
|
|
52
|
+
if (requestLoading)
|
|
53
|
+
return;
|
|
51
54
|
const fieldsValues = (form == null ? void 0 : form.getFieldsValue()) || {};
|
|
52
55
|
setActiveKey(key);
|
|
53
56
|
form.setFieldValue(name, key);
|
|
@@ -65,7 +68,7 @@ const RenderTabs = (props) => {
|
|
|
65
68
|
onChange: handleChange,
|
|
66
69
|
type: "card",
|
|
67
70
|
...tabsProps,
|
|
68
|
-
items: tabItems,
|
|
71
|
+
items: requestLoading ? tabItems.map((item) => ({ ...item, disabled: true })) : tabItems,
|
|
69
72
|
activeKey
|
|
70
73
|
}
|
|
71
74
|
);
|
|
@@ -76,6 +79,7 @@ const RenderTabs = (props) => {
|
|
|
76
79
|
className: "pro-table-segmented",
|
|
77
80
|
options: tabItems.map((item) => ({ label: item.label, value: item.key })),
|
|
78
81
|
...segmentedProps,
|
|
82
|
+
disabled: requestLoading || (segmentedProps == null ? void 0 : segmentedProps.disabled),
|
|
79
83
|
onChange: (value) => handleChange(value),
|
|
80
84
|
value: activeKey
|
|
81
85
|
}
|