@hzab/list-render 1.10.21-alpha.0 → 1.10.21-alpha.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.
package/CHANGELOG.md CHANGED
@@ -1,7 +1,3 @@
1
- # @hzab/list-render@1.10.21
2
-
3
- feat: 增加行内编辑表格时,canEditCallback的回调,从外部控制cell是否能编辑,修复原有的hasEdit逻辑
4
-
5
1
  # @hzab/list-render@1.10.20
6
2
 
7
3
  fix: 修复 PaginationRender 的 全部样式
package/README.md CHANGED
@@ -282,6 +282,26 @@ const Slots = {
282
282
  | onEdit | row | 手动触发编辑按钮相关操作 |
283
283
  | onDel | row | 手动触发删除按钮相关操作 |
284
284
 
285
+ #### cellEditTableProps
286
+
287
+ | 属性名称 | 属性类型 | 必须 | 默认值 | 描述 |
288
+ | -------------- | -------- | ---- | ------ | ------------------ |
289
+ | reactGridProps | Object | 否 | | reactGrid 相关参数 |
290
+ | onChange | Function | 否 | | 单元格回调 |
291
+ | formulaConfig | Object | 否 | | 运算相关配置 |
292
+ | headerHeight | number | 否 | | 表头高度 |
293
+
294
+ #### reactGridProps
295
+
296
+ | 属性名称 | 属性类型 | 必须 | 默认值 | 描述 |
297
+ | enableFillHandle | boolean | false | 开启后,选中单元格右下角会出现小方块,可拖拽快速复制 / 序列填充数据(类似 Excel 拖拽填充)|
298
+ | enableRangeSelection | boolean | false | 开启框选单元格区域(批量选中、批量编辑 / 填充必备)|
299
+ | onFocusLocationChanging | (location: CellLocation): boolean | 否 | 焦点 / 进入编辑态前回调,return false 阻止进入编辑)|
300
+ | customCellTemplates | Function | 否 | 注册自定义单元格模板(按钮、下拉、日期等单元格)|
301
+ | onSelectionChanged | Function | 否 | 选择区回调 |
302
+ | headerRowHeight | number | 否 | 表头高度 |
303
+ | rowHeight | number | 否 | 数据行高度 |
304
+
285
305
  - onSearch opt
286
306
  - isSaveQuery 是否保存传入的 query 值
287
307
  - isMergeQuery 是否合并上一次保存的 query 值
@@ -568,6 +588,7 @@ async function test() {
568
588
  ## 命令
569
589
 
570
590
  - Mac 执行该命令,设置 pre-commit 为可执行文件
591
+
571
592
  - npm run mac-chmod
572
593
  - chmod +x .husky && chmod +x .husky/pre-commit
573
594
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzab/list-render",
3
- "version": "1.10.21-alpha.0",
3
+ "version": "1.10.21-alpha.1",
4
4
  "description": "",
5
5
  "main": "src",
6
6
  "scripts": {
@@ -30,8 +30,8 @@
30
30
  "@hzab/formily-result-utils": "^1.2.0",
31
31
  "@hzab/permissions": "^1.0.0",
32
32
  "@hzab/schema-descriptions": "^1.3.0",
33
- "@hzab/webpack-config": "^0.7.2",
34
33
  "@hzab/utils": "^1.0.7",
34
+ "@hzab/webpack-config": "^0.7.2",
35
35
  "@types/react": "^17.0.62",
36
36
  "@types/react-dom": "^17.0.20",
37
37
  "antd": "^4.24.12",
@@ -66,6 +66,7 @@
66
66
  "lib": "lib"
67
67
  },
68
68
  "dependencies": {
69
+ "@silevis/reactgrid": "^4.1.17",
69
70
  "array-move": "^4.0.0",
70
71
  "react-sortable-hoc": "^2.0.0"
71
72
  }
@@ -0,0 +1,11 @@
1
+ .grid-container {
2
+ width: 100vw;
3
+ overflow: auto;
4
+ position: relative;
5
+
6
+ .reactgrid {
7
+ width: 100% !important;
8
+
9
+
10
+ }
11
+ }
@@ -0,0 +1,146 @@
1
+ import React, { useEffect, useState } from "react";
2
+ import { ReactGrid, Column, Row, CellChange, Cell, CellTemplate } from "@silevis/reactgrid";
3
+ import "@silevis/reactgrid/styles.css";
4
+ import _ from "lodash";
5
+ import "./index.less";
6
+
7
+ function isReactElement(value) {
8
+ return value !== null && typeof value === "object";
9
+ }
10
+
11
+ // 自定义单元格:状态标签(可编辑、带颜色)
12
+ export interface StatusCell extends Cell {
13
+ type: "status"; // 唯一标识,必须
14
+ text: string; // 状态文本(如:待办/进行中/完成)
15
+ color?: string; // 自定义颜色
16
+ validator?: (text: string) => boolean; // 可选:校验
17
+ }
18
+
19
+ // 合并所有单元格类型(供 rows 使用)
20
+ export type CustomCellTypes = StatusCell;
21
+
22
+ export default function CellEditTable(props: any) {
23
+ const {
24
+ columns,
25
+ dataSource,
26
+ formulaConfig,
27
+ onChange,
28
+ reactGridProps = {},
29
+ onEditSubmit,
30
+ headerRowHeight,
31
+ rowHeight,
32
+ } = props;
33
+ const [headerList, setHeaderList] = useState([]);
34
+ const [rows, setRows] = useState<any>([]);
35
+ const [tableColumns, setTableColumns] = useState([]);
36
+
37
+ /**将数组转为对象 */
38
+ const handleArrayToObj = (item) => {
39
+ let obj = {
40
+ id: item?.rowId,
41
+ };
42
+ item?.cells?.forEach((el) => {
43
+ if (el?.columnsId) {
44
+ obj[el?.columnsId] = el?.value || el?.selectedValue || el?.text || "";
45
+ }
46
+ });
47
+ return obj;
48
+ };
49
+ /** 表头 */
50
+ useEffect(() => {
51
+ if (Array.isArray(columns) && columns?.length > 0) {
52
+ const cells = columns?.map((item) => {
53
+ return {
54
+ type: "header",
55
+ text:
56
+ typeof item?.title == "function"
57
+ ? isReactElement(item?.title())
58
+ ? item?.title()?.props.children
59
+ : item?.title() || ""
60
+ : item?.title || "",
61
+ };
62
+ });
63
+ setHeaderList([
64
+ {
65
+ rowId: "header",
66
+ height: headerRowHeight,
67
+ cells: cells,
68
+ },
69
+ ]);
70
+ setTableColumns(
71
+ columns?.map((item, index) => ({
72
+ ...item,
73
+ columnId: item?.dataIndex || "",
74
+ })),
75
+ );
76
+ }
77
+ }, [columns]);
78
+ /** 数据行 */
79
+ useEffect(() => {
80
+ const columnsIds = tableColumns?.map((el) => el?.columnId);
81
+ const newDataSource = dataSource?.map((item, index) => {
82
+ return {
83
+ rowId: item?.id,
84
+ height: rowHeight,
85
+ cells: columnsIds?.map((el, ind) => {
86
+ return {
87
+ type: tableColumns[ind]?.cellType ?? "text",
88
+ text: typeof item[el] == "string" ? item[el] : "",
89
+ columnsId: el,
90
+ nonEditable: !tableColumns[ind]?.editable,
91
+ ...item,
92
+ };
93
+ }),
94
+ };
95
+ });
96
+ setRows([...headerList, ...newDataSource]);
97
+ }, [dataSource, tableColumns]);
98
+
99
+ // 单元格编辑回调
100
+ const handleCellsChanged = (changes) => {
101
+ setRows((prevRows) => {
102
+ changes.forEach((change) => {
103
+ const changeRowIdx = prevRows.findIndex((el) => el.rowId === change.rowId);
104
+ const changeColumnIdx = tableColumns.findIndex((el) => el.columnId === change.columnId);
105
+ prevRows[changeRowIdx].cells[changeColumnIdx] = change.newCell;
106
+ if (formulaConfig) {
107
+ for (let key in formulaConfig) {
108
+ const item = formulaConfig[key];
109
+ const resultColumnIdx = tableColumns.findIndex((el) => el.columnId === key);
110
+ const newCell = {
111
+ ...prevRows[changeRowIdx].cells[resultColumnIdx],
112
+ text: item?.setCellData(prevRows[changeRowIdx]),
113
+ value: item?.setCellData(prevRows[changeRowIdx]),
114
+ style: item?.setCellStyle(item?.setCellData(prevRows[changeRowIdx])),
115
+ };
116
+ prevRows[changeRowIdx].cells[resultColumnIdx] = newCell;
117
+ }
118
+ }
119
+ onEditSubmit && onEditSubmit(handleArrayToObj(prevRows[changeRowIdx]));
120
+ onChange && onChange(prevRows[changeRowIdx]);
121
+ });
122
+ return [...prevRows];
123
+ });
124
+ };
125
+
126
+ return (
127
+ <div className="grid-container">
128
+ <ReactGrid
129
+ rows={rows}
130
+ columns={tableColumns}
131
+ onCellsChanged={handleCellsChanged}
132
+ enableFillHandle={true}
133
+ enableRangeSelection={true}
134
+ stickyLeftColumns={1}
135
+ // customCellTemplates={{ status: StatusCellTemplate }}
136
+ // onFocusLocationChanging={(location) => {
137
+ // return false;
138
+ // }}
139
+ {...reactGridProps}
140
+ // onSelectionChanged={(newSelection) => {
141
+ // console.log("选区发生变化", newSelection[0]);
142
+ // }}
143
+ />
144
+ </div>
145
+ );
146
+ }
@@ -30,9 +30,8 @@ export interface EditableCellProps extends React.HTMLAttributes<HTMLElement> {
30
30
  onSave: (field: { type: string; name: string }) => void;
31
31
  onCancel: () => void;
32
32
  topProps: {
33
- tableConf: { hasEdit: boolean | Function };
33
+ config: { hasEdit: boolean | Function };
34
34
  editMode: "modal" | "line" | "line-cell" | "cell";
35
- canEditCallback: (record: Partial<Item> & { key: React.Key }, field: { type: string; name: string }, dataIndex: string) => void;
36
35
  };
37
36
  children: React.ReactNode;
38
37
  }
@@ -57,8 +56,8 @@ export const EditableCell: React.FC<EditableCellProps> = ({
57
56
  const field = getField && getField();
58
57
  const fPattern = field?.["x-pattern"];
59
58
  const fDisplay = field?.["x-display"];
60
- const { editMode = "modal", canEditCallback } = topProps || {};
61
- const { hasEdit } = topProps?.tableConf || {};
59
+ const { editMode = "modal" } = topProps || {};
60
+ const { hasEdit } = topProps?.config || {};
62
61
  const fieldRef = useRef();
63
62
 
64
63
  // 弹窗编辑模式
@@ -67,11 +66,7 @@ export const EditableCell: React.FC<EditableCellProps> = ({
67
66
  }
68
67
  // 无编辑权限或禁止编辑
69
68
  const _hasEdit = hasEdit && typeof hasEdit === "function" ? hasEdit(record, index) : hasEdit !== false;
70
- let _editable =
71
- _hasEdit &&
72
- editable &&
73
- !(fPattern === "disabled" || fPattern === "readOnly" || fDisplay === "none") &&
74
- (canEditCallback ? canEditCallback(record, field, dataIndex) : true);
69
+ let _editable = _hasEdit && editable && !(fPattern === "disabled" || fPattern === "readOnly" || fDisplay === "none");
75
70
  if (!_editable) {
76
71
  return <td {...restProps}>{children}</td>;
77
72
  }
@@ -540,6 +540,7 @@ const ListRender = forwardRef(function (props, parentRef) {
540
540
  i18n={i18n}
541
541
  onEditSubmit={onEditSubmit}
542
542
  topProps={props}
543
+ cellEditTableProps={props?.cellEditTableProps}
543
544
  />
544
545
  ) : null}
545
546
 
@@ -17,13 +17,13 @@ import { getVal, getFieldList } from "../common/utils";
17
17
  import { handleReactions } from "../common/handleReactions";
18
18
 
19
19
  import { useEditTable, EditableCell } from "../components/Formily/FormilyEditTable";
20
-
20
+ import CellEditTable from "../components/CellEditTable"
21
21
  import "./index.less";
22
22
 
23
23
  const scenario = "table-render";
24
24
 
25
25
  const TableRender = forwardRef(function (props, tableRef) {
26
- const { topProps, config = {}, query = {}, i18n, setList } = props;
26
+ const { topProps, config = {}, query = {}, i18n, setList, cellEditTableProps } = props;
27
27
  const { tableDel = "删除", tableEdit = "编辑", tableDelTip = "确认删除该项?", tableDetail = "详情" } = i18n || {};
28
28
  const {
29
29
  dragColConf = {},
@@ -34,6 +34,7 @@ const TableRender = forwardRef(function (props, tableRef) {
34
34
  tableEmptyValue,
35
35
  isShowTableFilter = false,
36
36
  isTableSortXIdex = false,
37
+ isCellEditTable = false
37
38
  } = config || {};
38
39
  const { editMode = "modal" } = topProps || {};
39
40
  const isEditTable = editMode !== "modal";
@@ -129,6 +130,7 @@ const TableRender = forwardRef(function (props, tableRef) {
129
130
  scope: props.schemaScope,
130
131
  formilyRef,
131
132
  });
133
+
132
134
  _fieldList.forEach((field, colIndex) => {
133
135
  const fieldSchemas = formilyRef.current?.fields;
134
136
  if (field.inTable !== false) {
@@ -231,6 +233,7 @@ const TableRender = forwardRef(function (props, tableRef) {
231
233
  title: () => _title,
232
234
  key: name,
233
235
  dataIndex: name,
236
+ cellType: field?.cellType,
234
237
  render: getColRender(colRender),
235
238
  });
236
239
  }
@@ -421,15 +424,23 @@ const TableRender = forwardRef(function (props, tableRef) {
421
424
  </Popover>
422
425
  </div>
423
426
  ) : null}
424
- {isEditTable ? (
425
- <FormProvider form={formRender}>
426
- <Form layout="vertical">
427
- <FormConsumer>{() => <Table {...tableProps} />}</FormConsumer>
428
- </Form>
429
- </FormProvider>
430
- ) : (
431
- <Table {...tableProps} />
432
- )}
427
+ {
428
+ isCellEditTable ? <CellEditTable
429
+ {...tableProps}
430
+ {...cellEditTableProps}
431
+ onEditSubmit={props?.onEditSubmit}
432
+ /> : <>
433
+ {isEditTable ? (
434
+ <FormProvider form={formRender}>
435
+ <Form layout="vertical">
436
+ <FormConsumer>{() => <Table {...tableProps} />}</FormConsumer>
437
+ </Form>
438
+ </FormProvider>
439
+ ) : (
440
+ <Table {...tableProps} />
441
+ )}
442
+ </>
443
+ }
433
444
  <FormilyField
434
445
  schema={props.schema}
435
446
  formilyRef={formilyRef}