@hzab/edit-table 0.0.1 → 0.0.2-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.
- package/package.json +59 -59
- package/src/Template/ExpandListTemplate/index.tsx +0 -3
- package/src/Template/NumberCellTemplate.tsx +1 -1
- package/src/common/WidthWrapHoc.tsx +4 -0
- package/src/index.less +10 -7
- package/src/index.tsx +45 -13
- package/src/Template/utils.ts +0 -288
- package/src/common/test.ts +0 -3
package/package.json
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@hzab/edit-table",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "src",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"dev": "webpack serve -c ./config/webpack.config.js --env local",
|
|
8
|
-
"build": "webpack -c ./config/webpack.config.js --env production",
|
|
9
|
-
"version:alpha": "npm version prerelease --preid=alpha",
|
|
10
|
-
"publish:alpha": "npm publish --tag alpha",
|
|
11
|
-
"version:beta": "npm version prerelease --preid=beta",
|
|
12
|
-
"publish:beta": "npm publish --tag beta",
|
|
13
|
-
"version:patch": "npm version patch",
|
|
14
|
-
"version:minior": "npm version minor",
|
|
15
|
-
"version:major": "npm version major",
|
|
16
|
-
"publish:stable": "npm publish --access public",
|
|
17
|
-
"prepare": "husky install",
|
|
18
|
-
"mac-chmod": "chmod +x .husky && chmod +x .husky/pre-commit",
|
|
19
|
-
"docs": "typedoc"
|
|
20
|
-
},
|
|
21
|
-
"files": [
|
|
22
|
-
"src",
|
|
23
|
-
"CHANGELOG.md"
|
|
24
|
-
],
|
|
25
|
-
"keywords": [],
|
|
26
|
-
"author": "CaiYansong",
|
|
27
|
-
"license": "ISC",
|
|
28
|
-
"devDependencies": {
|
|
29
|
-
"@hzab/permissions": "1.0.0",
|
|
30
|
-
"@hzab/webpack-config": "1.1.4",
|
|
31
|
-
"@types/react": "17.0.62",
|
|
32
|
-
"@types/react-dom": "17.0.20",
|
|
33
|
-
"antd": "4.24.16",
|
|
34
|
-
"axios": "1.13.6",
|
|
35
|
-
"eslint": "8.30.0",
|
|
36
|
-
"less": "4.1.3",
|
|
37
|
-
"mobx": "6.7.0",
|
|
38
|
-
"mobx-react": "7.6.0",
|
|
39
|
-
"react": "17.0.2",
|
|
40
|
-
"react-dom": "17.0.2",
|
|
41
|
-
"react-router-dom": "6.14.1",
|
|
42
|
-
"typedoc": "0.24.8",
|
|
43
|
-
"typescript": "4.9.4",
|
|
44
|
-
"webpack": "5.75.0"
|
|
45
|
-
},
|
|
46
|
-
"directories": {
|
|
47
|
-
"src": "src"
|
|
48
|
-
},
|
|
49
|
-
"lint-staged": {
|
|
50
|
-
"**.{js,jsx,ts,tsx,css,scss,less,json,html}": [
|
|
51
|
-
"prettier --write"
|
|
52
|
-
]
|
|
53
|
-
},
|
|
54
|
-
"dependencies": {
|
|
55
|
-
"@hzab/form-render": "^1.7.17",
|
|
56
|
-
"@hzab/list-render": "^1.11.0",
|
|
57
|
-
"@silevis/reactgrid": "^4.1.17"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@hzab/edit-table",
|
|
3
|
+
"version": "0.0.2-alpha.0",
|
|
4
|
+
"description": "",
|
|
5
|
+
"main": "src",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "webpack serve -c ./config/webpack.config.js --env local",
|
|
8
|
+
"build": "webpack -c ./config/webpack.config.js --env production",
|
|
9
|
+
"version:alpha": "npm version prerelease --preid=alpha",
|
|
10
|
+
"publish:alpha": "npm publish --tag alpha",
|
|
11
|
+
"version:beta": "npm version prerelease --preid=beta",
|
|
12
|
+
"publish:beta": "npm publish --tag beta",
|
|
13
|
+
"version:patch": "npm version patch",
|
|
14
|
+
"version:minior": "npm version minor",
|
|
15
|
+
"version:major": "npm version major",
|
|
16
|
+
"publish:stable": "npm publish --access public",
|
|
17
|
+
"prepare": "husky install",
|
|
18
|
+
"mac-chmod": "chmod +x .husky && chmod +x .husky/pre-commit",
|
|
19
|
+
"docs": "typedoc"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"src",
|
|
23
|
+
"CHANGELOG.md"
|
|
24
|
+
],
|
|
25
|
+
"keywords": [],
|
|
26
|
+
"author": "CaiYansong",
|
|
27
|
+
"license": "ISC",
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@hzab/permissions": "1.0.0",
|
|
30
|
+
"@hzab/webpack-config": "1.1.4",
|
|
31
|
+
"@types/react": "17.0.62",
|
|
32
|
+
"@types/react-dom": "17.0.20",
|
|
33
|
+
"antd": "4.24.16",
|
|
34
|
+
"axios": "1.13.6",
|
|
35
|
+
"eslint": "8.30.0",
|
|
36
|
+
"less": "4.1.3",
|
|
37
|
+
"mobx": "6.7.0",
|
|
38
|
+
"mobx-react": "7.6.0",
|
|
39
|
+
"react": "17.0.2",
|
|
40
|
+
"react-dom": "17.0.2",
|
|
41
|
+
"react-router-dom": "6.14.1",
|
|
42
|
+
"typedoc": "0.24.8",
|
|
43
|
+
"typescript": "4.9.4",
|
|
44
|
+
"webpack": "5.75.0"
|
|
45
|
+
},
|
|
46
|
+
"directories": {
|
|
47
|
+
"src": "src"
|
|
48
|
+
},
|
|
49
|
+
"lint-staged": {
|
|
50
|
+
"**.{js,jsx,ts,tsx,css,scss,less,json,html}": [
|
|
51
|
+
"prettier --write"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@hzab/form-render": "^1.7.17",
|
|
56
|
+
"@hzab/list-render": "^1.11.0",
|
|
57
|
+
"@silevis/reactgrid": "^4.1.17"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -57,9 +57,6 @@ export const ExpandListTemplate = (props) => {
|
|
|
57
57
|
) : (
|
|
58
58
|
<div style={{ width: 14 }}></div>
|
|
59
59
|
)}
|
|
60
|
-
<div className={`expandList-template-name`} style={{ marginLeft: record?.level * 8 }}>
|
|
61
|
-
{Slots?.[columnId] ? colRender(record) : record[columnId]}
|
|
62
|
-
</div>
|
|
63
60
|
</div>
|
|
64
61
|
);
|
|
65
62
|
};
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
UncertainCompatible,
|
|
16
16
|
} from "@silevis/reactgrid";
|
|
17
17
|
import * as React from "react";
|
|
18
|
-
import { parseLocaleNumber } from "
|
|
18
|
+
import { parseLocaleNumber } from "../common/utils";
|
|
19
19
|
|
|
20
20
|
// NOTE: all modules imported below may be imported from '@silevis/reactgrid'
|
|
21
21
|
|
|
@@ -108,6 +108,10 @@ export const WidthWrapHoc = (WrapComponent: any) => {
|
|
|
108
108
|
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
109
109
|
const datatypeId = cell?.columnId + cell?.rowId;
|
|
110
110
|
const [comValue, setComValue] = useState(cell?.text);
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
setComValue(cell?.text);
|
|
113
|
+
}, [cell?.text]);
|
|
114
|
+
|
|
111
115
|
useEffect(() => {
|
|
112
116
|
// 处理下拉选项弹层失焦逻辑
|
|
113
117
|
function onClick() {
|
package/src/index.less
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
.grid-container {
|
|
2
2
|
overflow: auto;
|
|
3
3
|
position: relative;
|
|
4
|
-
max-height:
|
|
4
|
+
max-height: 100vh;
|
|
5
|
+
padding-bottom: 16px;
|
|
6
|
+
|
|
7
|
+
|
|
5
8
|
|
|
6
9
|
|
|
7
10
|
|
|
@@ -10,13 +13,13 @@
|
|
|
10
13
|
}
|
|
11
14
|
|
|
12
15
|
|
|
13
|
-
.reactgrid-content .rg-pane .rg-cell {
|
|
14
|
-
|
|
16
|
+
// .reactgrid-content .rg-pane .rg-cell {
|
|
17
|
+
// padding: 0;
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
19
|
+
// >div:nth-child(1) {
|
|
20
|
+
// padding: 0 4px;
|
|
21
|
+
// }
|
|
22
|
+
// }
|
|
20
23
|
|
|
21
24
|
.rg-header-cell,
|
|
22
25
|
.rg-cell {
|
package/src/index.tsx
CHANGED
|
@@ -29,6 +29,8 @@ interface CellEditTableProps {
|
|
|
29
29
|
query?: any;
|
|
30
30
|
loading?: boolean;
|
|
31
31
|
isExpand?: boolean;
|
|
32
|
+
getList?: () => void;
|
|
33
|
+
onRow?: (v: any, ri: number, ci: number) => void;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
export default function CellEditTable(props: CellEditTableProps) {
|
|
@@ -39,8 +41,8 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
39
41
|
onChange,
|
|
40
42
|
reactGridProps = {},
|
|
41
43
|
onEditSubmit,
|
|
42
|
-
headerRowHeight,
|
|
43
|
-
rowHeight,
|
|
44
|
+
headerRowHeight = 44,
|
|
45
|
+
rowHeight = 44,
|
|
44
46
|
reactGridStyle,
|
|
45
47
|
className,
|
|
46
48
|
Slots,
|
|
@@ -49,15 +51,21 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
49
51
|
query,
|
|
50
52
|
loading,
|
|
51
53
|
isExpand = false,
|
|
54
|
+
getList,
|
|
55
|
+
onRow,
|
|
52
56
|
} = props;
|
|
53
57
|
|
|
54
58
|
const [headerList, setHeaderList] = useState<any>([]);
|
|
55
59
|
const [rows, setRows] = useState<any>([]);
|
|
60
|
+
/** 初始行数据 */
|
|
61
|
+
const initRowsRef = useRef<any>([]);
|
|
56
62
|
const [tableColumns, setTableColumns] = useState<any>([]);
|
|
57
63
|
const [selectedRowKeys, setSelectedRowKeys] = useState<any>([]);
|
|
58
64
|
const [newDataSource, setNewDataSource] = useState<any>([]);
|
|
59
65
|
const [expandKeys, setExpandKeys] = useState<any>([]);
|
|
60
66
|
const [headerCustomTemplate, setHeaderCustomTemplate] = useState<any>([]);
|
|
67
|
+
const gridRef = useRef<any>();
|
|
68
|
+
|
|
61
69
|
/** 递归处理子节点数据 */
|
|
62
70
|
const handleDataSource = (arr, level = 0) => {
|
|
63
71
|
arr?.forEach((el) => {
|
|
@@ -166,9 +174,9 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
166
174
|
if (key == el) {
|
|
167
175
|
const it = formulaConfig[key];
|
|
168
176
|
newCell = {
|
|
169
|
-
text: it?.setCellData(item),
|
|
170
|
-
value: it?.setCellData(item),
|
|
171
|
-
style: it?.setCellStyle(it?.setCellData(item)),
|
|
177
|
+
text: it?.setCellData && it?.setCellData(item),
|
|
178
|
+
value: it?.setCellData && it?.setCellData(item),
|
|
179
|
+
style: it?.setCellStyle && it?.setCellStyle((it?.setCellData && it?.setCellData(item)) || item),
|
|
172
180
|
};
|
|
173
181
|
}
|
|
174
182
|
}
|
|
@@ -184,6 +192,7 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
184
192
|
value: cellItem,
|
|
185
193
|
selectedValue: cellItem || "",
|
|
186
194
|
style: columnsItem?.type == "rowSelection" ? { display: "flex", justifyContent: "center" } : {},
|
|
195
|
+
...((onRow && onRow(item, index, ind)) || {}),
|
|
187
196
|
...((columnsItem?.onCell && columnsItem?.onCell(item, index, ind)) || {}),
|
|
188
197
|
...(columnsItem?.cellProps || {}),
|
|
189
198
|
setNewDataSource,
|
|
@@ -200,7 +209,8 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
200
209
|
}, [newDataSource, tableColumns, headerList]);
|
|
201
210
|
|
|
202
211
|
// 单元格编辑回调
|
|
203
|
-
const handleCellsChanged = (changes) => {
|
|
212
|
+
const handleCellsChanged = async (changes) => {
|
|
213
|
+
const batchQuery: any = [];
|
|
204
214
|
if (!Array.isArray(changes) || changes.length === 0) return;
|
|
205
215
|
/** 批量提交 */
|
|
206
216
|
let isBatchSubmit = false;
|
|
@@ -208,32 +218,51 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
208
218
|
isBatchSubmit = true;
|
|
209
219
|
}
|
|
210
220
|
setRows((prevRows) => {
|
|
211
|
-
changes.forEach((change) => {
|
|
221
|
+
changes.forEach(async (change) => {
|
|
212
222
|
const hasDiff = JSON.stringify((window as any).preCell?.text) != JSON.stringify(change.newCell?.text);
|
|
213
223
|
if (!hasDiff) return;
|
|
214
224
|
const changeRowIdx = prevRows.findIndex((el) => el.rowId == change.rowId);
|
|
215
225
|
const changeColumnIdx = tableColumns.findIndex((el) => el.columnId == change.columnId);
|
|
216
226
|
prevRows[changeRowIdx].cells[changeColumnIdx] = { ...change.newCell };
|
|
227
|
+
batchQuery.push(handleArrayToObj(prevRows[changeRowIdx]));
|
|
217
228
|
if (formulaConfig) {
|
|
218
229
|
for (let key in formulaConfig) {
|
|
219
230
|
const item = formulaConfig[key];
|
|
220
231
|
const resultColumnIdx = tableColumns.findIndex((el) => el.columnId == key);
|
|
221
232
|
const newCell = {
|
|
222
233
|
...prevRows[changeRowIdx].cells[resultColumnIdx],
|
|
223
|
-
text: item?.setCellData(prevRows[changeRowIdx]),
|
|
224
|
-
value: item?.setCellData(prevRows[changeRowIdx]),
|
|
225
|
-
style:
|
|
234
|
+
text: item?.setCellData && item?.setCellData(prevRows[changeRowIdx]),
|
|
235
|
+
value: item?.setCellData && item?.setCellData(prevRows[changeRowIdx]),
|
|
236
|
+
style:
|
|
237
|
+
item?.setCellStyle &&
|
|
238
|
+
item?.setCellStyle(
|
|
239
|
+
(item?.setCellData && item?.setCellData(prevRows[changeRowIdx])) || prevRows[changeRowIdx],
|
|
240
|
+
),
|
|
226
241
|
};
|
|
227
242
|
prevRows[changeRowIdx].cells[resultColumnIdx] = newCell;
|
|
228
243
|
}
|
|
229
244
|
}
|
|
230
|
-
if (change?.newCell?.commit == "submit") {
|
|
231
|
-
|
|
245
|
+
if (change?.newCell?.commit == "submit" && onEditSubmit && !isBatchSubmit) {
|
|
246
|
+
try {
|
|
247
|
+
await onEditSubmit(batchQuery);
|
|
248
|
+
} catch (err) {
|
|
249
|
+
getList && getList();
|
|
250
|
+
}
|
|
232
251
|
}
|
|
252
|
+
|
|
233
253
|
onChange && onChange(prevRows[changeRowIdx]);
|
|
234
254
|
});
|
|
255
|
+
initRowsRef.current = prevRows;
|
|
235
256
|
return [...prevRows];
|
|
236
257
|
});
|
|
258
|
+
|
|
259
|
+
if (isBatchSubmit) {
|
|
260
|
+
try {
|
|
261
|
+
onEditSubmit && (await onEditSubmit(batchQuery));
|
|
262
|
+
} catch (err) {
|
|
263
|
+
getList && getList();
|
|
264
|
+
}
|
|
265
|
+
}
|
|
237
266
|
};
|
|
238
267
|
/** 自定义组件注册 */
|
|
239
268
|
const baseTemplate = useMemo(() => {
|
|
@@ -325,7 +354,10 @@ export default function CellEditTable(props: CellEditTableProps) {
|
|
|
325
354
|
<Spin spinning={loading}>
|
|
326
355
|
<div className={`grid-container ${className}`} style={reactGridStyle}>
|
|
327
356
|
<ReactGrid
|
|
328
|
-
|
|
357
|
+
ref={gridRef}
|
|
358
|
+
rows={loading ? initRowsRef.current : rows}
|
|
359
|
+
/** 兼容初始化时吸顶生效 */
|
|
360
|
+
key={loading ? 1 : 2}
|
|
329
361
|
columns={tableColumns}
|
|
330
362
|
onCellsChanged={handleCellsChanged}
|
|
331
363
|
enableFillHandle={true}
|
package/src/Template/utils.ts
DELETED
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
export const getNavigatorLanguage = (): string => navigator.language || "en-US";
|
|
2
|
-
|
|
3
|
-
function getLocaleSeparators(locale: string) {
|
|
4
|
-
const testNumber = 123456.789;
|
|
5
|
-
const localeFormattedNumber = Intl.NumberFormat(locale).format(testNumber);
|
|
6
|
-
|
|
7
|
-
// Get the thousands separator of the locale
|
|
8
|
-
const thousandsSeparator = localeFormattedNumber.split("123")[1][0];
|
|
9
|
-
|
|
10
|
-
// Get the decimal separator of the locale
|
|
11
|
-
const decimalSeparator = localeFormattedNumber.split("123")[1][4];
|
|
12
|
-
return { thousandsSeparator, decimalSeparator };
|
|
13
|
-
}
|
|
14
|
-
export function parseLocaleNumber(stringNumber: string, locale = getNavigatorLanguage()): number {
|
|
15
|
-
if (!stringNumber.trim()) return NaN;
|
|
16
|
-
const { thousandsSeparator, decimalSeparator } = getLocaleSeparators(locale);
|
|
17
|
-
const normalizedStringNumber = stringNumber.replace(/\u00A0/g, " "); // Replace non-breaking space with normal space
|
|
18
|
-
const numberString = normalizedStringNumber
|
|
19
|
-
.replace(new RegExp(`[${thousandsSeparator}\\s]`, "g"), "") // Replace thousands separator and white-space
|
|
20
|
-
.replace(new RegExp(`\\${decimalSeparator}`, "g"), "."); // Replace decimal separator
|
|
21
|
-
|
|
22
|
-
const trimmedNumberString = numberString.replace(/^(?!-)\D+|\D+$/g, ""); // Remove characters before first and after last number, but keep negative sign
|
|
23
|
-
if (trimmedNumberString === null || trimmedNumberString.trim().length === 0) {
|
|
24
|
-
return NaN;
|
|
25
|
-
}
|
|
26
|
-
return Number(trimmedNumberString);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
export function isReactElement(value) {
|
|
31
|
-
return value !== null && typeof value === "object";
|
|
32
|
-
}
|
|
33
|
-
const getTitle = (item) => {
|
|
34
|
-
return typeof item?.title == "function"
|
|
35
|
-
? isReactElement(item?.title())
|
|
36
|
-
? item?.title()?.props.children
|
|
37
|
-
: String(item?.title()) || ""
|
|
38
|
-
: String(item?.title) || ""
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function convertColumnsToRows(columns, headerRowHeight = 40) {
|
|
42
|
-
// 获取所有叶子节点
|
|
43
|
-
const getLeaves = (cols) => {
|
|
44
|
-
return cols.reduce((acc, col) => {
|
|
45
|
-
if (col.children?.length) {
|
|
46
|
-
return [...acc, ...getLeaves(col.children)];
|
|
47
|
-
}
|
|
48
|
-
return [...acc, col];
|
|
49
|
-
}, []);
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
// 计算最大深度
|
|
53
|
-
const getDepth = (cols, depth = 1) => {
|
|
54
|
-
return cols.reduce((max, col) => {
|
|
55
|
-
if (col.children?.length) {
|
|
56
|
-
return Math.max(max, getDepth(col.children, depth + 1));
|
|
57
|
-
}
|
|
58
|
-
return Math.max(max, depth);
|
|
59
|
-
}, depth);
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const leafColumns = getLeaves(columns);
|
|
63
|
-
const totalDepth = getDepth(columns);
|
|
64
|
-
const totalCols = leafColumns.length;
|
|
65
|
-
|
|
66
|
-
// 构建表头树
|
|
67
|
-
const buildTree = (cols, depth = 0) => {
|
|
68
|
-
return cols.map((col) => {
|
|
69
|
-
const hasChildren = col.children?.length > 0;
|
|
70
|
-
if (!hasChildren) {
|
|
71
|
-
return {
|
|
72
|
-
...col,
|
|
73
|
-
rowspan: totalDepth - depth,
|
|
74
|
-
colspan: 1,
|
|
75
|
-
_depth: depth,
|
|
76
|
-
_isLeaf: true,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
const leafCount = getLeaves(col.children).length;
|
|
80
|
-
return {
|
|
81
|
-
...col,
|
|
82
|
-
rowspan: 1,
|
|
83
|
-
colspan: leafCount,
|
|
84
|
-
_depth: depth,
|
|
85
|
-
_isLeaf: false,
|
|
86
|
-
children: buildTree(col.children, depth + 1),
|
|
87
|
-
};
|
|
88
|
-
});
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
const tree = buildTree(columns, 0);
|
|
92
|
-
|
|
93
|
-
// 初始化行
|
|
94
|
-
const rows: any = Array.from({ length: totalDepth }, (_, i) => ({
|
|
95
|
-
rowId: `header-${i}`,
|
|
96
|
-
height: headerRowHeight,
|
|
97
|
-
cells: [],
|
|
98
|
-
}));
|
|
99
|
-
|
|
100
|
-
const handleType = (item) => {
|
|
101
|
-
if (["rowSelection", "ExpandListTemplate"]?.includes(item?.type)) {
|
|
102
|
-
return item?.type
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
if (isReactElement(typeof item?.title == "function" ? item?.title() : null)) {
|
|
106
|
-
return `${item?.dataIndex}`
|
|
107
|
-
}
|
|
108
|
-
return "header"
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
// 递归填充行
|
|
113
|
-
const fillRow = (nodes, rowIndex = 0) => {
|
|
114
|
-
nodes.forEach((node) => {
|
|
115
|
-
if (node._isLeaf) {
|
|
116
|
-
const cell = {
|
|
117
|
-
...node,
|
|
118
|
-
type: handleType(node),
|
|
119
|
-
text: getTitle(node),
|
|
120
|
-
dataIndex: node.dataIndex,
|
|
121
|
-
width: node.width,
|
|
122
|
-
rowspan: node.rowspan,
|
|
123
|
-
style: node?.style ? node?.style : {
|
|
124
|
-
background: "rgba(128, 128, 128, 0.1)",
|
|
125
|
-
display: "flex",
|
|
126
|
-
justifyContent: "center"
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
if (node.sorter) cell.sorter = node.sorter;
|
|
130
|
-
if (node.key) cell.key = node.key;
|
|
131
|
-
rows[rowIndex].cells.push(cell);
|
|
132
|
-
} else {
|
|
133
|
-
// 父节点:添加colspan
|
|
134
|
-
rows[rowIndex].cells.push({
|
|
135
|
-
...node,
|
|
136
|
-
type: handleType(node),
|
|
137
|
-
text: getTitle(node),
|
|
138
|
-
colspan: node.colspan,
|
|
139
|
-
style: node?.style ? node?.style : {
|
|
140
|
-
background: "rgba(128, 128, 128, 0.1)",
|
|
141
|
-
display: "flex",
|
|
142
|
-
justifyContent: "center"
|
|
143
|
-
},
|
|
144
|
-
});
|
|
145
|
-
if (node.children) {
|
|
146
|
-
fillRow(node.children, rowIndex + 1);
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
fillRow(tree, 0);
|
|
153
|
-
|
|
154
|
-
// 补全每一行的cell,使长度一致
|
|
155
|
-
rows.forEach((row, rowIndex) => {
|
|
156
|
-
const newCells = [];
|
|
157
|
-
let colIndex = 0;
|
|
158
|
-
let cellIndex = 0;
|
|
159
|
-
|
|
160
|
-
while (colIndex < totalCols) {
|
|
161
|
-
const currentCell = row.cells[cellIndex];
|
|
162
|
-
|
|
163
|
-
if (!currentCell) {
|
|
164
|
-
// 如果当前行没有足够的cell,从叶子节点补充
|
|
165
|
-
const leaf = leafColumns[colIndex];
|
|
166
|
-
newCells.push({
|
|
167
|
-
...leaf,
|
|
168
|
-
type: handleType(leaf),
|
|
169
|
-
text: getTitle(leaf),
|
|
170
|
-
dataIndex: leaf.dataIndex,
|
|
171
|
-
width: leaf.width,
|
|
172
|
-
rowspan: rowIndex === totalDepth - 1 ? 1 : undefined,
|
|
173
|
-
style: leaf?.style ? leaf?.style : {
|
|
174
|
-
background: "rgba(128, 128, 128, 0.1)",
|
|
175
|
-
display: "flex",
|
|
176
|
-
justifyContent: "center"
|
|
177
|
-
},
|
|
178
|
-
});
|
|
179
|
-
colIndex++;
|
|
180
|
-
cellIndex++;
|
|
181
|
-
continue;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const colspan = currentCell.colspan || 1;
|
|
185
|
-
const rowspan = currentCell.rowspan || 1;
|
|
186
|
-
|
|
187
|
-
// 检查当前cell是否应该出现在这一行
|
|
188
|
-
// 如果rowspan > 1,表示它跨多行,但只在第一行出现
|
|
189
|
-
if (rowspan > 1 && rowIndex > 0) {
|
|
190
|
-
// 这个cell不应该出现在当前行,跳过
|
|
191
|
-
colIndex += colspan;
|
|
192
|
-
cellIndex++;
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// 如果当前cell有colspan,需要补全后面的空cell
|
|
197
|
-
newCells.push(currentCell);
|
|
198
|
-
colIndex += colspan;
|
|
199
|
-
cellIndex++;
|
|
200
|
-
|
|
201
|
-
// 如果colspan > 1,后面补充空cell
|
|
202
|
-
for (let i = 1; i < colspan; i++) {
|
|
203
|
-
newCells.push({
|
|
204
|
-
type: "header",
|
|
205
|
-
text: "",
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
row.cells = newCells;
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
// 最后一行的特殊处理:确保所有叶子节点都有对应的cell
|
|
214
|
-
const lastRow = rows[totalDepth - 1];
|
|
215
|
-
const lastRowCells = [];
|
|
216
|
-
let leafIndex = 0;
|
|
217
|
-
|
|
218
|
-
// 遍历所有叶子节点
|
|
219
|
-
leafColumns.forEach((leaf, index) => {
|
|
220
|
-
// 检查是否已经在lastRow中有对应的cell
|
|
221
|
-
const existingCell = lastRow.cells.find((cell) => cell.dataIndex === leaf.dataIndex && cell.text === leaf.title);
|
|
222
|
-
|
|
223
|
-
if (existingCell) {
|
|
224
|
-
lastRowCells.push(existingCell);
|
|
225
|
-
} else {
|
|
226
|
-
// 创建新的cell
|
|
227
|
-
lastRowCells.push({
|
|
228
|
-
...leaf,
|
|
229
|
-
type: handleType(leaf),
|
|
230
|
-
text: getTitle(leaf),
|
|
231
|
-
dataIndex: leaf.dataIndex,
|
|
232
|
-
width: leaf.width,
|
|
233
|
-
rowspan: 1,
|
|
234
|
-
style: leaf?.style ? leaf?.style : {
|
|
235
|
-
background: "rgba(128, 128, 128, 0.1)",
|
|
236
|
-
display: "flex",
|
|
237
|
-
justifyContent: "center"
|
|
238
|
-
},
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
lastRow.cells = lastRowCells;
|
|
244
|
-
|
|
245
|
-
// 确保所有行的cell数量等于totalCols
|
|
246
|
-
rows.forEach((row) => {
|
|
247
|
-
// 如果cell数量少于totalCols,补充空cell
|
|
248
|
-
while (row.cells.length < totalCols) {
|
|
249
|
-
row.cells.push({
|
|
250
|
-
type: "header",
|
|
251
|
-
text: "",
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
return rows;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
export function flattenColumns(columns: any[]) {
|
|
261
|
-
const result: any[] = [];
|
|
262
|
-
|
|
263
|
-
function traverse(cols) {
|
|
264
|
-
cols.forEach((col) => {
|
|
265
|
-
if (col.children && col.children.length > 0) {
|
|
266
|
-
traverse(col.children);
|
|
267
|
-
} else {
|
|
268
|
-
// 创建新对象,只保留需要的属性
|
|
269
|
-
const { title, dataIndex, key, width, sorter, k, ...rest } = col;
|
|
270
|
-
|
|
271
|
-
result.push({
|
|
272
|
-
type: "Input",
|
|
273
|
-
dataIndex,
|
|
274
|
-
title,
|
|
275
|
-
...(key && { key }),
|
|
276
|
-
...(width && { width }),
|
|
277
|
-
...(sorter && { sorter }),
|
|
278
|
-
...(k && { k }),
|
|
279
|
-
// 如果需要保留其他属性
|
|
280
|
-
...rest,
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
});
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
traverse(columns);
|
|
287
|
-
return result;
|
|
288
|
-
}
|
package/src/common/test.ts
DELETED