@hzab/list-render 1.10.19 → 1.10.20-alpha.0

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.
@@ -1,13 +1,10 @@
1
- import { useEffect, useState, useMemo, useRef, forwardRef, useImperativeHandle } from "react";
1
+ import { useEffect, useState, useRef, forwardRef, useImperativeHandle, Fragment, useMemo } from "react";
2
2
  import { Form, Table, Button, Popconfirm, Tooltip, Checkbox, Popover } from "antd";
3
3
  import { QuestionCircleOutlined, FilterOutlined, SettingOutlined, MenuOutlined } from "@ant-design/icons";
4
4
  import { SortableContainer, SortableElement, SortableHandle } from "react-sortable-hoc";
5
5
  import { arrayMoveImmutable } from "array-move";
6
6
  import _, { isFunction } from "lodash";
7
7
 
8
- import { FormProvider, FormConsumer } from "@formily/react";
9
- import { createForm, onFormValuesChange, onFieldValueChange } from "@formily/core";
10
-
11
8
  import EnumRender from "@hzab/formily-result-utils/src/components/EnumRender";
12
9
  import { SHOW_MODE_TYPES } from "@hzab/formily-result-utils/src/common/constant";
13
10
  import { FormilyField } from "../components/Formily/FormilyField";
@@ -16,42 +13,64 @@ import { getColRender } from "../common/formily-utils";
16
13
  import { getVal, getFieldList } from "../common/utils";
17
14
  import { handleReactions } from "../common/handleReactions";
18
15
 
19
- import { useEditTable, EditableCell } from "../components/Formily/FormilyEditTable";
16
+ import { useEditTable } from "../components/Formily/FormilyEditTable";
17
+ import { EditTableRow } from "../components/Formily/FormilyEditTable/EditTableRow";
18
+ import { EditableCell } from "../components/Formily/FormilyEditTable/EditTableCell";
19
+ import { TableFormilyContext } from "../components/Formily/FormilyEditTable/useTableFormilyContext";
20
20
 
21
21
  import "./index.less";
22
22
 
23
23
  const scenario = "table-render";
24
24
 
25
+ /**
26
+ * 编辑按钮隐藏
27
+ */
28
+ const editModeHideList = ["cell", "line-cell", "table-line-show"];
29
+
25
30
  const TableRender = forwardRef(function (props, tableRef) {
26
- const { topProps, config = {}, query = {}, i18n, setList } = props;
31
+ const { topProps, config = {}, query = {}, i18n, setList, schema } = props;
32
+ const propsSchema = schema?.schema;
27
33
  const { tableDel = "删除", tableEdit = "编辑", tableDelTip = "确认删除该项?", tableDetail = "详情" } = i18n || {};
28
34
  const {
29
35
  dragColConf = {},
30
36
  isDargTable,
31
37
  dargEndBack,
32
- orderColType,
38
+ orderColType = "page",
33
39
  orderColWidth,
34
40
  tableEmptyValue,
35
41
  isShowTableFilter = false,
36
42
  isTableSortXIdex = false,
37
43
  } = config || {};
38
- const { editMode = "modal" } = topProps || {};
39
- const isEditTable = editMode !== "modal";
44
+ const [_list, _setList] = useState(props.list);
45
+ const antdTableRef = useRef();
46
+ const rowFormMapRef = useRef(new Map());
47
+ const editingInofRef = useRef({
48
+ editingRowId: "",
49
+ editingKey: "",
50
+ });
51
+
40
52
  useImperativeHandle(tableRef, () => ({
41
53
  onEditByTable,
42
54
  }));
43
55
 
56
+ useEffect(() => {
57
+ _setList(props.list);
58
+ // 数据清除问题,避免分页数据量持续累计过于庞大
59
+ rowFormMapRef.current.clear();
60
+ }, [props.list]);
61
+
44
62
  const [columns, setColumns] = useState([]);
45
63
  const [columnList, setColumnList] = useState([]);
46
64
  const DragHandle = SortableHandle(() => <MenuOutlined style={{ cursor: "grab", color: "#999" }} />);
47
65
 
48
- const SortableItem = SortableElement((props) => <tr {...props} />);
66
+ const SortableItem = SortableElement((props) => <Fragment children={props.children} />);
49
67
  const SortableBody = SortableContainer((props) => <tbody {...props} />);
50
68
 
51
69
  const onSortEnd = ({ oldIndex, newIndex }) => {
52
70
  if (oldIndex !== newIndex) {
53
71
  const newData = arrayMoveImmutable(props.list.slice(), oldIndex, newIndex).filter((el) => !!el);
54
72
  setList([...newData]);
73
+ _setList([...newData]);
55
74
  dargEndBack && dargEndBack(newData, query);
56
75
  }
57
76
  };
@@ -71,38 +90,27 @@ const TableRender = forwardRef(function (props, tableRef) {
71
90
  fieldSchemas: {},
72
91
  });
73
92
 
74
- const formRender = useMemo(
75
- () =>
76
- createForm({
77
- initialValues: props.initialValues,
78
- // 禁用状态(注意,自定义组件组件自行获取对应的状态)
79
- readOnly: props.readOnly,
80
- disabled: props.disabled,
81
- ...(props.formOptions || {}),
82
- effects(...args) {
83
- props.onFormValuesChange && onFormValuesChange(props.onFormValuesChange);
84
- props.onFieldValueChange && onFieldValueChange("*", props.onFieldValueChange);
85
- props.formOptions?.effects && props.formOptions?.effects(...args);
86
- },
87
- }),
88
- [],
89
- );
90
- const { onEdit: onEditByTable, mergedColumns } = useEditTable({
93
+ const {
94
+ onEditSave,
95
+ onEdit: onEditByTable,
96
+ mergedColumns,
97
+ } = useEditTable({
91
98
  idKey: props.idKey,
92
99
  columns,
93
100
  onEdit: props.onEdit,
94
101
  onEditSubmit: props.onEditSubmit,
95
- formRender,
96
102
  components: props.components,
97
103
  schemaScope: props.schemaScope,
98
104
  topProps: props.topProps,
105
+ rowFormMapRef,
106
+ editingInofRef,
99
107
  });
100
108
 
101
109
  useEffect(() => {
102
- if (!(props.schema && props.schema.properties)) {
110
+ if (!propsSchema.properties) {
103
111
  return;
104
112
  }
105
- const fieldList = getFieldList(props.schema, [], { ...props.getFieldListOpt, formilyRef }, isTableSortXIdex);
113
+ const fieldList = getFieldList(propsSchema, [], { ...props.getFieldListOpt, formilyRef }, isTableSortXIdex);
106
114
  const columns = [];
107
115
 
108
116
  // 序号列
@@ -131,10 +139,28 @@ const TableRender = forwardRef(function (props, tableRef) {
131
139
  });
132
140
  _fieldList.forEach((field, colIndex) => {
133
141
  const fieldSchemas = formilyRef.current?.fields;
142
+ if (!field["x-decorator-props"]) {
143
+ field["x-decorator-props"] = {};
144
+ }
145
+ // 存储原始的 pattern,用于行内编辑还原数据
146
+ field["x-decorator-props"]._sourcePattern = field["x-pattern"];
134
147
  if (field.inTable !== false) {
135
148
  const { name, title } = field;
136
149
  const comName = field["x-component"];
137
150
 
151
+ const decoratorProps = field["x-decorator-props"] || {};
152
+ let _title = title;
153
+ if (decoratorProps.tooltip) {
154
+ _title = (
155
+ <span className="col-title-tooltip-wrap inline-block-max-w">
156
+ {_title}
157
+ <Tooltip className="col-title-tooltip" title={decoratorProps.tooltip}>
158
+ <QuestionCircleOutlined className="col-title-tooltip-icon" />
159
+ </Tooltip>
160
+ </span>
161
+ );
162
+ }
163
+
138
164
  let _colConf = {};
139
165
 
140
166
  if (props.config?.colConf && props.config?.colConf[name]) {
@@ -204,22 +230,6 @@ const TableRender = forwardRef(function (props, tableRef) {
204
230
  };
205
231
  }
206
232
 
207
- let _title = isFunction(title) ? title() : title;
208
- if (_colConf?.title) {
209
- _title = isFunction(_colConf?.title) ? _colConf?.title() : _colConf?.title;
210
- }
211
- const decoratorProps = field["x-decorator-props"] || {};
212
- if (decoratorProps.tooltip) {
213
- _title = (
214
- <span className="col-title-tooltip-wrap inline-block-max-w">
215
- {_title}
216
- <Tooltip className="col-title-tooltip" title={decoratorProps.tooltip}>
217
- <QuestionCircleOutlined className="col-title-tooltip-icon" />
218
- </Tooltip>
219
- </span>
220
- );
221
- }
222
-
223
233
  columns.push({
224
234
  // field, // HACK: 直接传入 field 在 title 传入 ReactNode,内部深克隆导致页面报错白屏。使用函数获取解决
225
235
  getField: () => field,
@@ -227,8 +237,8 @@ const TableRender = forwardRef(function (props, tableRef) {
227
237
  ..._colConf,
228
238
  onCell: (record, rowIndex) =>
229
239
  _colConf?.onCell?.({ ...record, _field: { ...field, ...(fieldSchemas?.[name] || {}) } }, rowIndex) || {},
230
- // 函数式传入,解决 title ReactNode 传入报错问题(table 组件内部对 columns 进行 lodash.deepClone 导致 ReactNode 变成对象无法正常渲染) Uncaught TypeError: this.queryFeedbacks is not a function
231
- title: () => _title,
240
+ // 函数式传入,解决 title ReactNode 传入报错问题
241
+ title: () => (isFunction(_colConf?.title) ? _colConf?.title() : _title),
232
242
  key: name,
233
243
  dataIndex: name,
234
244
  render: getColRender(colRender),
@@ -256,8 +266,7 @@ const TableRender = forwardRef(function (props, tableRef) {
256
266
  const { editMode = "modal" } = props.topProps || {};
257
267
  // 编辑按钮权限
258
268
  const _hasEdit =
259
- editMode !== "cell" &&
260
- editMode !== "line-cell" &&
269
+ !editModeHideList.includes(editMode) &&
261
270
  (hasEdit && typeof hasEdit === "function" ? hasEdit(record, index) : hasEdit !== false);
262
271
 
263
272
  //详情按钮权限
@@ -289,6 +298,10 @@ const TableRender = forwardRef(function (props, tableRef) {
289
298
  type="link"
290
299
  onClick={() => {
291
300
  props.onEdit && props.onEdit(record, index);
301
+ if (editMode == "line") {
302
+ // 整行编辑,编辑按钮在操作列的模式下表单数据回填
303
+ return onEditByTable(record, record[props.idKey]);
304
+ }
292
305
  }}
293
306
  >
294
307
  {tableEdit}
@@ -327,12 +340,7 @@ const TableRender = forwardRef(function (props, tableRef) {
327
340
  }
328
341
  setColumns(columns);
329
342
  setColumnList(columns);
330
- }, [props.schema, props.config]);
331
-
332
- // 解决 FormilyField 中无相关参数报错的问题。自定义参数都从这里传入
333
- const reactionOpts = {
334
- scenario: scenario,
335
- };
343
+ }, [propsSchema, props.config]);
336
344
 
337
345
  const onChange = (e, col) => {
338
346
  if (e.target.checked) {
@@ -346,38 +354,66 @@ const TableRender = forwardRef(function (props, tableRef) {
346
354
  };
347
355
 
348
356
  const tableProps = {
357
+ ref: antdTableRef,
349
358
  className: "table-render",
350
359
  rowKey: props.idKey || "id",
351
360
  rowSelection: config?.rowSelection,
352
361
  columns: columns,
353
- dataSource: props.list,
362
+ dataSource: _list,
354
363
  pagination: false,
355
364
  scroll: config.scroll,
356
365
  expandable: config.expandable,
357
366
  loading: props.loading,
358
- onRow: config?.onRow,
367
+ onRow: (record, index) => {
368
+ const _onRowRes = config?.onRow && config?.onRow(record, index);
369
+ return {
370
+ ..._onRowRes,
371
+ record,
372
+ id: record[props.idKey || "id"],
373
+ rowFormMapRef,
374
+ editingInofRef,
375
+ components: props.components,
376
+ topProps,
377
+ onEditSave,
378
+ };
379
+ },
359
380
  topProps: props.topProps,
360
381
  ...props.tableProps,
361
382
  };
362
383
 
363
- if (isDargTable) {
364
- tableProps.components = {
365
- body: {
366
- wrapper: DraggableContainer,
367
- row: DraggableBodyRow,
368
- },
369
- };
370
- }
384
+ tableProps.columns = mergedColumns;
371
385
 
372
- if (isEditTable) {
373
- tableProps.columns = mergedColumns;
374
- tableProps.components = {
386
+ // useMemo 解决 row 重复渲染问题
387
+ const tableComponents = useMemo(
388
+ () => ({
375
389
  body: {
376
390
  ...tableProps?.components?.body,
377
391
  cell: EditableCell,
392
+ row: isDargTable
393
+ ? ({ rowFormMapRef, components, topProps, ...props }) => {
394
+ // 拖拽
395
+ return (
396
+ <DraggableBodyRow {...props}>
397
+ <EditTableRow rowFormMapRef={rowFormMapRef} components={components} topProps={topProps} {...props} />
398
+ </DraggableBodyRow>
399
+ );
400
+ }
401
+ : EditTableRow,
402
+ ...(isDargTable
403
+ ? {
404
+ wrapper: DraggableContainer,
405
+ }
406
+ : {}),
378
407
  },
379
- };
380
- }
408
+ }),
409
+ [],
410
+ );
411
+ tableProps.components = tableComponents;
412
+
413
+ // 解决 FormilyField 中无相关参数报错的问题。自定义参数都从这里传入
414
+ const reactionOpts = {
415
+ scenario: scenario,
416
+ };
381
417
 
382
418
  return (
383
419
  <div className="table-render-wrap">
@@ -421,26 +457,24 @@ const TableRender = forwardRef(function (props, tableRef) {
421
457
  </Popover>
422
458
  </div>
423
459
  ) : null}
424
- {isEditTable ? (
425
- <FormProvider form={formRender}>
426
- <Form layout="vertical">
427
- <FormConsumer>{() => <Table {...tableProps} />}</FormConsumer>
428
- </Form>
429
- </FormProvider>
430
- ) : (
460
+ <TableFormilyContext.Provider
461
+ value={{
462
+ rowFormMapRef,
463
+ editingInofRef,
464
+ }}
465
+ >
431
466
  <Table {...tableProps} />
432
- )}
433
- <FormilyField
434
- schema={props.schema}
467
+ </TableFormilyContext.Provider>
468
+ {/* <FormilyField
469
+ schema={propsSchema}
435
470
  formilyRef={formilyRef}
436
471
  components={props.components}
437
- topProps={topProps}
438
472
  schemaScope={{
439
473
  ...reactionOpts,
440
474
  ...props.schemaScope,
441
475
  }}
442
476
  reactionOpts={reactionOpts}
443
- />
477
+ /> */}
444
478
  </div>
445
479
  );
446
480
  });