@ftjs/antd 0.0.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/dist/index.js ADDED
@@ -0,0 +1,1211 @@
1
+ import { computed, toValue, createVNode, mergeProps, unref, isVNode, ref, useId, Fragment, createTextVNode, watchEffect, onMounted, onUnmounted, nextTick, reactive, watch, h } from "vue";
2
+ import { SwapOutlined, SettingOutlined } from "@ant-design/icons-vue";
3
+ import { getField, defineFormComponent, useFormItem, unrefs, defineTfForm, useFormInject, set, defineTfTable, useTableInject, get, cloneDeep } from "@ftjs/core";
4
+ import { FormItem, Input, Select, DatePicker, RangePicker, Radio, Textarea, Upload, Cascader, AutoComplete, CheckboxGroup, InputNumber, Mentions, Rate, Slider, Switch, TreeSelect, Modal, Tree, Button, Form, Table, Spin, Pagination } from "ant-design-vue";
5
+ import dayjs from "dayjs";
6
+ import { VxeGrid } from "vxe-table";
7
+ const useFormItemProps = (column) => {
8
+ return computed(() => {
9
+ const field = getField(column);
10
+ const name = field.split(".");
11
+ const label = toValue(column.title) ?? "";
12
+ return {
13
+ name,
14
+ label
15
+ };
16
+ });
17
+ };
18
+ const input = defineFormComponent((props) => {
19
+ const {
20
+ valueComputed,
21
+ isView
22
+ } = useFormItem({
23
+ props
24
+ });
25
+ const formItemProps = useFormItemProps(props.column);
26
+ return () => {
27
+ const _props = unrefs(props.column.props);
28
+ const placeholder = `请输入${formItemProps.value.label}`;
29
+ return createVNode(FormItem, formItemProps.value, {
30
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(Input, mergeProps({
31
+ "value": valueComputed.value,
32
+ "onUpdate:value": ($event) => valueComputed.value = $event,
33
+ "allowClear": true,
34
+ "placeholder": placeholder
35
+ }, _props), null)]
36
+ });
37
+ };
38
+ });
39
+ const select = defineFormComponent((props) => {
40
+ const {
41
+ valueComputed,
42
+ isView
43
+ } = useFormItem({
44
+ props
45
+ });
46
+ const formItemProps = useFormItemProps(props.column);
47
+ const placeholder = computed(() => {
48
+ return `请选择${formItemProps.value.label}`;
49
+ });
50
+ const isViewText = computed(() => {
51
+ var _a, _b;
52
+ const options = unref((_a = props.column.props) == null ? void 0 : _a.options);
53
+ const isMultiple = ((_b = props.column.props) == null ? void 0 : _b.mode) === "multiple";
54
+ const arr = isMultiple ? valueComputed.value : [valueComputed.value];
55
+ if (options) {
56
+ return arr.map((e) => {
57
+ const option = options.find((o) => o.value === e);
58
+ return option == null ? void 0 : option.label;
59
+ }).filter(Boolean).join(", ");
60
+ }
61
+ return valueComputed.value;
62
+ });
63
+ return () => {
64
+ const _props = unrefs(props.column.props);
65
+ return createVNode(FormItem, formItemProps.value, {
66
+ default: () => [toValue(isView.value) ? createVNode("div", null, [isViewText.value]) : createVNode(Select, mergeProps({
67
+ "value": valueComputed.value,
68
+ "onUpdate:value": ($event) => valueComputed.value = $event,
69
+ "placeholder": placeholder.value
70
+ }, _props), null)]
71
+ });
72
+ };
73
+ });
74
+ const datePicker = defineFormComponent((props) => {
75
+ const {
76
+ valueComputed,
77
+ isView
78
+ } = useFormItem({
79
+ props
80
+ });
81
+ const formItemProps = useFormItemProps(props.column);
82
+ return () => {
83
+ const _props = {
84
+ valueFormat: "YYYY-MM-DD",
85
+ ...unrefs(props.column.props)
86
+ };
87
+ return createVNode(FormItem, formItemProps.value, {
88
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : (
89
+ // @ts-expect-error 类型推断错误
90
+ createVNode(DatePicker, mergeProps({
91
+ "value": valueComputed.value,
92
+ "onUpdate:value": ($event) => valueComputed.value = $event
93
+ }, _props), null)
94
+ )]
95
+ });
96
+ };
97
+ });
98
+ const rangePicker = defineFormComponent((props) => {
99
+ const {
100
+ valueComputed,
101
+ isView
102
+ } = useFormItem({
103
+ props
104
+ });
105
+ const formItemProps = useFormItemProps(props.column);
106
+ return () => {
107
+ const unrefsProps = unrefs(props.column.props);
108
+ const _props = {
109
+ valueFormat: (unrefsProps == null ? void 0 : unrefsProps.showTime) ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD",
110
+ ...unrefsProps,
111
+ showTime: (unrefsProps == null ? void 0 : unrefsProps.showTime) ? {
112
+ defaultValue: [dayjs().startOf("day"), dayjs().endOf("day")],
113
+ ...typeof (unrefsProps == null ? void 0 : unrefsProps.showTime) === "object" ? unrefsProps.showTime : {}
114
+ } : false
115
+ };
116
+ return createVNode(FormItem, formItemProps.value, {
117
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(RangePicker, mergeProps({
118
+ "value": valueComputed.value,
119
+ "onUpdate:value": ($event) => valueComputed.value = $event
120
+ }, _props), null)]
121
+ });
122
+ };
123
+ });
124
+ const radio = defineFormComponent((props) => {
125
+ const {
126
+ valueComputed,
127
+ isView
128
+ } = useFormItem({
129
+ props
130
+ });
131
+ const formItemProps = useFormItemProps(props.column);
132
+ const isViewText = computed(() => {
133
+ var _a;
134
+ const options = unref(props.column.props.options);
135
+ if (!options) return valueComputed.value;
136
+ return ((_a = options.find((option) => option.value === valueComputed.value)) == null ? void 0 : _a.label) || "";
137
+ });
138
+ return () => {
139
+ const _props = unrefs(props.column.props);
140
+ return createVNode(FormItem, formItemProps.value, {
141
+ default: () => [toValue(isView.value) ? createVNode("div", null, [isViewText.value]) : createVNode(Radio.Group, mergeProps({
142
+ "value": valueComputed.value,
143
+ "onUpdate:value": ($event) => valueComputed.value = $event
144
+ }, _props), null)]
145
+ });
146
+ };
147
+ });
148
+ const textarea = defineFormComponent((props) => {
149
+ const {
150
+ valueComputed,
151
+ isView
152
+ } = useFormItem({
153
+ props
154
+ });
155
+ const formItemProps = useFormItemProps(props.column);
156
+ return () => {
157
+ const _props = unrefs(props.column.props);
158
+ const placeholder = `请输入${formItemProps.value.label}`;
159
+ return createVNode(FormItem, formItemProps.value, {
160
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(Textarea, mergeProps({
161
+ "value": valueComputed.value,
162
+ "onUpdate:value": ($event) => valueComputed.value = $event,
163
+ "allowClear": true,
164
+ "showCount": true,
165
+ "placeholder": placeholder
166
+ }, _props), null)]
167
+ });
168
+ };
169
+ });
170
+ function _isSlot(s) {
171
+ return typeof s === "function" || Object.prototype.toString.call(s) === "[object Object]" && !isVNode(s);
172
+ }
173
+ const upload = defineFormComponent((props) => {
174
+ const {
175
+ valueComputed,
176
+ isView
177
+ } = useFormItem({
178
+ props
179
+ });
180
+ const formItemProps = useFormItemProps(props.column);
181
+ return () => {
182
+ let _slot;
183
+ const _props = unrefs(props.column.props);
184
+ return createVNode(FormItem, formItemProps.value, {
185
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(Upload, mergeProps({
186
+ "file-list": valueComputed.value,
187
+ "onUpdate:file-list": ($event) => valueComputed.value = $event
188
+ }, _props), _isSlot(_slot = props.column.slots.default({
189
+ value: valueComputed.value,
190
+ isView: isView.value
191
+ })) ? _slot : {
192
+ default: () => [_slot]
193
+ })]
194
+ });
195
+ };
196
+ });
197
+ const cascader = defineFormComponent((props) => {
198
+ const {
199
+ valueComputed,
200
+ isView
201
+ } = useFormItem({
202
+ props
203
+ });
204
+ const formItemProps = useFormItemProps(props.column);
205
+ return () => {
206
+ const _props = unrefs(props.column.props);
207
+ const placeholder = `请选择${formItemProps.value.label}`;
208
+ return createVNode(FormItem, formItemProps.value, {
209
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(Cascader, mergeProps({
210
+ "value": valueComputed.value,
211
+ "onUpdate:value": ($event) => valueComputed.value = $event,
212
+ "placeholder": placeholder
213
+ }, _props), null)]
214
+ });
215
+ };
216
+ });
217
+ const autoComplete = defineFormComponent((props) => {
218
+ const {
219
+ valueComputed,
220
+ isView
221
+ } = useFormItem({
222
+ props
223
+ });
224
+ const formItemProps = useFormItemProps(props.column);
225
+ return () => {
226
+ const _props = unrefs(props.column.props);
227
+ const placeholder = `请输入${formItemProps.value.label}`;
228
+ return createVNode(FormItem, formItemProps.value, {
229
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(AutoComplete, mergeProps({
230
+ "value": valueComputed.value,
231
+ "onUpdate:value": ($event) => valueComputed.value = $event,
232
+ "placeholder": placeholder,
233
+ "allowClear": true
234
+ }, _props), null)]
235
+ });
236
+ };
237
+ });
238
+ const checkbox = defineFormComponent((props) => {
239
+ const {
240
+ valueComputed,
241
+ isView
242
+ } = useFormItem({
243
+ props
244
+ });
245
+ const formItemProps = useFormItemProps(props.column);
246
+ return () => {
247
+ const _props = unrefs(props.column.props);
248
+ return createVNode(FormItem, formItemProps.value, {
249
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(CheckboxGroup, mergeProps({
250
+ "value": valueComputed.value,
251
+ "onUpdate:value": ($event) => valueComputed.value = $event
252
+ }, _props), null)]
253
+ });
254
+ };
255
+ });
256
+ const inputNumber = defineFormComponent((props) => {
257
+ const {
258
+ valueComputed,
259
+ isView
260
+ } = useFormItem({
261
+ props
262
+ });
263
+ const formItemProps = useFormItemProps(props.column);
264
+ return () => {
265
+ const _props = unrefs(props.column.props);
266
+ return createVNode(FormItem, formItemProps.value, {
267
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(InputNumber, mergeProps({
268
+ "value": valueComputed.value,
269
+ "onUpdate:value": ($event) => valueComputed.value = $event
270
+ }, _props), null)]
271
+ });
272
+ };
273
+ });
274
+ const mentions = defineFormComponent((props) => {
275
+ const {
276
+ valueComputed,
277
+ isView
278
+ } = useFormItem({
279
+ props
280
+ });
281
+ const formItemProps = useFormItemProps(props.column);
282
+ return () => {
283
+ const _props = unrefs(props.column.props);
284
+ return createVNode(FormItem, formItemProps.value, {
285
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(Mentions, mergeProps({
286
+ "value": valueComputed.value,
287
+ "onUpdate:value": ($event) => valueComputed.value = $event
288
+ }, _props), null)]
289
+ });
290
+ };
291
+ });
292
+ const rate = defineFormComponent((props) => {
293
+ const {
294
+ valueComputed,
295
+ isView
296
+ } = useFormItem({
297
+ props
298
+ });
299
+ const formItemProps = useFormItemProps(props.column);
300
+ return () => {
301
+ const _props = unrefs(props.column.props);
302
+ return createVNode(FormItem, formItemProps.value, {
303
+ default: () => [createVNode(Rate, mergeProps({
304
+ "value": valueComputed.value,
305
+ "onUpdate:value": ($event) => valueComputed.value = $event,
306
+ "disabled": isView.value
307
+ }, _props), null)]
308
+ });
309
+ };
310
+ });
311
+ const slider = defineFormComponent((props) => {
312
+ const {
313
+ valueComputed,
314
+ isView
315
+ } = useFormItem({
316
+ props
317
+ });
318
+ const formItemProps = useFormItemProps(props.column);
319
+ return () => {
320
+ const _props = unrefs(props.column.props);
321
+ return createVNode(FormItem, formItemProps.value, {
322
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(Slider, mergeProps({
323
+ "value": valueComputed.value,
324
+ "onUpdate:value": ($event) => valueComputed.value = $event
325
+ }, _props), null)]
326
+ });
327
+ };
328
+ });
329
+ const switchComponent = defineFormComponent((props) => {
330
+ const {
331
+ valueComputed,
332
+ isView
333
+ } = useFormItem({
334
+ props
335
+ });
336
+ const formItemProps = useFormItemProps(props.column);
337
+ return () => {
338
+ const _props = unrefs(props.column.props);
339
+ return createVNode(FormItem, formItemProps.value, {
340
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(Switch, mergeProps({
341
+ "checked": valueComputed.value,
342
+ "onUpdate:checked": ($event) => valueComputed.value = $event
343
+ }, _props), null)]
344
+ });
345
+ };
346
+ });
347
+ const treeSelect = defineFormComponent((props) => {
348
+ const {
349
+ valueComputed,
350
+ isView
351
+ } = useFormItem({
352
+ props
353
+ });
354
+ const formItemProps = useFormItemProps(props.column);
355
+ return () => {
356
+ const _props = unrefs(props.column.props);
357
+ const placeholder = `请输入${formItemProps.value.label}`;
358
+ return createVNode(FormItem, formItemProps.value, {
359
+ default: () => [toValue(isView.value) ? createVNode("div", null, [valueComputed.value]) : createVNode(TreeSelect, mergeProps({
360
+ "value": valueComputed.value,
361
+ "onUpdate:value": ($event) => valueComputed.value = $event,
362
+ "allowClear": true,
363
+ "placeholder": placeholder
364
+ }, _props), null)]
365
+ });
366
+ };
367
+ });
368
+ const formRenderMap = /* @__PURE__ */ new Map([["input", input], ["textarea", textarea], ["select", select], ["radio", radio], ["date-picker", datePicker], ["range-picker", rangePicker], ["upload", upload], ["cascader", cascader], ["auto-complete", autoComplete], ["checkbox", checkbox], ["input-number", inputNumber], ["mentions", mentions], ["rate", rate], ["slider", slider], ["switch", switchComponent], ["tree-select", treeSelect]]);
369
+ function registerForm(type, Component) {
370
+ formRenderMap.set(type, Component);
371
+ }
372
+ const useRules = () => {
373
+ const {
374
+ columns
375
+ } = useFormInject();
376
+ const rules = computed(() => {
377
+ const rulesObj = {};
378
+ for (const column of columns.value) {
379
+ if (column.rules) {
380
+ const field = getField(column);
381
+ set(rulesObj, field, toValue(column.rules));
382
+ }
383
+ }
384
+ return rulesObj;
385
+ });
386
+ return {
387
+ rules
388
+ };
389
+ };
390
+ const useExposed = (formRef) => {
391
+ const {
392
+ "onUpdate:exposed": onUpdateExposed,
393
+ resetToDefault,
394
+ getFormData,
395
+ setAsDefault
396
+ } = useFormInject();
397
+ watchEffect(() => {
398
+ onUpdateExposed == null ? void 0 : onUpdateExposed({
399
+ getFormData,
400
+ resetToDefault,
401
+ setAsDefault,
402
+ formInstance: formRef.value
403
+ });
404
+ });
405
+ };
406
+ const TfForm = /* @__PURE__ */ defineTfForm((_, ctx) => {
407
+ const {
408
+ form,
409
+ width,
410
+ internalFormProps: _formProps,
411
+ hideFooter,
412
+ hideConfirm,
413
+ hideReset,
414
+ onSubmit,
415
+ getFormData,
416
+ resetToDefault
417
+ } = useFormInject();
418
+ const {
419
+ rules
420
+ } = useRules();
421
+ const formRef = ref();
422
+ useExposed(formRef);
423
+ const formProps = computed(() => {
424
+ return {
425
+ layout: "horizontal",
426
+ model: form.value,
427
+ onFinish: async () => {
428
+ await (onSubmit == null ? void 0 : onSubmit(getFormData()));
429
+ },
430
+ labelCol: {
431
+ style: {
432
+ width: "100px"
433
+ }
434
+ },
435
+ rules: rules.value,
436
+ ..._formProps.value
437
+ };
438
+ });
439
+ const id = useId();
440
+ return () => createVNode(Form, mergeProps({
441
+ "ref": formRef,
442
+ "name": id,
443
+ "style": {
444
+ width
445
+ }
446
+ }, ctx.attrs, formProps.value), {
447
+ default: () => [ctx.slots.formContent(), !hideFooter.value && createVNode(FormItem, {
448
+ "label": " ",
449
+ "colon": false
450
+ }, {
451
+ default: () => [!hideConfirm.value && createVNode(Button, {
452
+ "type": "primary",
453
+ "htmlType": "submit"
454
+ }, {
455
+ default: () => [createTextVNode("提交")]
456
+ }), !hideReset.value && createVNode(Button, {
457
+ "style": "margin-left: 10px;",
458
+ "type": "primary",
459
+ "danger": true,
460
+ "onClick": () => resetToDefault()
461
+ }, {
462
+ default: () => [createTextVNode("重置")]
463
+ })]
464
+ })]
465
+ });
466
+ }, formRenderMap, ["exposed", "onUpdate:exposed", ["width", {
467
+ type: String,
468
+ default: "500px"
469
+ }], ["hideFooter", {
470
+ type: Boolean
471
+ }], ["hideConfirm", {
472
+ type: Boolean
473
+ }], ["hideReset", {
474
+ type: Boolean
475
+ }]]);
476
+ const TfFormSearch = /* @__PURE__ */ defineTfForm((_, ctx) => {
477
+ const {
478
+ form,
479
+ columnsChecked,
480
+ columnsSort,
481
+ columns,
482
+ cache,
483
+ internalFormProps: _formProps,
484
+ onSubmit,
485
+ getFormData,
486
+ resetToDefault,
487
+ resetColumnsChecked,
488
+ resetColumnsSort
489
+ } = useFormInject();
490
+ const {
491
+ rules
492
+ } = useRules();
493
+ const formRef = ref();
494
+ useExposed(formRef);
495
+ const formProps = computed(() => {
496
+ return {
497
+ layout: "inline",
498
+ labelCol: {
499
+ style: {
500
+ width: "100px"
501
+ }
502
+ },
503
+ wrapperCol: {
504
+ style: {
505
+ // 这样定义宽度,可以方便后续修改
506
+ width: `var(--tf-form-control-width, 200px)`
507
+ }
508
+ },
509
+ ..._formProps.value,
510
+ model: form.value,
511
+ onFinish: async () => {
512
+ await (onSubmit == null ? void 0 : onSubmit(getFormData()));
513
+ },
514
+ rules: rules.value
515
+ };
516
+ });
517
+ const settingModal = ref(false);
518
+ let oldSortList = [];
519
+ const createColumnsTree = () => {
520
+ var _a;
521
+ const treeData = [{
522
+ title: "全选",
523
+ key: "__all",
524
+ children: []
525
+ }];
526
+ const children = [];
527
+ for (const column of columns.value) {
528
+ const key = column.field || ((_a = column.fields) == null ? void 0 : _a[0]);
529
+ children.push({
530
+ title: column.title,
531
+ key,
532
+ isLeaf: true
533
+ });
534
+ }
535
+ children.sort((a, b) => {
536
+ const aSort = columnsSort.value[a.key];
537
+ const bSort = columnsSort.value[b.key];
538
+ return aSort - bSort;
539
+ });
540
+ oldSortList = [...children];
541
+ treeData[0].children = children;
542
+ return {
543
+ treeData
544
+ };
545
+ };
546
+ const columnsTree = ref([]);
547
+ const columnsCheckedTree = ref([]);
548
+ const setting = () => {
549
+ const {
550
+ treeData
551
+ } = createColumnsTree();
552
+ columnsTree.value = treeData;
553
+ columnsCheckedTree.value = JSON.parse(JSON.stringify(columnsChecked.value));
554
+ settingModal.value = true;
555
+ };
556
+ const onSettingOk = () => {
557
+ settingModal.value = false;
558
+ columnsChecked.value = columnsCheckedTree.value;
559
+ const list = columnsTree.value[0].children;
560
+ const oldColumnsSort = {
561
+ ...columnsSort.value
562
+ };
563
+ const newColumnsSort = {};
564
+ list.forEach((e, idx) => {
565
+ const oldNode = oldSortList[idx];
566
+ const oldField = oldNode.key;
567
+ const oldSort = oldColumnsSort[oldField];
568
+ const curField = e.key;
569
+ newColumnsSort[curField] = oldSort;
570
+ });
571
+ columnsSort.value = newColumnsSort;
572
+ };
573
+ const onCancel = () => {
574
+ resetColumnsChecked();
575
+ resetColumnsSort();
576
+ settingModal.value = false;
577
+ };
578
+ const id = useId();
579
+ return () => createVNode(Fragment, null, [createVNode(Modal, {
580
+ "open": settingModal.value,
581
+ "onUpdate:open": ($event) => settingModal.value = $event,
582
+ "mask": false,
583
+ "width": 260,
584
+ "maskClosable": false,
585
+ "destroyOnClose": true
586
+ }, {
587
+ title: () => createVNode("span", null, [createTextVNode("配置筛选项"), createVNode("span", {
588
+ "style": {
589
+ fontSize: "12px",
590
+ color: "gray"
591
+ }
592
+ }, [createTextVNode("(可拖动排序)")])]),
593
+ footer: () => {
594
+ return createVNode("div", {
595
+ "style": "text-align: center;"
596
+ }, [createVNode(Button, {
597
+ "type": "primary",
598
+ "danger": true,
599
+ "onClick": onCancel
600
+ }, {
601
+ default: () => [createTextVNode("重置")]
602
+ }), createVNode(Button, {
603
+ "type": "primary",
604
+ "onClick": onSettingOk
605
+ }, {
606
+ default: () => [createTextVNode("保存")]
607
+ })]);
608
+ },
609
+ default: () => createVNode(Tree, {
610
+ "treeData": columnsTree.value,
611
+ "checkedKeys": columnsCheckedTree.value,
612
+ "onUpdate:checkedKeys": ($event) => columnsCheckedTree.value = $event,
613
+ "checkable": true,
614
+ "selectable": false,
615
+ "draggable": true,
616
+ "blockNode": true,
617
+ "expandedKeys": ["__all"],
618
+ "virtual": false,
619
+ "allowDrop": ({
620
+ dropNode,
621
+ dropPosition
622
+ }) => {
623
+ if (dropNode.isLeaf && dropPosition === 1) return true;
624
+ if (dropNode.key === "__all" && dropPosition === 0) return true;
625
+ return false;
626
+ },
627
+ "onDrop": (info) => {
628
+ const dragNode = info.dragNode;
629
+ const position = info.dropPosition;
630
+ const list = columnsTree.value[0].children;
631
+ const fromIndex = list.findIndex((e) => e.key === dragNode.key);
632
+ const toIndex = position > fromIndex ? position - 1 : position;
633
+ list.splice(fromIndex, 1);
634
+ list.splice(toIndex, 0, dragNode);
635
+ }
636
+ }, {
637
+ title: (node) => createVNode("div", {
638
+ "style": {
639
+ display: "flex"
640
+ }
641
+ }, [createVNode("span", null, [node.title]), node.key !== "__all" && createVNode(SwapOutlined, {
642
+ "rotate": 90,
643
+ "style": {
644
+ marginLeft: "auto",
645
+ color: "gray"
646
+ }
647
+ }, null)])
648
+ })
649
+ }), createVNode(Form, mergeProps({
650
+ "name": id,
651
+ "style": {
652
+ gap: "10px 0"
653
+ },
654
+ "ref": formRef
655
+ }, ctx.attrs, formProps.value), {
656
+ default: () => [ctx.slots.formContent(), createVNode(FormItem, {
657
+ "style": {
658
+ "--tf-form-control-width": "220px"
659
+ }
660
+ }, {
661
+ default: () => [createVNode("div", {
662
+ "style": "display: flex; gap: 10px;"
663
+ }, [cache.value && createVNode(Button, {
664
+ "icon": createVNode(SettingOutlined, null, null),
665
+ "onClick": setting
666
+ }, {
667
+ default: () => [createTextVNode("配置")]
668
+ }), createVNode(Button, {
669
+ "type": "primary",
670
+ "htmlType": "submit"
671
+ }, {
672
+ default: () => [createTextVNode("查询")]
673
+ }), createVNode(Button, {
674
+ "type": "primary",
675
+ "danger": true,
676
+ "htmlType": "reset",
677
+ "onClick": () => resetToDefault()
678
+ }, {
679
+ default: () => [createTextVNode("重置")]
680
+ })])]
681
+ })]
682
+ })]);
683
+ }, formRenderMap, ["exposed", "onUpdate:exposed"]);
684
+ const editMap = /* @__PURE__ */ new Map([
685
+ ["input", Input],
686
+ ["select", Select]
687
+ ]);
688
+ const TfTable = defineTfTable((_p, ctx) => {
689
+ const {
690
+ formColumns,
691
+ tableColumns,
692
+ internalTableProps,
693
+ internalFormProps,
694
+ tableData,
695
+ loading,
696
+ total,
697
+ keyField,
698
+ defaultPageSize,
699
+ cache,
700
+ initSearch,
701
+ fitFlexHeight,
702
+ minHeight,
703
+ hideSearch,
704
+ hidePagination,
705
+ onSearch,
706
+ onChange,
707
+ onExpand,
708
+ onExpandedRowsChange,
709
+ onResizeColumn,
710
+ "onUpdate:exposed": onUpdateExposed
711
+ } = useTableInject();
712
+ const formExposed = ref();
713
+ const handleSearch = async (pagination) => {
714
+ var _a;
715
+ if (!onSearch) return;
716
+ const formData = (_a = formExposed.value) == null ? void 0 : _a.getFormData();
717
+ if (!pagination && !hidePagination.value) {
718
+ pagination = {
719
+ page: 1,
720
+ pageSize: defaultPageSize.value ?? 20
721
+ };
722
+ }
723
+ onSearch(formData, {
724
+ pagination
725
+ });
726
+ };
727
+ onMounted(() => {
728
+ if (initSearch.value ?? true) {
729
+ handleSearch();
730
+ }
731
+ });
732
+ const columns = computed(() => {
733
+ return tableColumns.value.map((column) => {
734
+ return {
735
+ width: 120,
736
+ align: "center",
737
+ ...column,
738
+ dataIndex: column.field
739
+ };
740
+ });
741
+ });
742
+ const currentPage = ref(1);
743
+ const props = computed(() => {
744
+ return {
745
+ bordered: true,
746
+ pagination: hidePagination.value ? false : {
747
+ total: total.value,
748
+ defaultPageSize: defaultPageSize.value ?? 20,
749
+ current: currentPage.value,
750
+ onChange: (page, pageSize) => {
751
+ currentPage.value = page;
752
+ handleSearch({
753
+ page,
754
+ pageSize
755
+ });
756
+ }
757
+ },
758
+ tableLayout: "fixed",
759
+ rowKey: keyField.value ?? "id",
760
+ ...internalTableProps.value
761
+ };
762
+ });
763
+ const _scrollY = ref(0);
764
+ const scrollY = computed(() => {
765
+ if (!tableData.value || tableData.value.length === 0) return;
766
+ return _scrollY.value;
767
+ });
768
+ const scroll = computed(() => {
769
+ return {
770
+ scrollToFirstRowOnChange: true,
771
+ x: "100%",
772
+ y: scrollY.value
773
+ };
774
+ });
775
+ let containerStyle = {
776
+ display: "flex",
777
+ flexDirection: "column",
778
+ gap: "10px"
779
+ };
780
+ let tableStyle;
781
+ const containerRef = ref();
782
+ const calcTableHeight = () => {
783
+ const container = containerRef.value;
784
+ const table = container == null ? void 0 : container.querySelector(".ant-table-wrapper");
785
+ if (!table) return;
786
+ const header = container.querySelector(".ant-table-thead");
787
+ const footer = container.querySelector(".ant-table-footer");
788
+ if (!table) return;
789
+ let y = table.clientHeight - // pagination不是立即渲染的,其高度为64
790
+ // 多减去2px,避免出现小数
791
+ 64 - 2 - ((header == null ? void 0 : header.clientHeight) ?? 0) - ((footer == null ? void 0 : footer.clientHeight) ?? 0);
792
+ const minHeightValue = minHeight.value ?? 210;
793
+ if (y < minHeightValue) y = minHeightValue;
794
+ _scrollY.value = y;
795
+ };
796
+ if (fitFlexHeight.value ?? true) {
797
+ containerStyle = {
798
+ ...containerStyle,
799
+ flex: "1",
800
+ minHeight: 0
801
+ };
802
+ tableStyle = {
803
+ flex: "1",
804
+ minHeight: 0
805
+ };
806
+ let resizeObserver;
807
+ let prevHeight;
808
+ let timer;
809
+ onMounted(() => {
810
+ resizeObserver = new ResizeObserver((entries) => {
811
+ const height = entries[0].contentRect.height;
812
+ if (prevHeight === height) return;
813
+ prevHeight = height;
814
+ if (timer) {
815
+ clearTimeout(timer);
816
+ }
817
+ timer = setTimeout(() => {
818
+ calcTableHeight();
819
+ }, 100);
820
+ });
821
+ resizeObserver.observe(containerRef.value);
822
+ });
823
+ onUnmounted(() => {
824
+ resizeObserver.disconnect();
825
+ });
826
+ }
827
+ const {
828
+ createBodyCell,
829
+ setEditRow,
830
+ cancelEditRow,
831
+ saveEditRow,
832
+ editRowMap
833
+ } = useEdit(tableData);
834
+ const scrollToIndex = (index) => {
835
+ var _a;
836
+ const row = (_a = containerRef.value) == null ? void 0 : _a.querySelectorAll(".ant-table-row")[index];
837
+ if (!row) return;
838
+ row.scrollIntoView({
839
+ behavior: "smooth",
840
+ block: "nearest",
841
+ inline: "start"
842
+ });
843
+ };
844
+ const scrollToRow = (row) => {
845
+ const index = tableData.value.indexOf(row);
846
+ scrollToIndex(index);
847
+ };
848
+ watchEffect(() => {
849
+ onUpdateExposed == null ? void 0 : onUpdateExposed({
850
+ refresh: async () => {
851
+ var _a;
852
+ await ((_a = formExposed.value) == null ? void 0 : _a.resetToDefault());
853
+ handleSearch();
854
+ },
855
+ formExposed: formExposed.value,
856
+ editRowMap,
857
+ setEditRow: (row) => {
858
+ setEditRow(row);
859
+ nextTick().then(() => {
860
+ scrollToRow(row);
861
+ });
862
+ },
863
+ cancelEditRow,
864
+ saveEditRow,
865
+ scrollToIndex,
866
+ scrollToRow
867
+ });
868
+ });
869
+ return () => {
870
+ var _a, _b, _c, _d;
871
+ return createVNode("div", {
872
+ "ref": containerRef,
873
+ "style": containerStyle
874
+ }, [!hideSearch.value && createVNode(TfFormSearch, mergeProps({
875
+ "exposed": formExposed.value,
876
+ "onUpdate:exposed": ($event) => formExposed.value = $event,
877
+ "cache": cache.value,
878
+ "columns": formColumns.value,
879
+ "onSubmit": () => handleSearch()
880
+ }, internalFormProps.value), null), (ctx.slots.buttons || ctx.slots.tools) && createVNode("div", null, [(_b = (_a = ctx.slots).buttons) == null ? void 0 : _b.call(_a), (_d = (_c = ctx.slots).tools) == null ? void 0 : _d.call(_c)]), createVNode(Table, mergeProps({
881
+ "style": tableStyle,
882
+ "columns": columns.value,
883
+ "loading": loading.value,
884
+ "dataSource": tableData.value,
885
+ "scroll": scroll.value
886
+ }, ctx.attrs, props.value, {
887
+ "onChange": onChange,
888
+ "onExpand": onExpand,
889
+ "onExpandedRowsChange": onExpandedRowsChange,
890
+ "onResizeColumn": onResizeColumn
891
+ }), {
892
+ ...ctx.slots,
893
+ bodyCell: createBodyCell(ctx.slots.bodyCell)
894
+ })]);
895
+ };
896
+ }, ["onChange", "onExpand", "onExpandedRowsChange", "onResizeColumn", "onSearch", ["initSearch", {
897
+ type: Boolean,
898
+ default: true
899
+ }], "fitFlexHeight", "minHeight", ["hidePagination", {
900
+ type: Boolean
901
+ }], "exposed", "onUpdate:exposed", ["hideSearch", {
902
+ type: Boolean
903
+ }]]);
904
+ function useEdit(tableData) {
905
+ const editRowMap = reactive(/* @__PURE__ */ new Map());
906
+ const createBodyCell = (bodyCellDefault) => {
907
+ if (editRowMap.size === 0) return bodyCellDefault;
908
+ return (scopeProps) => {
909
+ const column = scopeProps.column;
910
+ if (column.customRender) {
911
+ return column.customRender({
912
+ ...scopeProps,
913
+ record: scopeProps.record,
914
+ // todo:: 这个是啥?
915
+ renderIndex: -1
916
+ });
917
+ }
918
+ if (column.edit && editRowMap.has(scopeProps.record)) {
919
+ let edit;
920
+ if (typeof column.edit === "string") {
921
+ edit = {
922
+ type: column.edit
923
+ };
924
+ } else {
925
+ edit = column.edit;
926
+ }
927
+ const field = edit.field ?? column.field;
928
+ const component = editMap.get(edit.type);
929
+ if (component) {
930
+ return h(component, {
931
+ ...edit.props,
932
+ class: "tf-table-edit",
933
+ value: get(scopeProps.record, field),
934
+ "onUpdate:value": (value) => {
935
+ set(scopeProps.record, field, value);
936
+ }
937
+ });
938
+ }
939
+ }
940
+ };
941
+ };
942
+ const setEditRow = (row) => {
943
+ const oldRow = cloneDeep(row);
944
+ editRowMap.set(row, oldRow);
945
+ };
946
+ const cancelEditRow = (row) => {
947
+ const oldRow = editRowMap.get(row);
948
+ if (!oldRow) return;
949
+ const index = tableData.value.indexOf(row);
950
+ tableData.value[index] = oldRow;
951
+ delEditRow(row);
952
+ };
953
+ const saveEditRow = (row) => {
954
+ delEditRow(row);
955
+ };
956
+ const delEditRow = (row) => {
957
+ editRowMap.delete(row);
958
+ };
959
+ watch(tableData, (v) => {
960
+ editRowMap.forEach((_val, key) => {
961
+ if (!(v == null ? void 0 : v.includes(key))) {
962
+ editRowMap.delete(key);
963
+ }
964
+ });
965
+ });
966
+ return {
967
+ editRowMap,
968
+ setEditRow,
969
+ createBodyCell,
970
+ cancelEditRow,
971
+ saveEditRow
972
+ };
973
+ }
974
+ const TfVxeTable = defineTfTable((_, ctx) => {
975
+ const {
976
+ formColumns,
977
+ tableColumns,
978
+ internalTableProps,
979
+ internalFormProps,
980
+ tableData,
981
+ loading,
982
+ total,
983
+ keyField,
984
+ defaultPageSize,
985
+ cache,
986
+ initSearch,
987
+ fitFlexHeight,
988
+ minHeight,
989
+ hideSearch,
990
+ hidePagination,
991
+ rowConfig: _rowConfig,
992
+ customConfig: _customConfig,
993
+ toolbarConfig: _toolbarConfig,
994
+ columnConfig: _columnConfig,
995
+ treeConfig,
996
+ onSearch,
997
+ "onUpdate:exposed": onUpdateExposed
998
+ } = useTableInject();
999
+ const formExposed = ref();
1000
+ const tableExposed = ref();
1001
+ const handleSearch = async (pagination) => {
1002
+ var _a;
1003
+ if (!onSearch) return;
1004
+ const formData = (_a = formExposed.value) == null ? void 0 : _a.getFormData();
1005
+ if (!pagination && !hidePagination.value) {
1006
+ pagination = {
1007
+ page: 1,
1008
+ pageSize: defaultPageSize.value ?? 20
1009
+ };
1010
+ }
1011
+ await onSearch(formData, {
1012
+ pagination
1013
+ });
1014
+ };
1015
+ onMounted(() => {
1016
+ if (initSearch.value) {
1017
+ handleSearch();
1018
+ }
1019
+ });
1020
+ const rowConfig = computed(() => {
1021
+ return {
1022
+ keyField: keyField.value,
1023
+ ..._rowConfig.value
1024
+ };
1025
+ });
1026
+ const enableEdit = computed(() => {
1027
+ return tableColumns.value.some((column) => {
1028
+ var _a;
1029
+ return column.edit || ((_a = column.slots) == null ? void 0 : _a.edit);
1030
+ });
1031
+ });
1032
+ const columns = computed(() => {
1033
+ return tableColumns.value.map((column) => {
1034
+ var _a;
1035
+ let editObj = column.edit;
1036
+ if (typeof editObj === "string") {
1037
+ editObj = {
1038
+ type: editObj,
1039
+ props: {}
1040
+ };
1041
+ }
1042
+ const slots = {
1043
+ edit: editObj ? (params) => {
1044
+ const {
1045
+ row
1046
+ } = params;
1047
+ const type = editObj.type;
1048
+ const field = editObj.field ?? column.field;
1049
+ const component = editMap.get(type);
1050
+ if (!component) {
1051
+ console.warn(`[@ftjs/antd] 不支持的编辑类型: ${type}`);
1052
+ return "";
1053
+ }
1054
+ return h(component, {
1055
+ ...editObj.props,
1056
+ value: row[field],
1057
+ "onUpdate:value": (value) => {
1058
+ row[field] = value;
1059
+ }
1060
+ });
1061
+ } : null,
1062
+ ...column.slots
1063
+ };
1064
+ if (slots.edit == null) {
1065
+ delete slots.edit;
1066
+ }
1067
+ return {
1068
+ minWidth: 120,
1069
+ align: "center",
1070
+ editRender: editObj || ((_a = column.slots) == null ? void 0 : _a.edit) ? {} : void 0,
1071
+ ...column,
1072
+ slots
1073
+ };
1074
+ });
1075
+ });
1076
+ const customConfig = computed(() => {
1077
+ return {
1078
+ storage: true,
1079
+ enabled: cache.value != null,
1080
+ ..._customConfig.value
1081
+ };
1082
+ });
1083
+ const toolbarConfig = computed(() => {
1084
+ return {
1085
+ custom: true,
1086
+ zoom: true,
1087
+ ..._toolbarConfig.value
1088
+ };
1089
+ });
1090
+ const editConfig = computed(() => {
1091
+ if (!enableEdit.value) return void 0;
1092
+ return {
1093
+ mode: "row",
1094
+ showStatus: true,
1095
+ trigger: "manual",
1096
+ autoClear: false,
1097
+ autoPos: true
1098
+ };
1099
+ });
1100
+ const columnConfig = computed(() => {
1101
+ return {
1102
+ resizable: true,
1103
+ ..._columnConfig.value
1104
+ };
1105
+ });
1106
+ let containerStyle = {
1107
+ display: "flex",
1108
+ flexDirection: "column",
1109
+ gap: "10px",
1110
+ width: "100%"
1111
+ };
1112
+ let tableStyle;
1113
+ const containerRef = ref();
1114
+ let height;
1115
+ if (fitFlexHeight.value ?? true) {
1116
+ containerStyle = {
1117
+ ...containerStyle,
1118
+ flex: "1",
1119
+ minHeight: 0
1120
+ };
1121
+ tableStyle = {
1122
+ flex: "1",
1123
+ minHeight: 0
1124
+ };
1125
+ height = "100%";
1126
+ }
1127
+ const current = ref(1);
1128
+ async function refresh() {
1129
+ await handleSearch();
1130
+ }
1131
+ watchEffect(() => {
1132
+ onUpdateExposed == null ? void 0 : onUpdateExposed({
1133
+ refresh,
1134
+ formExposed: formExposed.value,
1135
+ tableExposed: tableExposed.value
1136
+ });
1137
+ });
1138
+ return () => createVNode("div", {
1139
+ "ref": containerRef,
1140
+ "style": containerStyle
1141
+ }, [!hideSearch.value && createVNode(TfFormSearch, mergeProps({
1142
+ "exposed": formExposed.value,
1143
+ "onUpdate:exposed": ($event) => formExposed.value = $event,
1144
+ "cache": cache.value,
1145
+ "columns": formColumns.value,
1146
+ "onSubmit": () => handleSearch()
1147
+ }, internalFormProps.value), null), createVNode("div", {
1148
+ "style": tableStyle
1149
+ }, [createVNode(VxeGrid, mergeProps({
1150
+ "ref": (ref2) => tableExposed.value = ref2,
1151
+ "border": true,
1152
+ "showOverflow": true,
1153
+ "height": height,
1154
+ "columns": columns.value,
1155
+ "loading": loading.value,
1156
+ "data": tableData.value,
1157
+ "minHeight": minHeight.value ?? 310,
1158
+ "rowConfig": rowConfig.value,
1159
+ "treeConfig": treeConfig.value,
1160
+ "id": cache.value,
1161
+ "toolbarConfig": toolbarConfig.value,
1162
+ "customConfig": customConfig.value,
1163
+ "columnConfig": columnConfig.value,
1164
+ "keepSource": enableEdit.value,
1165
+ "editConfig": editConfig.value
1166
+ }, internalTableProps.value), {
1167
+ pager() {
1168
+ return hidePagination.value ? null : createVNode("div", {
1169
+ "style": "text-align: right; padding: .5em 0;"
1170
+ }, [createVNode(Pagination, {
1171
+ "current": current.value,
1172
+ "onUpdate:current": ($event) => current.value = $event,
1173
+ "showQuickJumper": true,
1174
+ "showSizeChanger": true,
1175
+ "total": total.value,
1176
+ "defaultPageSize": defaultPageSize.value ?? 20,
1177
+ "showTotal": (total2) => {
1178
+ if (total2 === 0) return null;
1179
+ return `共 ${total2} 条数据`;
1180
+ },
1181
+ "onChange": (page, pageSize) => {
1182
+ handleSearch({
1183
+ page,
1184
+ pageSize
1185
+ });
1186
+ }
1187
+ }, null)]);
1188
+ },
1189
+ ...ctx.slots,
1190
+ loading() {
1191
+ return createVNode("div", {
1192
+ "style": "height: 100%; width: 100%; display: flex; justify-content: center; align-items: center;"
1193
+ }, [createVNode(Spin, null, null)]);
1194
+ }
1195
+ })])]);
1196
+ }, ["onSearch", ["initSearch", {
1197
+ type: Boolean,
1198
+ default: true
1199
+ }], "fitFlexHeight", "minHeight", ["hidePagination", {
1200
+ type: Boolean
1201
+ }], "exposed", "onUpdate:exposed", ["hideSearch", {
1202
+ type: Boolean
1203
+ }], "rowConfig", "treeConfig", "customConfig", "toolbarConfig", "columnConfig"]);
1204
+ export {
1205
+ TfForm,
1206
+ TfFormSearch,
1207
+ TfTable,
1208
+ TfVxeTable,
1209
+ registerForm,
1210
+ useRules
1211
+ };