@zat-design/sisyphus-react 4.6.0-beta.1 → 4.6.0-beta.3

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.
@@ -15,6 +15,7 @@ import {
15
15
  getMenuRoute,
16
16
  hasRelationKey,
17
17
  findExistingTab,
18
+ getComparableTabUrl,
18
19
  normalizeTabUrl,
19
20
  isSafeExternalUrl,
20
21
  isSafeHttpUrl,
@@ -30,6 +31,7 @@ const useTabsState = (options) => {
30
31
  const finalConfig = { ...DEFAULT_TABS_CONFIG, ...config };
31
32
  const urlSyncEnabled = finalConfig.urlSync === true || typeof finalConfig.urlSync === "object" && finalConfig.urlSync !== null;
32
33
  const urlSyncIdentity = typeof finalConfig.urlSync === "object" && finalConfig.urlSync !== null ? finalConfig.urlSync.identity || "url" : "url";
34
+ const urlSyncBasename = typeof finalConfig.urlSync === "object" && finalConfig.urlSync !== null ? finalConfig.urlSync.basename : void 0;
33
35
  const [state, setState] = useState(() => ({
34
36
  tabsList: [],
35
37
  activeKey: "",
@@ -71,8 +73,11 @@ const useTabsState = (options) => {
71
73
  const normalizedUrl = normalizeTabUrl(tab.url);
72
74
  if (!normalizedUrl)
73
75
  return;
76
+ const comparableUrl = getComparableTabUrl(normalizedUrl, urlSyncBasename);
77
+ if (!comparableUrl)
78
+ return;
74
79
  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}`;
80
+ const identity = urlSyncIdentity === "relationKey" && hasRelationKey(relationKey) ? `relationKey:${typeof relationKey}:${String(relationKey)}` : `url:${comparableUrl}`;
76
81
  const retainedTab = retainedTabByIdentity.get(identity);
77
82
  if (retainedTab) {
78
83
  retainedTabByIdentity.set(identity, { ...retainedTab, url: normalizedUrl });
@@ -93,7 +98,7 @@ const useTabsState = (options) => {
93
98
  setState(restoredState);
94
99
  }
95
100
  setIsInitialized(true);
96
- }, [restoreFromCache, urlSyncEnabled, urlSyncIdentity]);
101
+ }, [restoreFromCache, urlSyncEnabled, urlSyncIdentity, urlSyncBasename]);
97
102
  const lastActiveKeyRef = useRef("");
98
103
  const shouldSkipSaveRef = useRef(false);
99
104
  const initialTabsAppliedRef = useRef(false);
@@ -132,7 +137,8 @@ const useTabsState = (options) => {
132
137
  if (urlSyncEnabled || !forceNew) {
133
138
  const existingTab = findExistingTab(state.tabsList, menuItem, {
134
139
  urlSync: urlSyncEnabled,
135
- identity: urlSyncIdentity
140
+ identity: urlSyncIdentity,
141
+ basename: urlSyncBasename
136
142
  });
137
143
  if (existingTab) {
138
144
  return true;
@@ -143,7 +149,7 @@ const useTabsState = (options) => {
143
149
  }
144
150
  return true;
145
151
  },
146
- [state.tabsList, finalConfig, urlSyncEnabled, urlSyncIdentity]
152
+ [state.tabsList, finalConfig, urlSyncEnabled, urlSyncIdentity, urlSyncBasename]
147
153
  );
148
154
  const addTab = useCallback(
149
155
  (menuItem, options2) => {
@@ -170,11 +176,12 @@ const useTabsState = (options) => {
170
176
  const resolvedMenuItem = normalizedUrl ? { ...menuItem, url: normalizedUrl, redirectUrl: void 0 } : menuItem;
171
177
  const existingTab = urlSyncEnabled || !forceNew ? findExistingTab(prevState.tabsList, resolvedMenuItem, {
172
178
  urlSync: urlSyncEnabled,
173
- identity: urlSyncIdentity
179
+ identity: urlSyncIdentity,
180
+ basename: urlSyncBasename
174
181
  }) : void 0;
175
182
  if (existingTab) {
176
183
  const shouldFixClosable = resolvedMenuItem.closable === false && existingTab.closable !== false;
177
- const shouldUpdateUrl = urlSyncIdentity === "relationKey" && normalizedUrl !== void 0 && existingTab.url !== normalizedUrl;
184
+ const shouldUpdateUrl = urlSyncIdentity === "relationKey" && normalizedUrl !== void 0 && getComparableTabUrl(existingTab.url, urlSyncBasename) !== getComparableTabUrl(normalizedUrl, urlSyncBasename);
178
185
  const correctedTab = shouldFixClosable || shouldUpdateUrl ? {
179
186
  ...existingTab,
180
187
  ...shouldFixClosable ? { closable: false } : {},
@@ -216,7 +223,7 @@ const useTabsState = (options) => {
216
223
  };
217
224
  });
218
225
  },
219
- [finalConfig, urlSyncEnabled, urlSyncIdentity]
226
+ [finalConfig, urlSyncEnabled, urlSyncIdentity, urlSyncBasename]
220
227
  );
221
228
  useEffect(() => {
222
229
  const initialTabs = finalConfig.initialTabs;
@@ -273,21 +280,22 @@ const useTabsState = (options) => {
273
280
  (tabId) => {
274
281
  setState((prevState) => {
275
282
  var _a;
276
- const tabToRemove = prevState.tabsList.find((tab) => tab.id === tabId);
283
+ const targetTabId = tabId ?? prevState.activeKey;
284
+ const tabToRemove = prevState.tabsList.find((tab) => tab.id === targetTabId);
277
285
  if (!tabToRemove || !tabToRemove.closable) {
278
286
  return prevState;
279
287
  }
280
- const newTabs = prevState.tabsList.filter((tab) => tab.id !== tabId);
288
+ const newTabs = prevState.tabsList.filter((tab) => tab.id !== targetTabId);
281
289
  let newActiveKey = prevState.activeKey;
282
290
  let newActiveTabInfo = prevState.activeTabInfo;
283
291
  let newActiveComponent = prevState.activeComponent;
284
- if (prevState.activeKey === tabId && newTabs.length > 0) {
285
- const currentIndex = prevState.tabsList.findIndex((tab) => tab.id === tabId);
292
+ if (prevState.activeKey === targetTabId && newTabs.length > 0) {
293
+ const currentIndex = prevState.tabsList.findIndex((tab) => tab.id === targetTabId);
286
294
  const newActiveIndex = Math.min(currentIndex, newTabs.length - 1);
287
295
  newActiveTabInfo = newTabs[newActiveIndex];
288
296
  newActiveKey = newActiveTabInfo.id;
289
297
  newActiveComponent = ((_a = newActiveTabInfo.menuItem) == null ? void 0 : _a.code) || newActiveTabInfo.id;
290
- } else if (prevState.activeKey === tabId) {
298
+ } else if (prevState.activeKey === targetTabId) {
291
299
  newActiveKey = "";
292
300
  newActiveTabInfo = void 0;
293
301
  newActiveComponent = "";
@@ -3,6 +3,8 @@ import * as ReactRouterDom from "react-router-dom";
3
3
  import {
4
4
  canOpenAsTab,
5
5
  flattenMenuData,
6
+ getBrowserTabUrl,
7
+ getComparableTabUrl,
6
8
  getCurrentTabUrl,
7
9
  getMenuRoute,
8
10
  getTabUrlPathname,
@@ -92,6 +94,7 @@ const useTabsUrlSync = ({
92
94
  const navigator = navigationContext == null ? void 0 : navigationContext.navigator;
93
95
  const enabled = config.urlSync === true || typeof config.urlSync === "object" && config.urlSync !== null;
94
96
  const historyMode = typeof config.urlSync === "object" ? config.urlSync.history || "replace" : "replace";
97
+ const basename = typeof config.urlSync === "object" ? config.urlSync.basename : void 0;
95
98
  const bootstrappedRef = useRef(false);
96
99
  const writingUrlRef = useRef(false);
97
100
  const preserveUrlInteractionRef = useRef(null);
@@ -156,11 +159,14 @@ const useTabsUrlSync = ({
156
159
  if (!enabled || !isInitialized || typeof window === "undefined")
157
160
  return;
158
161
  const currentUrl = normalizeTabUrl(locationChange.url);
159
- if (!currentUrl)
162
+ const comparableCurrentUrl = getComparableTabUrl(currentUrl, basename);
163
+ if (!currentUrl || !comparableCurrentUrl)
160
164
  return;
161
165
  if (handledLocationSequenceRef.current === locationChange.sequence)
162
166
  return;
163
- const exactTab = state.tabsList.find((tab) => normalizeTabUrl(tab.url) === currentUrl);
167
+ const exactTab = state.tabsList.find(
168
+ (tab) => getComparableTabUrl(tab.url, basename) === comparableCurrentUrl
169
+ );
164
170
  if (exactTab) {
165
171
  handledLocationSequenceRef.current = locationChange.sequence;
166
172
  bootstrappedRef.current = true;
@@ -170,16 +176,16 @@ const useTabsUrlSync = ({
170
176
  }
171
177
  return;
172
178
  }
173
- const currentPathname = getTabUrlPathname(currentUrl);
179
+ const currentPathname = getTabUrlPathname(comparableCurrentUrl);
174
180
  const sourceMenus = getSourceMenus(dataSource);
175
181
  const activeTab = state.tabsList.find((tab) => tab.id === state.activeKey);
176
182
  const activeCode = ((_a = activeTab == null ? void 0 : activeTab.menuItem) == null ? void 0 : _a.code) || (activeTab == null ? void 0 : activeTab.code);
177
183
  const activeSourceMenu = activeCode ? sourceMenus.find((item) => item.code === activeCode) : void 0;
178
184
  const activeMenuItem = activeSourceMenu || (activeTab == null ? void 0 : activeTab.menuItem);
179
- const activeBasePathname = activeMenuItem ? getTabUrlPathname(getMenuRoute(activeMenuItem)) : getTabUrlPathname(activeTab == null ? void 0 : activeTab.url);
185
+ const activeBasePathname = activeMenuItem ? getTabUrlPathname(getComparableTabUrl(getMenuRoute(activeMenuItem), basename)) : getTabUrlPathname(getComparableTabUrl(activeTab == null ? void 0 : activeTab.url, basename));
180
186
  const targetMenu = (_b = sourceMenus.map((item) => ({
181
187
  item,
182
- pathname: getTabUrlPathname(getMenuRoute(item))
188
+ pathname: getTabUrlPathname(getComparableTabUrl(getMenuRoute(item), basename))
183
189
  })).filter(
184
190
  (entry) => !!entry.pathname && isSameOrNestedPath(entry.pathname, currentPathname)
185
191
  ).sort((left, right) => right.pathname.length - left.pathname.length)[0]) == null ? void 0 : _b.item;
@@ -223,7 +229,8 @@ const useTabsUrlSync = ({
223
229
  addTab,
224
230
  switchTab,
225
231
  updateTabUrl,
226
- interactionSequence
232
+ interactionSequence,
233
+ basename
227
234
  ]);
228
235
  useEffect(() => {
229
236
  if (!enabled || !isInitialized || !bootstrappedRef.current || typeof window === "undefined") {
@@ -231,13 +238,14 @@ const useTabsUrlSync = ({
231
238
  }
232
239
  const activeTab = state.tabsList.find((tab) => tab.id === state.activeKey);
233
240
  const targetUrl = normalizeTabUrl(activeTab == null ? void 0 : activeTab.url);
241
+ const browserTargetUrl = getBrowserTabUrl(targetUrl, basename);
234
242
  const commitActiveTab = () => {
235
243
  committedActiveKeyRef.current = state.activeKey;
236
244
  committedTabIdsRef.current = new Set(state.tabsList.map((tab) => tab.id));
237
245
  };
238
246
  if (preserveUrlInteractionRef.current !== null) {
239
247
  if (preserveUrlInteractionRef.current === interactionSequence) {
240
- if (targetUrl === getCurrentTabUrl()) {
248
+ if (browserTargetUrl === getCurrentTabUrl()) {
241
249
  preserveUrlInteractionRef.current = null;
242
250
  }
243
251
  commitActiveTab();
@@ -245,7 +253,7 @@ const useTabsUrlSync = ({
245
253
  }
246
254
  preserveUrlInteractionRef.current = null;
247
255
  }
248
- if (!targetUrl || targetUrl === getCurrentTabUrl()) {
256
+ if (!targetUrl || !browserTargetUrl || browserTargetUrl === getCurrentTabUrl()) {
249
257
  const pendingNavigation = pendingDataNavigationRef.current;
250
258
  navigationAttemptRef.current += 1;
251
259
  pendingDataNavigationRef.current = false;
@@ -286,30 +294,34 @@ const useTabsUrlSync = ({
286
294
  pendingDataNavigationRef.current = false;
287
295
  pendingDataNavigationUrlRef.current = null;
288
296
  const currentUrl = getCurrentTabUrl();
289
- if (targetUrl === currentUrl || committedDataNavigationUrl === currentUrl) {
297
+ if (browserTargetUrl === currentUrl || committedDataNavigationUrl === currentUrl) {
290
298
  commitActiveTab();
291
299
  return;
292
300
  }
293
301
  rollbackTabActivation(previousActiveKey, attemptedActiveKey, removeAttemptedTab);
294
302
  };
295
303
  pendingDataNavigationRef.current = true;
296
- pendingDataNavigationUrlRef.current = targetUrl;
297
- void dataRouterContext.router.navigate(getDataRouterUrl(targetUrl, dataRouterContext.basename), {
304
+ pendingDataNavigationUrlRef.current = browserTargetUrl;
305
+ void dataRouterContext.router.navigate(getDataRouterUrl(browserTargetUrl, dataRouterContext.basename), {
298
306
  replace: historyMode === "replace",
299
307
  state: routerState
300
308
  }).then(settleNavigation);
301
309
  } else if (navigator) {
302
310
  if (historyMode === "push") {
303
- navigator.push(targetUrl, routerState);
311
+ navigator.push(browserTargetUrl, routerState);
304
312
  } else {
305
- navigator.replace(targetUrl, routerState);
313
+ navigator.replace(browserTargetUrl, routerState);
306
314
  }
307
315
  commitActiveTab();
308
316
  } else if (historyMode === "push") {
309
- window.history.pushState(createPushHistoryState(window.history.state), "", targetUrl);
317
+ window.history.pushState(
318
+ createPushHistoryState(window.history.state),
319
+ "",
320
+ browserTargetUrl
321
+ );
310
322
  commitActiveTab();
311
323
  } else {
312
- window.history.replaceState(window.history.state, "", targetUrl);
324
+ window.history.replaceState(window.history.state, "", browserTargetUrl);
313
325
  commitActiveTab();
314
326
  }
315
327
  } finally {
@@ -324,7 +336,8 @@ const useTabsUrlSync = ({
324
336
  interactionSequence,
325
337
  navigator,
326
338
  dataRouterContext,
327
- rollbackTabActivation
339
+ rollbackTabActivation,
340
+ basename
328
341
  ]);
329
342
  };
330
343
  export {
@@ -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: string) => void;
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 不变 */
@@ -14,10 +14,15 @@ export declare const normalizeTabUrl: (value?: string) => string | undefined;
14
14
  export declare const isSafeExternalUrl: (value?: string) => boolean;
15
15
  export declare const isSafeHttpUrl: (value?: string) => boolean;
16
16
  export declare const getCurrentTabUrl: () => string;
17
+ /** 将浏览器地址和 Tab 内部地址转为同一身份,仅按完整路径段移除 basename。 */
18
+ export declare const getComparableTabUrl: (value?: string, basename?: string) => string | undefined;
19
+ /** 将 Tab 内部地址转为浏览器地址,已带 basename 时不重复添加。 */
20
+ export declare const getBrowserTabUrl: (value?: string, basename?: string) => string | undefined;
17
21
  export declare const getTabUrlPathname: (value?: string) => string | undefined;
18
22
  export interface FindExistingTabOptions {
19
23
  urlSync?: boolean;
20
24
  identity?: TabsUrlSyncConfig['identity'];
25
+ basename?: TabsUrlSyncConfig['basename'];
21
26
  }
22
27
  export declare const findExistingTab: (tabsList: TabItem[], menuItem: MenusType, options?: FindExistingTabOptions) => TabItem | undefined;
23
28
  /**
@@ -29,6 +29,49 @@ const isSafeExternalUrl = (value) => {
29
29
  };
30
30
  const isSafeHttpUrl = (value) => !!resolveHttpUrl(value);
31
31
  const getCurrentTabUrl = () => `${window.location.pathname}${window.location.search}${window.location.hash}`;
32
+ const normalizeTabsBasename = (basename) => {
33
+ const normalized = String(basename ?? "").trim();
34
+ if (!normalized || normalized === "/")
35
+ return "";
36
+ return `/${normalized.replace(/^\/+|\/+$/g, "")}`;
37
+ };
38
+ const splitNormalizedTabUrl = (url) => {
39
+ const pathnameEnd = [url.indexOf("?"), url.indexOf("#")].filter((index) => index >= 0).reduce((current, index) => Math.min(current, index), url.length);
40
+ return {
41
+ pathname: url.slice(0, pathnameEnd),
42
+ suffix: url.slice(pathnameEnd)
43
+ };
44
+ };
45
+ const hasPathBasename = (pathname, basename) => {
46
+ const lowerPathname = pathname.toLowerCase();
47
+ const lowerBasename = basename.toLowerCase();
48
+ return lowerPathname === lowerBasename || lowerPathname.startsWith(`${lowerBasename}/`);
49
+ };
50
+ const getComparableTabUrl = (value, basename) => {
51
+ const normalizedUrl = normalizeTabUrl(value);
52
+ if (!normalizedUrl)
53
+ return void 0;
54
+ const normalizedBasename = normalizeTabsBasename(basename);
55
+ if (!normalizedBasename)
56
+ return normalizedUrl;
57
+ const { pathname, suffix } = splitNormalizedTabUrl(normalizedUrl);
58
+ if (!hasPathBasename(pathname, normalizedBasename))
59
+ return normalizedUrl;
60
+ const barePathname = pathname.slice(normalizedBasename.length) || "/";
61
+ return `${barePathname}${suffix}`;
62
+ };
63
+ const getBrowserTabUrl = (value, basename) => {
64
+ const normalizedUrl = normalizeTabUrl(value);
65
+ if (!normalizedUrl)
66
+ return void 0;
67
+ const normalizedBasename = normalizeTabsBasename(basename);
68
+ if (!normalizedBasename)
69
+ return normalizedUrl;
70
+ const { pathname, suffix } = splitNormalizedTabUrl(normalizedUrl);
71
+ if (hasPathBasename(pathname, normalizedBasename))
72
+ return normalizedUrl;
73
+ return `${normalizedBasename}${pathname}${suffix}`;
74
+ };
32
75
  const getTabUrlPathname = (value) => {
33
76
  const normalized = normalizeTabUrl(value);
34
77
  if (!normalized || typeof window === "undefined")
@@ -45,10 +88,10 @@ const findExistingTab = (tabsList, menuItem, options = {}) => {
45
88
  }
46
89
  );
47
90
  }
48
- const targetUrl = normalizeTabUrl(getMenuRoute(menuItem));
91
+ const targetUrl = getComparableTabUrl(getMenuRoute(menuItem), options.basename);
49
92
  if (!targetUrl)
50
93
  return void 0;
51
- return tabsList.find((tab) => normalizeTabUrl(tab.url) === targetUrl);
94
+ return tabsList.find((tab) => getComparableTabUrl(tab.url, options.basename) === targetUrl);
52
95
  }
53
96
  if (hasRelationKey(menuItem.relationKey)) {
54
97
  return tabsList.find(
@@ -232,6 +275,8 @@ export {
232
275
  findExistingTab,
233
276
  flattenMenuData,
234
277
  generateTabId,
278
+ getBrowserTabUrl,
279
+ getComparableTabUrl,
235
280
  getCurrentTabUrl,
236
281
  getMenuRoute,
237
282
  getPinnedBoundary,
@@ -373,6 +373,11 @@ export interface TabsUrlSyncConfig {
373
373
  * @default 'url'
374
374
  */
375
375
  identity?: 'url' | 'relationKey';
376
+ /**
377
+ * @description 浏览器地址中的显式基础路径;Tab 内部 URL 可以不带该前缀
378
+ * @example '/wjs'
379
+ */
380
+ basename?: string;
376
381
  }
377
382
  /**
378
383
  * @description 添加标签页的业务参数
@@ -464,9 +469,15 @@ export interface ProLayoutTabsInstance {
464
469
  */
465
470
  addTab: (params: AddTabParams, options?: AddTabOptions) => void;
466
471
  /**
467
- * @description 删除标签页
472
+ * @description 删除指定标签页;不传 tabId 时删除当前激活标签页
473
+ * @param tabId 目标标签页 id,省略时使用当前激活标签页
474
+ * @example
475
+ * ```tsx
476
+ * layoutTabs.removeTab();
477
+ * layoutTabs.removeTab('tab-id');
478
+ * ```
468
479
  */
469
- removeTab: (tabId: string) => void;
480
+ removeTab: (tabId?: string) => void;
470
481
  /**
471
482
  * @description 更新已存在标签页的展示信息(不会卸载/重挂渲染组件)
472
483
  * @param tabId 目标标签页 id
@@ -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
- return selectProps.showCodeName ? `${option[code]}-${option[label]}` : option == null ? void 0 : option[label];
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
- return labelList == null ? void 0 : labelList.join("、");
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, _c2;
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 text = ((_b2 = option == null ? void 0 : option.data) == null ? void 0 : _b2.searchText) ?? ((_c2 = option == null ? void 0 : option.data) == null ? void 0 : _c2.title) ?? (option == null ? void 0 : option.label) ?? "";
288
- if (!currentRecord) {
289
- return /* @__PURE__ */ jsx(TooltipOption, { title: String(text), children: String(text) });
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
- }) => string;
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: string;
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(item[label] ?? "");
137
+ return isString(rendered) ? rendered : isObject(itemLabel) ? itemLabel : String(itemLabel ?? "");
136
138
  }
137
- const text = showCodeName ? `${item[code]}-${item[label]}` : item[label];
138
- return isString(text) ? text : String(text ?? "");
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 text = getOptionText({ item, ...config });
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: text,
153
+ label: optionLabel,
145
154
  value: item[config.code] != null ? item[config.code] : void 0,
146
155
  disabled: !!item.disabled,
147
- title: text,
148
- searchText: text,
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.label] ?? `group-${index}`,
161
- label: item[config.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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zat-design/sisyphus-react",
3
- "version": "4.6.0-beta.1",
3
+ "version": "4.6.0-beta.3",
4
4
  "license": "MIT",
5
5
  "publishConfig": {
6
6
  "access": "public",