@jetlinks-web/components 3.1.15 → 3.2.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.
Files changed (57) hide show
  1. package/es/EditTable/CellRender.js +69 -3
  2. package/es/EditTable/EditTable.js +108 -165
  3. package/es/EditTable/FormItem.js +234 -95
  4. package/es/EditTable/consts.js +13 -13
  5. package/es/EditTable/context.js +3 -2
  6. package/es/EditTable/fieldPool.js +166 -0
  7. package/es/EditTable/hooks/index.js +4 -2
  8. package/es/EditTable/hooks/useValidate.js +121 -51
  9. package/es/EditTable/hooks/useVirtualTreeTable.js +111 -0
  10. package/es/EditTable/index.js +0 -4
  11. package/es/EditTable/style/body.js +15 -2
  12. package/es/EditTable/style/form.js +2 -2
  13. package/es/EditTable/style/header.js +2 -2
  14. package/es/EditTable/style/table.js +2 -1
  15. package/es/Icon/icon.js +3 -3
  16. package/es/ProTable/ProTable.js +5 -0
  17. package/es/Search/Advanced/index.js +1 -1
  18. package/es/Search/Item.js +13 -1
  19. package/es/Search/util.js +1 -1
  20. package/es/VirtualTable/Table.js +367 -0
  21. package/es/VirtualTable/VirtualBody.js +94 -0
  22. package/es/VirtualTable/index.js +1 -1
  23. package/es/VirtualTable/useTreeData.js +243 -0
  24. package/es/VirtualTable/useVirtualScroll.js +159 -0
  25. package/lib/EditTable/CellRender.js +69 -3
  26. package/lib/EditTable/EditTable.js +108 -165
  27. package/lib/EditTable/FormItem.js +234 -95
  28. package/lib/EditTable/consts.js +13 -13
  29. package/lib/EditTable/context.js +3 -2
  30. package/lib/EditTable/fieldPool.js +173 -0
  31. package/lib/EditTable/hooks/index.js +15 -2
  32. package/lib/EditTable/hooks/useValidate.js +120 -50
  33. package/lib/EditTable/hooks/useVirtualTreeTable.js +117 -0
  34. package/lib/EditTable/index.js +0 -4
  35. package/lib/EditTable/style/body.js +15 -2
  36. package/lib/EditTable/style/form.js +2 -2
  37. package/lib/EditTable/style/header.js +2 -2
  38. package/lib/EditTable/style/table.js +2 -1
  39. package/lib/Icon/icon.js +3 -3
  40. package/lib/ProTable/ProTable.js +5 -0
  41. package/lib/Search/Advanced/index.js +1 -1
  42. package/lib/Search/Item.js +13 -1
  43. package/lib/Search/util.js +1 -1
  44. package/lib/VirtualTable/Table.js +374 -0
  45. package/lib/VirtualTable/VirtualBody.js +100 -0
  46. package/lib/VirtualTable/index.js +4 -4
  47. package/lib/VirtualTable/useTreeData.js +250 -0
  48. package/lib/VirtualTable/useVirtualScroll.js +165 -0
  49. package/package.json +3 -3
  50. package/es/EditTable/Body.js +0 -312
  51. package/es/EditTable/Header.js +0 -164
  52. package/es/EditTable/HeaderRender.js +0 -12
  53. package/es/VirtualTable/VirtualTable.js +0 -482
  54. package/lib/EditTable/Body.js +0 -312
  55. package/lib/EditTable/Header.js +0 -164
  56. package/lib/EditTable/HeaderRender.js +0 -12
  57. package/lib/VirtualTable/VirtualTable.js +0 -482
@@ -15,21 +15,26 @@ function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]
15
15
  }
16
16
  } return value; }
17
17
  /* Analyzed bindings: {
18
- "name": "props",
19
- "required": "props",
20
18
  "onBeforeUnmount": "setup-const",
21
19
  "computed": "setup-const",
22
20
  "reactive": "setup-const",
23
21
  "watch": "setup-const",
24
22
  "provide": "setup-const",
23
+ "toRaw": "setup-const",
24
+ "nextTick": "setup-const",
25
+ "onMounted": "setup-const",
25
26
  "get": "setup-maybe-ref",
26
27
  "isArray": "setup-maybe-ref",
28
+ "set": "setup-maybe-ref",
29
+ "cloneDeep": "setup-maybe-ref",
27
30
  "useProvideFormItemContext": "setup-maybe-ref",
31
+ "Schema": "setup-maybe-ref",
28
32
  "useInjectError": "setup-maybe-ref",
29
33
  "useInjectForm": "setup-maybe-ref",
30
34
  "TABLE_FORM_ITEM_ERROR": "setup-maybe-ref",
31
35
  "genEditTableStyle": "setup-maybe-ref",
32
- "props": "setup-reactive-const",
36
+ "fieldPool": "setup-maybe-ref",
37
+ "props": "setup-const",
33
38
  "emit": "setup-const",
34
39
  "prefixCls": "setup-ref",
35
40
  "wrapSSR": "setup-maybe-ref",
@@ -37,70 +42,119 @@ function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]
37
42
  "context": "setup-maybe-ref",
38
43
  "globalErrorMessage": "setup-maybe-ref",
39
44
  "hideTimer": "setup-let",
45
+ "cachedFieldPath": "setup-let",
46
+ "cachedName": "setup-let",
47
+ "fieldPath": "setup-ref",
40
48
  "eventKey": "setup-ref",
49
+ "fieldId": "setup-ref",
50
+ "fieldName": "setup-ref",
51
+ "rowIndex": "setup-ref",
52
+ "fieldValue": "setup-ref",
41
53
  "errorMap": "setup-reactive-const",
42
- "filedId": "setup-ref",
43
- "filedName": "setup-ref",
44
- "filedValue": "setup-ref",
45
54
  "popContainer": "setup-const",
46
55
  "removeTimer": "setup-const",
47
56
  "showErrorTip": "setup-const",
48
57
  "hideErrorTip": "setup-const",
58
+ "getFieldRules": "setup-const",
59
+ "validateField": "setup-const",
49
60
  "validateRules": "setup-const",
50
61
  "onFieldBlur": "setup-const",
51
- "onFieldChange": "setup-const"
62
+ "onFieldChange": "setup-const",
63
+ "isRegistered": "setup-let",
64
+ "registerField": "setup-const",
65
+ "name": "props",
66
+ "required": "props",
67
+ "rules": "props"
52
68
  } */
53
- import { toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, unref as _unref, normalizeClass as _normalizeClass, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, createVNode as _createVNode, renderSlot as _renderSlot, Fragment as _Fragment } from "vue";
69
+ import { defineComponent as _defineComponent } from 'vue';
70
+ import { toDisplayString as _toDisplayString, createElementVNode as _createElementVNode, unref as _unref, normalizeClass as _normalizeClass, openBlock as _openBlock, createElementBlock as _createElementBlock, createCommentVNode as _createCommentVNode, resolveComponent as _resolveComponent, withCtx as _withCtx, createBlock as _createBlock, renderSlot as _renderSlot, Fragment as _Fragment } from "vue";
54
71
  const _hoisted_1 = { style: { "color": "#1d2129" } };
55
72
  const _hoisted_2 = ["id"];
56
- import { onBeforeUnmount, computed, reactive, watch, provide } from "vue";
57
- import { get, isArray } from 'lodash-es';
73
+ import { onBeforeUnmount, computed, reactive, watch, provide, toRaw, nextTick, onMounted } from "vue";
74
+ import { get, isArray, } from 'lodash-es';
58
75
  import { useProvideFormItemContext } from 'ant-design-vue/lib/form/FormItemContext';
76
+ import Schema from 'async-validator';
59
77
  import { useInjectError, useInjectForm } from "./hooks";
60
78
  import { TABLE_FORM_ITEM_ERROR } from "./consts";
61
79
  import genEditTableStyle from './style';
62
- const __sfc_main__ = Object.assign({
63
- name: 'JEditTableFormItem'
64
- }, {
80
+ import { fieldPool } from './fieldPool';
81
+ const __sfc_main__ = _defineComponent({
82
+ ...{
83
+ name: 'JEditTableFormItem'
84
+ },
65
85
  props: {
66
- name: {
67
- type: [String, Array],
68
- default: undefined
69
- },
70
- required: {
71
- type: Boolean,
72
- default: false
73
- }
86
+ name: { type: [String, Array], required: false, default: undefined },
87
+ required: { type: Boolean, required: false, default: false },
88
+ rules: { type: Array, required: false, default: () => [] }
74
89
  },
75
- emits: ['change'],
76
- setup(__props, { emit: __emit }) {
90
+ emits: ["change"],
91
+ setup(__props, { expose: __expose, emit: __emit }) {
77
92
  const props = __props;
78
93
  const emit = __emit;
79
94
  const prefixCls = computed(() => 'jetlinks-edit-table');
80
95
  const [wrapSSR, hashId] = genEditTableStyle(prefixCls);
81
96
  const context = useInjectForm();
82
97
  const globalErrorMessage = useInjectError();
83
- let hideTimer;
84
- const eventKey = computed(() => {
85
- const names = isArray(props.name) ? props.name : [props.name];
86
- return names.join('-');
87
- });
88
- const errorMap = reactive({
89
- message: '',
90
- visible: false
98
+ let hideTimer = null;
99
+ // 缓存字段路径,避免频繁的数组操作
100
+ let cachedFieldPath = null;
101
+ let cachedName = undefined;
102
+ // 计算字段路径
103
+ const fieldPath = computed(() => {
104
+ if (!props.name)
105
+ return [];
106
+ // 如果 name 没变,返回缓存
107
+ if (cachedName === props.name && cachedFieldPath) {
108
+ return cachedFieldPath;
109
+ }
110
+ cachedName = props.name;
111
+ cachedFieldPath = isArray(props.name) ? props.name : [props.name];
112
+ return cachedFieldPath;
91
113
  });
92
- const filedId = computed(() => {
93
- const names = isArray(props.name) ? props.name : [props.name];
94
- const [index, ...extra] = names;
114
+ // 事件key,用于标识字段 - 使用简单字符串拼接
115
+ const eventKey = computed(() => fieldPath.value.join('-'));
116
+ // 字段ID
117
+ const fieldId = computed(() => {
118
+ const path = fieldPath.value;
119
+ if (path.length === 0)
120
+ return '';
121
+ const [index, ...extra] = path;
95
122
  return `${index}-${extra.join('.')}`;
96
123
  });
97
- const filedName = computed(() => {
98
- const names = isArray(props.name) ? props.name : [props.name];
99
- return [...names].pop();
124
+ // 字段名(最后一个路径部分)
125
+ const fieldName = computed(() => {
126
+ const path = fieldPath.value;
127
+ return path.length > 0 ? path[path.length - 1] : undefined;
100
128
  });
101
- const filedValue = computed(() => {
102
- return get(context.dataSource.value, props.name);
129
+ // 行索引
130
+ const rowIndex = computed(() => {
131
+ const path = fieldPath.value;
132
+ return path.length > 0 ? Number(path[0]) : 0;
103
133
  });
134
+ // 字段值 - 优化:避免不必要的 get 调用
135
+ const fieldValue = computed(() => {
136
+ if (!_optionalChain([context, 'access', _2 => _2.dataSource, 'optionalAccess', _3 => _3.value]) || !props.name)
137
+ return undefined;
138
+ const dataSource = context.dataSource.value;
139
+ const path = fieldPath.value;
140
+ // 快速路径:单层访问
141
+ if (path.length === 1) {
142
+ return dataSource[path[0]];
143
+ }
144
+ // 快速路径:双层访问(最常见的情况:dataSource[index][field])
145
+ if (path.length === 2) {
146
+ const item = dataSource[path[0]];
147
+ return item ? item[path[1]] : undefined;
148
+ }
149
+ // 深层路径:使用 lodash.get
150
+ return get(dataSource, props.name);
151
+ });
152
+ // 错误状态
153
+ const errorMap = reactive({
154
+ message: '',
155
+ visible: false
156
+ });
157
+ // 向下提供错误状态
104
158
  provide(TABLE_FORM_ITEM_ERROR, errorMap);
105
159
  const popContainer = (e) => {
106
160
  return e;
@@ -123,87 +177,172 @@ const __sfc_main__ = Object.assign({
123
177
  errorMap.message = '';
124
178
  }, 300);
125
179
  };
126
- const validateRules = () => {
127
- let index = 0;
128
- if (isArray(props.name)) {
129
- index = props.name[0];
180
+ // 获取当前字段的校验规则
181
+ const getFieldRules = () => {
182
+ // 优先使用 props.rules
183
+ if (props.rules && props.rules.length > 0) {
184
+ return props.rules;
130
185
  }
131
- const promise = context.validateItem({ [filedName.value]: get(context.dataSource.value, props.name) }, index);
132
- promise.then(() => {
133
- hideErrorTip();
134
- context.removeFieldError(eventKey.value);
135
- }).catch(res => {
136
- const error = _optionalChain([res, 'optionalAccess', _2 => _2.filter, 'call', _3 => _3(item => item.field === filedName.value)]) || [];
137
- if (error.length === 0) {
138
- hideErrorTip();
139
- context.removeFieldError(eventKey.value);
186
+ // context 中获取规则
187
+ if (_optionalChain([context, 'access', _4 => _4.rules, 'optionalAccess', _5 => _5.value]) && fieldName.value) {
188
+ const rules = context.rules.value[fieldName.value];
189
+ if (Array.isArray(rules)) {
190
+ return rules;
140
191
  }
141
- else {
142
- removeTimer();
143
- errorMap.message = _optionalChain([error, 'access', _4 => _4[0], 'optionalAccess', _5 => _5.message]) || errorMap.message;
144
- errorMap.visible = !!error.length;
145
- context.addFieldError(eventKey.value, errorMap.message);
192
+ }
193
+ // 如果 required 但没有规则,创建默认必填规则
194
+ if (props.required) {
195
+ return [{ required: true, message: `${fieldName.value} 不能为空` }];
196
+ }
197
+ return [];
198
+ };
199
+ // 使用 async-validator 执行校验
200
+ const validateField = () => {
201
+ return new Promise((resolve, reject) => {
202
+ const rules = getFieldRules();
203
+ if (!rules || rules.length === 0) {
204
+ hideErrorTip();
205
+ _optionalChain([context, 'access', _6 => _6.removeFieldError, 'optionalCall', _7 => _7(eventKey.value)]);
206
+ resolve();
207
+ return;
146
208
  }
147
- return errorMap.message;
209
+ const descriptor = {
210
+ [fieldName.value]: rules
211
+ };
212
+ const validator = new Schema(descriptor);
213
+ const data = {
214
+ [fieldName.value]: toRaw(fieldValue.value)
215
+ };
216
+ validator.validate(data, { firstFields: true }, (errors) => {
217
+ if (errors && errors.length > 0) {
218
+ const errorMsg = errors[0].message || '校验失败';
219
+ showErrorTip(errorMsg);
220
+ _optionalChain([context, 'access', _8 => _8.addFieldError, 'optionalCall', _9 => _9(eventKey.value, errorMsg)]);
221
+ reject(errors);
222
+ }
223
+ else {
224
+ hideErrorTip();
225
+ _optionalChain([context, 'access', _10 => _10.removeFieldError, 'optionalCall', _11 => _11(eventKey.value)]);
226
+ resolve();
227
+ }
228
+ });
148
229
  });
149
- return promise;
230
+ };
231
+ // 兼容旧API的校验方法
232
+ const validateRules = () => {
233
+ // 如果 context 提供了 validateItem,使用它来保持兼容性
234
+ if (context.validateItem) {
235
+ const promise = context.validateItem({ [fieldName.value]: fieldValue.value }, rowIndex.value);
236
+ promise.then(() => {
237
+ hideErrorTip();
238
+ _optionalChain([context, 'access', _12 => _12.removeFieldError, 'optionalCall', _13 => _13(eventKey.value)]);
239
+ }).catch((res) => {
240
+ const error = _optionalChain([res, 'optionalAccess', _14 => _14.filter, 'call', _15 => _15((item) => item.field === fieldName.value)]) || [];
241
+ if (error.length === 0) {
242
+ hideErrorTip();
243
+ _optionalChain([context, 'access', _16 => _16.removeFieldError, 'optionalCall', _17 => _17(eventKey.value)]);
244
+ }
245
+ else {
246
+ removeTimer();
247
+ errorMap.message = _optionalChain([error, 'access', _18 => _18[0], 'optionalAccess', _19 => _19.message]) || errorMap.message;
248
+ errorMap.visible = !!error.length;
249
+ _optionalChain([context, 'access', _20 => _20.addFieldError, 'optionalCall', _21 => _21(eventKey.value, errorMap.message)]);
250
+ }
251
+ });
252
+ return promise;
253
+ }
254
+ // 使用本地校验
255
+ return validateField();
150
256
  };
151
257
  const onFieldBlur = () => {
152
- // validateRules()
258
+ // 改为失焦时校验,减少实时校验的性能开销
259
+ validateRules();
153
260
  };
154
261
  const onFieldChange = () => {
155
- validateRules();
262
+ // 只触发 change 事件,不进行校验
263
+ // validateRules() // 移到 onBlur
156
264
  emit('change');
157
265
  };
158
- watch(() => globalErrorMessage.value, (val) => {
159
- if (val[eventKey.value]) {
160
- showErrorTip(val[eventKey.value]);
266
+ // 监听全局错误变化 - 精确监听单个字段,避免深度遍历
267
+ watch(() => _optionalChain([globalErrorMessage, 'optionalAccess', _22 => _22.value, 'optionalAccess', _23 => _23[eventKey.value]]), (errorMsg) => {
268
+ if (errorMsg) {
269
+ showErrorTip(errorMsg);
161
270
  }
162
271
  else {
163
272
  hideErrorTip();
164
273
  }
165
- }, { immediate: true, deep: true });
274
+ }, { immediate: true });
275
+ // 注册到 ant-design-vue form context
166
276
  useProvideFormItemContext({
167
- id: filedId,
277
+ id: fieldId,
168
278
  onFieldChange,
169
279
  onFieldBlur,
170
280
  }, computed(() => {
171
- console.log(context.dataSource.value, props.name);
172
- return get(context.dataSource.value, props.name);
281
+ return get(_optionalChain([context, 'access', _24 => _24.dataSource, 'optionalAccess', _25 => _25.value]), props.name);
173
282
  }));
283
+ // 注册字段到父组件 - 使用字段池复用,减少创建/销毁开销
284
+ let isRegistered = false;
285
+ const registerField = () => {
286
+ if (props.name && !isRegistered) {
287
+ // 使用字段池获取或创建字段信息
288
+ const fieldInfo = fieldPool.acquire(eventKey.value, {
289
+ fieldName: fieldName.value,
290
+ eventKey: eventKey.value,
291
+ names: props.name,
292
+ validateRules,
293
+ showErrorTip
294
+ });
295
+ _optionalChain([context, 'access', _26 => _26.addField, 'optionalCall', _27 => _27(eventKey.value, fieldInfo)]);
296
+ isRegistered = true;
297
+ }
298
+ };
299
+ // 延迟注册,避免虚拟滚动时的同步阻塞
300
+ onMounted(() => {
301
+ nextTick(() => {
302
+ registerField();
303
+ });
304
+ });
174
305
  onBeforeUnmount(() => {
175
306
  hideErrorTip();
307
+ if (isRegistered) {
308
+ _optionalChain([context, 'access', _28 => _28.removeField, 'optionalCall', _29 => _29(eventKey.value)]);
309
+ // 释放字段到池中,而不是销毁
310
+ fieldPool.release(eventKey.value);
311
+ isRegistered = false;
312
+ }
313
+ });
314
+ // 暴露方法
315
+ __expose({
316
+ validate: validateField,
317
+ validateRules,
318
+ showErrorTip,
319
+ hideErrorTip
176
320
  });
177
- watch(() => [filedName.value, props.name], () => {
178
- context.addField(eventKey.value, {
179
- filedName: filedName.value,
180
- eventKey: eventKey.value,
181
- names: props.name,
182
- validateRules,
183
- showErrorTip
184
- });
185
- }, { immediate: true });
186
321
  return (_ctx, _cache) => {
187
322
  const _component_a_tooltip = _resolveComponent("a-tooltip");
188
323
  return (_openBlock(), _createElementBlock(_Fragment, null, [
189
- _createVNode(_component_a_tooltip, {
190
- color: "#ffffff",
191
- "get-popup-container": popContainer,
192
- arrowPointAtCenter: true
193
- }, {
194
- title: _withCtx(() => [
195
- _createElementVNode("span", _hoisted_1, _toDisplayString(errorMap.message), 1 /* TEXT */)
196
- ]),
197
- default: _withCtx(() => [
198
- (errorMap.visible)
199
- ? (_openBlock(), _createElementBlock("div", {
200
- key: 0,
201
- class: _normalizeClass(['jetlinks-table-form-error-target', _unref(hashId), 'hashId'])
202
- }, null, 2 /* CLASS */))
203
- : _createCommentVNode("v-if", true)
204
- ]),
205
- _: 1 /* STABLE */
206
- }),
324
+ (errorMap.visible)
325
+ ? (_openBlock(), _createBlock(_component_a_tooltip, {
326
+ key: 0,
327
+ color: "#ffffff",
328
+ "get-popup-container": popContainer,
329
+ arrowPointAtCenter: true,
330
+ open: ""
331
+ }, {
332
+ title: _withCtx(() => [
333
+ _createElementVNode("span", _hoisted_1, _toDisplayString(errorMap.message), 1 /* TEXT */)
334
+ ]),
335
+ default: _withCtx(() => [
336
+ (errorMap.visible)
337
+ ? (_openBlock(), _createElementBlock("div", {
338
+ key: 0,
339
+ class: _normalizeClass(['jetlinks-table-form-error-target', _unref(hashId), 'hashId'])
340
+ }, null, 2 /* CLASS */))
341
+ : _createCommentVNode("v-if", true)
342
+ ]),
343
+ _: 1 /* STABLE */
344
+ }))
345
+ : _createCommentVNode("v-if", true),
207
346
  _createElementVNode("div", {
208
347
  id: eventKey.value,
209
348
  style: { "position": "relative" },
@@ -1,13 +1,13 @@
1
- export var METADATA_GROUP_OPTIONS = Symbol('metadata-group-options');
2
- export var TABLE_WRAPPER = Symbol('table-wrapper');
3
- export var FULL_SCREEN = Symbol('full');
4
- export var RIGHT_MENU = Symbol('right-menu');
5
- export var TABLE_ERROR = Symbol('table-error');
6
- export var TABLE_GROUP_ERROR = Symbol('table-group-error');
7
- export var TABLE_GROUP_OPTIONS = Symbol('table-group-options');
8
- export var TABLE_DATA_SOURCE = Symbol('table-data-source');
9
- export var TABLE_OPEN_GROUP = Symbol('table-open-group');
10
- export var TABLE_TOOL = Symbol('table-tool');
11
- export var TABLE_FORM_ITEM_ERROR = Symbol('table-form-item-error');
12
- export var TABLE_GROUP_ACTIVE = Symbol('table-group-active');
13
- export var TABLE_H_SCROLL = Symbol('table-h-scroll');
1
+ export var METADATA_GROUP_OPTIONS = 'metadata-group-options';
2
+ export var TABLE_WRAPPER = 'table-wrapper';
3
+ export var FULL_SCREEN = 'full';
4
+ export var RIGHT_MENU = 'right-menu';
5
+ export var TABLE_ERROR = 'table-error';
6
+ export var TABLE_GROUP_ERROR = 'table-group-error';
7
+ export var TABLE_GROUP_OPTIONS = 'table-group-options';
8
+ export var TABLE_DATA_SOURCE = 'table-data-source';
9
+ export var TABLE_OPEN_GROUP = 'table-open-group';
10
+ export var TABLE_TOOL = 'table-tool';
11
+ export var TABLE_FORM_ITEM_ERROR = 'table-form-item-error';
12
+ export var TABLE_GROUP_ACTIVE = 'table-group-active';
13
+ export var TABLE_H_SCROLL = 'table-h-scroll';
@@ -6,7 +6,8 @@ export var useFormContext = function useFormContext(options) {
6
6
  };
7
7
  export var useInjectForm = function useInjectForm() {
8
8
  return inject(FormContextKey, {
9
- addField: function addField(key, field) {},
9
+ addField: function addField() {},
10
+ removeField: function removeField() {},
10
11
  dataSource: computed(function () {
11
12
  return [];
12
13
  }),
@@ -34,7 +35,7 @@ export var useTableOpenGroup = function useTableOpenGroup() {
34
35
  return inject(TABLE_OPEN_GROUP, false);
35
36
  };
36
37
  export var useTableTool = function useTableTool() {
37
- return inject(TABLE_TOOL, false);
38
+ return inject(TABLE_TOOL, {});
38
39
  };
39
40
  export var useGroupOptions = function useGroupOptions() {
40
41
  return inject(TABLE_GROUP_OPTIONS, []);
@@ -0,0 +1,166 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
2
+ import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
3
+ import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
4
+ import _createClass from "@babel/runtime/helpers/esm/createClass";
5
+ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
6
+ /**
7
+ * 字段注册池 - 复用字段注册对象,避免频繁创建/销毁
8
+ */
9
+ var FieldPool = /*#__PURE__*/function () {
10
+ function FieldPool() {
11
+ _classCallCheck(this, FieldPool);
12
+ _defineProperty(this, "pool", new Map());
13
+ _defineProperty(this, "maxSize", 200);
14
+ // 池的最大大小
15
+ _defineProperty(this, "cleanupThreshold", 150);
16
+ // 清理阈值
17
+ _defineProperty(this, "cleanupInterval", null);
18
+ // 每 5 秒清理一次不活跃的字段
19
+ this.startCleanup();
20
+ }
21
+ /**
22
+ * 获取或创建字段
23
+ */
24
+ return _createClass(FieldPool, [{
25
+ key: "acquire",
26
+ value: function acquire(eventKey, fieldInfo) {
27
+ var pooled = this.pool.get(eventKey);
28
+ if (pooled) {
29
+ // 复用现有字段
30
+ pooled.isActive = true;
31
+ pooled.lastUsed = Date.now();
32
+ // 更新字段信息(可能数据变了)
33
+ pooled.field = fieldInfo;
34
+ return pooled.field;
35
+ }
36
+ // 创建新字段
37
+ var newPooled = {
38
+ field: fieldInfo,
39
+ isActive: true,
40
+ lastUsed: Date.now()
41
+ };
42
+ this.pool.set(eventKey, newPooled);
43
+ // 如果池太大,触发清理
44
+ if (this.pool.size > this.maxSize) {
45
+ this.cleanup();
46
+ }
47
+ return fieldInfo;
48
+ }
49
+ /**
50
+ * 释放字段(标记为不活跃,但不删除)
51
+ */
52
+ }, {
53
+ key: "release",
54
+ value: function release(eventKey) {
55
+ var pooled = this.pool.get(eventKey);
56
+ if (pooled) {
57
+ pooled.isActive = false;
58
+ pooled.lastUsed = Date.now();
59
+ }
60
+ }
61
+ /**
62
+ * 清理不活跃的字段
63
+ */
64
+ }, {
65
+ key: "cleanup",
66
+ value: function cleanup() {
67
+ var _this = this;
68
+ var now = Date.now();
69
+ var maxAge = 30000; // 30秒未使用的字段会被清理
70
+ // 如果池大小超过阈值,开始清理
71
+ if (this.pool.size < this.cleanupThreshold) {
72
+ return;
73
+ }
74
+ var toDelete = [];
75
+ var _iterator = _createForOfIteratorHelper(this.pool.entries()),
76
+ _step;
77
+ try {
78
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
79
+ var _step$value = _slicedToArray(_step.value, 2),
80
+ key = _step$value[0],
81
+ pooled = _step$value[1];
82
+ // 清理不活跃且长时间未使用的字段
83
+ if (!pooled.isActive && now - pooled.lastUsed > maxAge) {
84
+ toDelete.push(key);
85
+ }
86
+ }
87
+ } catch (err) {
88
+ _iterator.e(err);
89
+ } finally {
90
+ _iterator.f();
91
+ }
92
+ toDelete.forEach(function (key) {
93
+ return _this.pool.delete(key);
94
+ });
95
+ if (toDelete.length > 0) {
96
+ console.debug("[FieldPool] Cleaned up ".concat(toDelete.length, " inactive fields"));
97
+ }
98
+ }
99
+ /**
100
+ * 启动定时清理
101
+ */
102
+ }, {
103
+ key: "startCleanup",
104
+ value: function startCleanup() {
105
+ var _this2 = this;
106
+ if (this.cleanupInterval) return;
107
+ this.cleanupInterval = setInterval(function () {
108
+ _this2.cleanup();
109
+ }, 5000);
110
+ }
111
+ /**
112
+ * 停止定时清理
113
+ */
114
+ }, {
115
+ key: "stopCleanup",
116
+ value: function stopCleanup() {
117
+ if (this.cleanupInterval) {
118
+ clearInterval(this.cleanupInterval);
119
+ this.cleanupInterval = null;
120
+ }
121
+ }
122
+ /**
123
+ * 清空池
124
+ */
125
+ }, {
126
+ key: "clear",
127
+ value: function clear() {
128
+ this.pool.clear();
129
+ }
130
+ /**
131
+ * 获取池的统计信息
132
+ */
133
+ }, {
134
+ key: "getStats",
135
+ value: function getStats() {
136
+ var activeCount = 0;
137
+ var inactiveCount = 0;
138
+ var _iterator2 = _createForOfIteratorHelper(this.pool.values()),
139
+ _step2;
140
+ try {
141
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
142
+ var pooled = _step2.value;
143
+ if (pooled.isActive) {
144
+ activeCount++;
145
+ } else {
146
+ inactiveCount++;
147
+ }
148
+ }
149
+ } catch (err) {
150
+ _iterator2.e(err);
151
+ } finally {
152
+ _iterator2.f();
153
+ }
154
+ return {
155
+ total: this.pool.size,
156
+ active: activeCount,
157
+ inactive: inactiveCount
158
+ };
159
+ }
160
+ }]);
161
+ }(); // 创建全局单例
162
+ export var fieldPool = new FieldPool();
163
+ // 开发环境下暴露到 window,方便调试
164
+ if (import.meta.env.DEV) {
165
+ window.__fieldPool__ = fieldPool;
166
+ }
@@ -3,13 +3,15 @@ import { RIGHT_MENU, TABLE_DATA_SOURCE, TABLE_ERROR, TABLE_WRAPPER, TABLE_TOOL,
3
3
  export * from './useResizeObserver';
4
4
  export * from './useValidate';
5
5
  export * from './useGroup';
6
+ export * from './useVirtualTreeTable';
6
7
  var FormContextKey = 'form-context';
7
8
  export var useFormContext = function useFormContext(options) {
8
9
  provide(FormContextKey, options);
9
10
  };
10
11
  export var useInjectForm = function useInjectForm() {
11
12
  return inject(FormContextKey, {
12
- addField: function addField(key, field) {},
13
+ addField: function addField() {},
14
+ removeField: function removeField() {},
13
15
  dataSource: computed(function () {
14
16
  return [];
15
17
  }),
@@ -31,7 +33,7 @@ export var useTableDataSource = function useTableDataSource() {
31
33
  return inject(TABLE_DATA_SOURCE, []);
32
34
  };
33
35
  export var useTableTool = function useTableTool() {
34
- return inject(TABLE_TOOL, false);
36
+ return inject(TABLE_TOOL, {});
35
37
  };
36
38
  export var useFormItemError = function useFormItemError() {
37
39
  return inject(TABLE_FORM_ITEM_ERROR);