@zat-design/sisyphus-react 4.5.3 → 4.5.5-beta.1

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.
@@ -98,14 +98,17 @@ function reducer(state, action) {
98
98
  }
99
99
  const ThemeAwareConfigProvider = ({
100
100
  locale,
101
+ theme,
101
102
  children
102
103
  }) => {
103
104
  const {
104
105
  state: themeState
105
106
  } = useTheme();
107
+ // 外部传入的 theme 与 ThemeContext 的 antdConfig 深度合并,外部 theme 优先覆盖默认值
108
+ const mergedTheme = merge({}, themeState.antdConfig, theme);
106
109
  return /*#__PURE__*/_jsx(ConfigProvider, {
107
110
  locale: locale,
108
- theme: themeState.antdConfig,
111
+ theme: mergedTheme,
109
112
  children: /*#__PURE__*/_jsx("div", {
110
113
  children: children
111
114
  })
@@ -149,6 +152,7 @@ export const ProConfigProvider = props => {
149
152
  },
150
153
  children: /*#__PURE__*/_jsx(ThemeAwareConfigProvider, {
151
154
  locale: antdLangMap[lang] ?? zhCN,
155
+ theme: props.theme,
152
156
  children: props.children
153
157
  })
154
158
  })
@@ -97,24 +97,29 @@ const RenderField = ({
97
97
  }
98
98
 
99
99
  // 单行正在编辑时,临时生成一套formItem用来存储中间值,点击取消时候重置回上一次状态
100
- const namePath = getNamePath(name, virtualKey);
101
- const rowData = form.getFieldValue([...namePath, index]) || record || {};
100
+ const namePathKey = useMemo(() => {
101
+ const path = getNamePath(name, virtualKey);
102
+ return Array.isArray(path) ? path.join('.') : String(path);
103
+ }, [name, virtualKey]);
104
+ const namePath = useMemo(() => getNamePath(name, virtualKey), [namePathKey, name, virtualKey]);
105
+ const rowNamePath = useMemo(() => [...namePath, index], [namePath, index]);
106
+ const rowData = form.getFieldValue(rowNamePath) || record || {};
102
107
  let currentValue = dataIndex ? rowData?.[dataIndex] : null;
103
108
 
104
109
  // 构建新的参数格式(与 ProForm 保持一致)
105
110
  const reactiveParams = useMemo(() => ({
106
111
  form,
107
112
  index,
108
- namePath: [...namePath, index]
109
- }), [form, index, namePath]);
113
+ namePath: rowNamePath
114
+ }), [form, index, rowNamePath]);
110
115
 
111
116
  // 保留 options 用于 viewRender 和 formatArgs(兼容旧格式)
112
117
  const options = useMemo(() => ({
113
118
  index,
114
119
  form,
115
120
  name: column?.name,
116
- namePath: [...namePath, index]
117
- }), [index, column?.name, namePath, form]);
121
+ namePath: rowNamePath
122
+ }), [index, column?.name, rowNamePath, form]);
118
123
 
119
124
  // 行参数 - 使用useMemo优化(新格式:values, { form, index, namePath })
120
125
  const rowParams = useMemo(() => [rowData, reactiveParams], [rowData, reactiveParams]);
@@ -141,7 +146,7 @@ const RenderField = ({
141
146
  lastValueType = dynamicProps.valueType ?? valueType(currentValue, rowData, {
142
147
  index,
143
148
  form,
144
- namePath: [...namePath, index],
149
+ namePath: rowNamePath,
145
150
  name: column?.name
146
151
  });
147
152
  }
@@ -253,8 +258,8 @@ const RenderField = ({
253
258
  if (hasFunctionDependency) {
254
259
  // 使用 shouldUpdate 监听同一行的数据变化;shouldUpdate 与 dependencies 互斥,始终优先 shouldUpdate
255
260
  lastFormItemProps.shouldUpdate = (prevValues, currentValues) => {
256
- const prevRow = _get(prevValues, [...namePath, index]);
257
- const currentRow = _get(currentValues, [...namePath, index]);
261
+ const prevRow = _get(prevValues, rowNamePath);
262
+ const currentRow = _get(currentValues, rowNamePath);
258
263
  // 如果行数据发生变化,则重新渲染
259
264
  return !_isEqual(prevRow, currentRow);
260
265
  };
@@ -391,8 +396,11 @@ const RenderField = ({
391
396
  // 使用useCallback优化debounceValidate函数
392
397
  const debounceValidate = useCallback((validateFieldKeys = []) => {
393
398
  setTimeout(() => {
399
+ // 行内联动被动触发的重校验:只校验、不滚动到报错位置(全局/主动保存校验仍会滚动)
400
+ // @ts-ignore 内部选项
394
401
  form.validateFields(validateFieldKeys, {
395
- recursive: true
402
+ recursive: true,
403
+ __skipScrollOnError: true
396
404
  });
397
405
  }, 100);
398
406
  }, [form]);
@@ -408,12 +416,16 @@ const RenderField = ({
408
416
  errorStore.clearCell(record.rowKey, String(column?.dataIndex));
409
417
  }
410
418
  let callArgs = [...innerArgs];
411
- const rowPath = [...namePath, index];
419
+ const rowPath = rowNamePath;
412
420
  if (!onFieldChange && !onChange) {
413
421
  if (dependencies?.length) {
414
422
  const validateFieldKeys = dependencies?.map?.(key => [...rowPath, key]);
415
423
  setTimeout(() => {
416
- form.validateFields(validateFieldKeys);
424
+ // 依赖字段联动重校验:只校验、不滚动
425
+ // @ts-ignore 内部选项
426
+ form.validateFields(validateFieldKeys, {
427
+ __skipScrollOnError: true
428
+ });
417
429
  }, 100);
418
430
  }
419
431
  return;
@@ -531,7 +543,7 @@ const RenderField = ({
531
543
  return;
532
544
  }
533
545
  let callArgs = formatArgs(...args);
534
- const rowPath = [...namePath, index];
546
+ const rowPath = rowNamePath;
535
547
  const row = form.getFieldValue(rowPath, true);
536
548
  const orgRow = _cloneDeep(row);
537
549
  callArgs[1] = row;
@@ -564,7 +576,7 @@ const RenderField = ({
564
576
  name: cellName,
565
577
  ...lastFieldProps,
566
578
  ...TargetComponent?.props,
567
- namePath: [...namePath, index],
579
+ namePath: rowNamePath,
568
580
  disabled: lastDisabled,
569
581
  onChange: handleChange,
570
582
  onBlur: handleBlur,
@@ -574,7 +586,7 @@ const RenderField = ({
574
586
  otherProps: {
575
587
  form,
576
588
  names,
577
- namePath: [...namePath, index],
589
+ namePath: rowNamePath,
578
590
  name: originalName,
579
591
  listName: cellName,
580
592
  // 用于下拉框去重消费,保持和formlist一致
@@ -643,11 +655,11 @@ const RenderField = ({
643
655
  // shouldUpdate 模式下重新获取最新行数据并重算所有响应式属性,返回最新渲染状态(不修改外层闭包)
644
656
  const recalcShouldUpdateState = () => {
645
657
  // 重新获取最新的行数据(shouldUpdate 触发时,通过 getFieldValue 拿到最新值)
646
- const latestRowData = form.getFieldValue([...namePath, index]) || record || {};
658
+ const latestRowData = form.getFieldValue(rowNamePath) || record || {};
647
659
  const latestReactiveParams = {
648
660
  form,
649
661
  index,
650
- namePath: [...namePath, index]
662
+ namePath: rowNamePath
651
663
  };
652
664
  const latestRowParams = [latestRowData, latestReactiveParams];
653
665
 
@@ -3,7 +3,7 @@ import _isEqualWith from "lodash/isEqualWith";
3
3
  import _isEqual from "lodash/isEqual";
4
4
  import _get from "lodash/get";
5
5
  import { customEqualForFunction } from "../../../utils";
6
- import { getNamePath } from "../../utils/tools";
6
+ import { getNamePath, isRecordShallowEqual } from "../../utils/tools";
7
7
  /** 列配置中不应透传到 Form.Item 或 DOM 的字段(与 ProForm Render 保持一致) */
8
8
  export const OMIT_FORM_ITEM_AND_DOM_KEYS = ['format', 'toISOString', 'toCSTString', 'switchValue', 'precision', 'clearNotShow', 'dependNames', 'shouldCellUpdate' // 表格内部性能优化属性,不应传递给 Form.Item
9
9
  ];
@@ -121,8 +121,8 @@ export const arePropsEqual = (prevProps, nextProps) => {
121
121
  // 优化:不直接调用函数,而是比较输入参数(record 和 reactiveParams)
122
122
  // 如果输入参数相同,fieldProps 的返回值应该相同(纯函数假设)
123
123
  if (_isFunction(prevColumn?.fieldProps) && _isFunction(nextColumn?.fieldProps)) {
124
- // 比较 record 数据是否变化
125
- if (!_isEqualWith(prevRecord, nextRecord, customEqualForFunction)) {
124
+ // 比较 record 数据是否变化(浅比较,虚拟滚动性能优化)
125
+ if (!isRecordShallowEqual(prevRecord, nextRecord)) {
126
126
  return false;
127
127
  }
128
128
  // reactiveParams 中的 form、index、namePath 已经在外层比较过了,无需重复比较
@@ -144,7 +144,7 @@ export const arePropsEqual = (prevProps, nextProps) => {
144
144
  // 函数引用变化说明闭包可能捕获了新的外部状态(如异步加载的 list),必须重渲染
145
145
  if (prevFunc !== nextFunc) return false;
146
146
  // 同引用函数,比较输入参数(纯函数假设:输入相同则输出相同)
147
- return _isEqualWith(prevValues, nextValues, customEqualForFunction);
147
+ return isRecordShallowEqual(prevValues, nextValues);
148
148
  }
149
149
  return true; // 如果不是函数或只有一个是函数,认为相等
150
150
  };
@@ -187,15 +187,7 @@ export const arePropsEqual = (prevProps, nextProps) => {
187
187
  // 特殊处理:当使用自定义 component 函数时,比较整个 record 对象
188
188
  // 因为自定义组件可能依赖 record 中的其他字段(不只是当前列的 dataIndex)
189
189
  if (_isFunction(prevColumn?.component) || _isFunction(nextColumn?.component)) {
190
- // 浅比较 record 的所有属性
191
- const prevKeys = Object.keys(prevRecord || {});
192
- const nextKeys = Object.keys(nextRecord || {});
193
- if (prevKeys.length !== nextKeys.length) {
194
- return false;
195
- }
196
-
197
- // 使用 some 方法代替 for 循环
198
- if (prevKeys.some(key => prevRecord?.[key] !== nextRecord?.[key])) {
190
+ if (!isRecordShallowEqual(prevRecord, nextRecord)) {
199
191
  return false;
200
192
  }
201
193
  }
@@ -1,5 +1,4 @@
1
1
  import _isFunction from "lodash/isFunction";
2
- import _isEqual from "lodash/isEqual";
3
2
  import _isBoolean from "lodash/isBoolean";
4
3
  import _isArray from "lodash/isArray";
5
4
  import _cloneDeepWith from "lodash/cloneDeepWith";
@@ -9,7 +8,7 @@ import classnames from 'classnames';
9
8
  import { tools } from '@zat-design/utils';
10
9
  import { QuestionCircleOutlined } from '@ant-design/icons';
11
10
  import { actions, defaultBtnNameMap, defaultSingleActionKeys, defaultMultipleActionKeys, defaultEditingActionKeys } from "./config";
12
- import { customValidate, getNamePath, splitNames, handleScrollToError, cloneDeepFilterNode } from "./tools";
11
+ import { customValidate, getNamePath, splitNames, handleScrollToError, cloneDeepFilterNode, isRecordShallowEqual } from "./tools";
13
12
  import { filterInternalFields } from "../../ProForm/utils";
14
13
  import ProTooltip from "../../ProTooltip";
15
14
  import { RenderField, ActionButton } from "../components";
@@ -407,7 +406,7 @@ export const transformColumns = (columns = [], config, caches) => {
407
406
  if (record === prevRecord) {
408
407
  return true;
409
408
  }
410
- return !_isEqual(record, prevRecord);
409
+ return !isRecordShallowEqual(record, prevRecord);
411
410
  }
412
411
  const key = item.dataIndex || item.key;
413
412
  if (!key) return true;
@@ -35,6 +35,25 @@ export const buildTableRowKey = rowKey => {
35
35
  };
36
36
  };
37
37
 
38
+ /**
39
+ * 表格行数据的浅比较:仅比较第一层字段引用/值,避免虚拟滚动时整行深比较开销。
40
+ * 行对象在本组件场景通常为扁平标量字段;同引用时由调用方另行处理。
41
+ */
42
+ export const isRecordShallowEqual = (a, b) => {
43
+ if (a === b) {
44
+ return true;
45
+ }
46
+ if (!a || !b) {
47
+ return false;
48
+ }
49
+ const aKeys = Object.keys(a);
50
+ const bKeys = Object.keys(b);
51
+ if (aKeys.length !== bKeys.length) {
52
+ return false;
53
+ }
54
+ return aKeys.every(key => a[key] === b[key]);
55
+ };
56
+
38
57
  /**
39
58
  * 深层次对比两个对象且取出来差异值
40
59
  * @param object 比较对象
@@ -132,9 +132,10 @@ const useShouldUpdateForTable = props => {
132
132
  // 使用 ref 存储上一次的 rowParams,避免引用变化导致的重复调用
133
133
  const prevRowParamsRef = useRef(null);
134
134
 
135
- // 只有当 rowParams 内容真正变化时才处理更新
136
- // 或者是第一次初始化
137
- const shouldProcess = !isInitializedRef.current || !_isEqualWith(prevRowParamsRef.current, rowParams, customEqualForFunction);
135
+ // 行数据引用 + 行索引均不变时跳过深比较(虚拟滚动常见路径)
136
+ const prevRowParams = prevRowParamsRef.current;
137
+ const rowDataUnchanged = isInitializedRef.current && prevRowParams?.[0] === rowParams[0] && prevRowParams?.[1]?.index === rowParams[1]?.index;
138
+ const shouldProcess = !isInitializedRef.current || !rowDataUnchanged && !_isEqualWith(prevRowParams, rowParams, customEqualForFunction);
138
139
  if (shouldProcess) {
139
140
  prevRowParamsRef.current = rowParams;
140
141
  isInitializedRef.current = true;
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useMemo, useRef } from 'react';
2
2
  import { useDeepCompareEffect, useRequest as useRequestFunc } from 'ahooks';
3
- import { diffCode, getEnumData, setEnumData, removeEnumData, cacheFieldNames, baseCacheKey, baseStorage } from "../utils";
3
+ import { diffCode, getEnumData, setEnumData, removeEnumData, cacheFieldNames, cleanEnumResponse, baseCacheKey, baseStorage } from "../utils";
4
4
  import locale from "../../locale";
5
5
  import "../utils/eventCenter";
6
6
  const useEnumRequest = (props, dispatch) => {
@@ -209,19 +209,12 @@ const useEnumRequest = (props, dispatch) => {
209
209
  } else if (res.status === 200) {
210
210
  response = res.data;
211
211
  }
212
- // 只返回fieldNames对象的key
213
- if (clear) {
214
- Object.keys(response).forEach(key => {
215
- const options = [...response[key]];
216
- if (ignoreCodes.includes(key)) {
217
- response[key] = options;
218
- } else {
219
- response[key] = options.map(item => {
220
- return cacheFieldNames(fieldNames, item);
221
- });
222
- }
223
- });
224
- }
212
+ // 只返回fieldNames对象的key(非数组值会被安全跳过,避免展开报错)
213
+ response = cleanEnumResponse(response, {
214
+ clear,
215
+ ignoreCodes,
216
+ fieldNames
217
+ });
225
218
  cacheData.data = {
226
219
  ...cacheData.data,
227
220
  ...response
@@ -4,7 +4,7 @@ import _isString from "lodash/isString";
4
4
  import _isFunction from "lodash/isFunction";
5
5
  import _cloneDeep from "lodash/cloneDeep";
6
6
  import { useDeepCompareEffect, useRequest as useRequestFunc } from 'ahooks';
7
- import { message, Radio, Checkbox, Space } from 'antd';
7
+ import { message, Radio, Checkbox, Space, Segmented } from 'antd';
8
8
  import React, { useState, useEffect, useMemo } from 'react';
9
9
  import ProSelect from "../ProSelect";
10
10
  import { useProConfig } from "../ProConfigProvider";
@@ -217,6 +217,17 @@ const ProEnum = props => {
217
217
  fieldValue: fieldValue,
218
218
  dataSource: list
219
219
  });
220
+ case 'Segmented':
221
+ return /*#__PURE__*/_jsx(Segmented, {
222
+ ..._omit(enumProps, ['fieldNames', 'showCodeName']),
223
+ options: list.map(item => ({
224
+ label: item[label],
225
+ value: item[fieldValue],
226
+ disabled: !!item.disabled
227
+ })),
228
+ value: value,
229
+ onChange: onChange
230
+ });
220
231
  default:
221
232
  return null;
222
233
  }
@@ -313,4 +313,38 @@ export function cacheFieldNames(fieldNames, dataSource) {
313
313
  });
314
314
  }
315
315
  return result;
316
+ }
317
+
318
+ /**
319
+ * 对枚举请求返回的数据按 clear/fieldNames 进行清洗
320
+ * @param response 枚举数据 { code: DataOption[] }
321
+ * @param options clear 是否清洗、ignoreCodes 忽略清洗的 code、fieldNames 字段映射
322
+ * @returns 清洗后的新对象(不修改入参)
323
+ * @remark 某个 code 的值非数组时(脏缓存/异常返回)跳过清洗并原样透传,避免展开非可迭代值报错
324
+ */
325
+ export function cleanEnumResponse(response, options) {
326
+ const {
327
+ clear = true,
328
+ ignoreCodes = [],
329
+ fieldNames
330
+ } = options;
331
+ if (!clear || typeof response !== 'object' || response === null) {
332
+ return response;
333
+ }
334
+ const result = {};
335
+ Object.keys(response).forEach(key => {
336
+ const value = response[key];
337
+ // 非数组值(脏缓存、异常返回等)无法展开清洗,原样透传,避免 not iterable 报错
338
+ if (!Array.isArray(value)) {
339
+ result[key] = value;
340
+ return;
341
+ }
342
+ const list = [...value];
343
+ if (ignoreCodes.includes(key)) {
344
+ result[key] = list;
345
+ } else {
346
+ result[key] = list.map(item => cacheFieldNames(fieldNames, item));
347
+ }
348
+ });
349
+ return result;
316
350
  }
@@ -50,6 +50,15 @@ export const useForm = function (originForm, options) {
50
50
  return getFieldsValue(nameList, filterFunc);
51
51
  };
52
52
  const nextValidateFields = async (nameList, ...rest) => {
53
+ // 内部选项:行内联动等被动校验只想触发校验、不想滚动到报错位置;
54
+ // 全局/主动提交校验不传,保持滚动。提取后从传给 antd 底层的选项中剔除,避免污染原生 options。
55
+ // @ts-ignore
56
+ const skipScrollOnError = !!rest?.[0]?.__skipScrollOnError;
57
+ // @ts-ignore
58
+ const restForNative = rest?.[0] ? [(({
59
+ __skipScrollOnError,
60
+ ...opts
61
+ }) => opts)(rest[0]), ...rest.slice(1)] : rest;
53
62
  try {
54
63
  const isRecursive = rest?.[0]?.recursive;
55
64
  const stopOnFirstError = form?.__INTERNAL_CONFIG__?.stopOnFirstError;
@@ -62,18 +71,19 @@ export const useForm = function (originForm, options) {
62
71
  // eslint-disable-next-line no-restricted-syntax
63
72
  for (const field of allFields) {
64
73
  try {
65
- // 创建不包含 stopOnFirstError 的选项
74
+ // 创建不包含 stopOnFirstError / 内部选项的选项
66
75
  // @ts-ignore
67
76
  const options = rest?.[0] ? {
68
77
  ...rest[0]
69
78
  } : {};
70
79
  delete options.stopOnFirstError;
80
+ delete options.__skipScrollOnError;
71
81
  // 验证单个字段
72
82
  // eslint-disable-next-line no-await-in-loop
73
83
  await validateFields([field], options);
74
84
  } catch (error) {
75
- // 遇到错误,滚动到错误位置
76
- if (scrollToError && error?.errorFields?.length) {
85
+ // 遇到错误,滚动到错误位置(skipScrollOnError 时跳过)
86
+ if (!skipScrollOnError && scrollToError && error?.errorFields?.length) {
77
87
  form.scrollToField(error.errorFields[0]?.name, {
78
88
  block: 'center',
79
89
  behavior: 'smooth'
@@ -112,7 +122,7 @@ export const useForm = function (originForm, options) {
112
122
  }
113
123
 
114
124
  // @ts-ignore
115
- return await validateFields(validateNames, ...rest).then(values => {
125
+ return await validateFields(validateNames, ...restForNative).then(values => {
116
126
  return filterInternalFields(values, optimize);
117
127
  });
118
128
  }
@@ -124,17 +134,20 @@ export const useForm = function (originForm, options) {
124
134
  tablePagination?.click?.();
125
135
  }
126
136
  }
127
- return await validateFields(nameList, ...rest).then(values => {
137
+ return await validateFields(nameList, ...restForNative).then(values => {
128
138
  return nameList ? values : nextGetFieldsValue();
129
139
  });
130
140
  } catch (error) {
131
- if (scrollToError && error?.errorFields?.length && source === 'ProForm') {
132
- form.scrollToField(error.errorFields[0]?.name, {
133
- block: 'center',
134
- behavior: 'smooth'
135
- });
141
+ // skipScrollOnError(行内联动等被动校验)时不滚动,仅抛出错误
142
+ if (!skipScrollOnError) {
143
+ if (scrollToError && error?.errorFields?.length && source === 'ProForm') {
144
+ form.scrollToField(error.errorFields[0]?.name, {
145
+ block: 'center',
146
+ behavior: 'smooth'
147
+ });
148
+ }
149
+ handleScrollToErrorProEditTable();
136
150
  }
137
- handleScrollToErrorProEditTable();
138
151
  throw error;
139
152
  }
140
153
  };
@@ -1,4 +1,4 @@
1
- import { Tabs, Form } from 'antd';
1
+ import { Tabs, Form, Segmented } from 'antd';
2
2
  import { useMemo, useState, useEffect, memo } from 'react';
3
3
  import useEnum from "../../../ProEnum/hooks/useEnum";
4
4
  import { jsx as _jsx } from "react/jsx-runtime";
@@ -8,6 +8,8 @@ const RenderTabs = props => {
8
8
  dataSource = [],
9
9
  transformResponse,
10
10
  tabsProps,
11
+ segmentedProps,
12
+ mode = 'Segmented',
11
13
  name,
12
14
  formTableProps,
13
15
  transformParams
@@ -52,25 +54,38 @@ const RenderTabs = props => {
52
54
  if (!tabItems?.length) {
53
55
  return null;
54
56
  }
55
- return /*#__PURE__*/_jsx(Tabs, {
56
- className: "pro-table-tabs",
57
- onChange: key => {
58
- const fieldsValues = form?.getFieldsValue() || {};
59
- setActiveKey(key);
60
- form.setFieldValue(name, key);
61
- let params = {
62
- ...fieldsValues,
63
- [name]: key
64
- };
65
- if (transformParams && typeof transformParams === 'function') {
66
- params = transformParams(params);
67
- }
68
- onSearch?.(params);
69
- },
70
- type: "card",
71
- ...tabsProps,
72
- items: tabItems,
73
- activeKey: activeKey
57
+ const handleChange = key => {
58
+ const fieldsValues = form?.getFieldsValue() || {};
59
+ setActiveKey(key);
60
+ form.setFieldValue(name, key);
61
+ let params = {
62
+ ...fieldsValues,
63
+ [name]: key
64
+ };
65
+ if (transformParams && typeof transformParams === 'function') {
66
+ params = transformParams(params);
67
+ }
68
+ onSearch?.(params);
69
+ };
70
+ if (mode === 'Tab') {
71
+ return /*#__PURE__*/_jsx(Tabs, {
72
+ className: "pro-table-tabs",
73
+ onChange: handleChange,
74
+ type: "card",
75
+ ...tabsProps,
76
+ items: tabItems,
77
+ activeKey: activeKey
78
+ });
79
+ }
80
+ return /*#__PURE__*/_jsx(Segmented, {
81
+ className: "pro-table-segmented",
82
+ options: tabItems.map(item => ({
83
+ label: item.label,
84
+ value: item.key
85
+ })),
86
+ ...segmentedProps,
87
+ onChange: value => handleChange(value),
88
+ value: activeKey
74
89
  });
75
90
  };
76
91
  export default /*#__PURE__*/memo(RenderTabs);
@@ -644,3 +644,8 @@
644
644
  }
645
645
  }
646
646
  }
647
+
648
+ // tabs mode 为 Segmented 时:宽度按内容自适应(靠左),与表格保持 8px 间距
649
+ .pro-table-segmented {
650
+ margin-bottom: 8px;
651
+ }
@@ -1,6 +1,6 @@
1
1
  // 导入语句
2
- import { CheckOutlined, CloseOutlined } from '@ant-design/icons';
3
- import { Button, Drawer, Radio, Switch } from 'antd';
2
+ import { CloseOutlined } from '@ant-design/icons';
3
+ import { Button, ColorPicker, Drawer, Radio, Switch } from 'antd';
4
4
  import React, { useState, useEffect } from 'react';
5
5
  import { setThemes } from "../../utils/index";
6
6
  import { useProConfig } from "../../../ProConfigProvider";
@@ -31,46 +31,24 @@ const ProTools = ({
31
31
  } = useProConfig();
32
32
 
33
33
  // 状态和 Refs
34
- const [active, setActive] = useState([{
35
- color: '#006AFF',
36
- active: true
37
- }, {
38
- color: '#00BC70',
39
- active: false
40
- }, {
41
- color: '#FF8C16',
42
- active: false
43
- }, {
44
- color: '#A00F20',
45
- active: false
46
- }, {
47
- color: '#31AF96',
48
- active: false
49
- }]);
34
+ const [color, setColor] = useState('#006AFF');
50
35
 
51
36
  // 事件处理函数
52
- const handleThemeColorClick = item => {
53
- const array = active.map(activeItem => {
54
- activeItem.active = false;
55
- return {
56
- color: activeItem.color,
57
- active: item.color === activeItem.color
58
- };
59
- });
60
- setActive(array);
37
+ const handleColorChange = hex => {
38
+ setColor(hex);
61
39
  setState({
62
40
  ...state,
63
- zauiBrand: item.color
41
+ zauiBrand: hex
64
42
  });
65
43
  setThemes({
66
- 'zaui-brand': item.color
44
+ 'zaui-brand': hex
67
45
  });
68
46
  dispatch({
69
47
  type: 'set',
70
48
  payload: {
71
49
  theme: {
72
- primaryColor: item.color,
73
- qiankunPrimaryColor: item.color
50
+ primaryColor: hex,
51
+ qiankunPrimaryColor: hex
74
52
  },
75
53
  forms: {}
76
54
  }
@@ -123,22 +101,7 @@ const ProTools = ({
123
101
  });
124
102
  };
125
103
  const handleResetClick = () => {
126
- setActive([{
127
- color: '#006AFF',
128
- active: true
129
- }, {
130
- color: '#00BC70',
131
- active: false
132
- }, {
133
- color: '#FF8C16',
134
- active: false
135
- }, {
136
- color: '#A00F20',
137
- active: false
138
- }, {
139
- color: '#31AF96',
140
- active: false
141
- }]);
104
+ setColor('#006AFF');
142
105
  onReset();
143
106
  };
144
107
 
@@ -155,14 +118,7 @@ const ProTools = ({
155
118
  // 优先使用 CSS 变量的值
156
119
  const finalZauiBrand = existingZauiBrand || zauiBrand;
157
120
  if (finalZauiBrand) {
158
- const newArray = active.map(activeItem => {
159
- activeItem.active = false;
160
- return {
161
- color: activeItem.color,
162
- active: activeItem.color === finalZauiBrand.toLocaleUpperCase()
163
- };
164
- });
165
- setActive(newArray);
121
+ setColor(finalZauiBrand);
166
122
  dispatch({
167
123
  type: 'set',
168
124
  payload: {
@@ -193,15 +149,10 @@ const ProTools = ({
193
149
  className: "pro-theme-tools-space",
194
150
  children: [/*#__PURE__*/_jsx("p", {
195
151
  children: `${locale.ProThemeTools.themeColor}`
196
- }), /*#__PURE__*/_jsx("ul", {
197
- className: "pro-theme-color",
198
- children: active.map((item, index) => {
199
- return /*#__PURE__*/_jsx("li", {
200
- className: item.active ? 'active' : '',
201
- onClick: () => handleThemeColorClick(item),
202
- children: item.active ? /*#__PURE__*/_jsx(CheckOutlined, {}) : null
203
- }, item.color);
204
- })
152
+ }), /*#__PURE__*/_jsx(ColorPicker, {
153
+ value: color,
154
+ showText: true,
155
+ onChangeComplete: value => handleColorChange(value.toHexString())
205
156
  })]
206
157
  }), /*#__PURE__*/_jsxs("div", {
207
158
  className: "pro-theme-tools-space",