@enableai-base/table 1.0.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/dist/table.cjs.js +4465 -0
- package/dist/table.cjs.prod.js +4465 -0
- package/dist/table.css +73 -0
- package/dist/table.d.ts +1275 -0
- package/dist/table.esm-bundler.mjs +4292 -0
- package/index.js +7 -0
- package/index.node.js +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,4465 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @enableai-base/table v1.0.0
|
|
3
|
+
* (c) 2024-present Enableai
|
|
4
|
+
* @license Proprietary
|
|
5
|
+
**/
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
9
|
+
|
|
10
|
+
var React = require('react');
|
|
11
|
+
var reactHooks = require('@enableai-sdk-common/react-hooks');
|
|
12
|
+
var core = require('@enableai-base/core');
|
|
13
|
+
var lodash = require('lodash');
|
|
14
|
+
var vrender = require('@visactor/vtable/es/vrender');
|
|
15
|
+
var color = require('@enableai-sdk-common/color');
|
|
16
|
+
var id = require('@enableai-sdk-common/id');
|
|
17
|
+
var store = require('@enableai-sdk-common/store');
|
|
18
|
+
var jotai = require('jotai');
|
|
19
|
+
var command = require('@enableai-sdk-common/command');
|
|
20
|
+
var fontIconEnableaiBase = require('@enableai-fonts/font-icon-enableai-base');
|
|
21
|
+
var dayjs = require('dayjs');
|
|
22
|
+
var customParseFormat = require('dayjs/plugin/customParseFormat');
|
|
23
|
+
var timezone = require('dayjs/plugin/timezone');
|
|
24
|
+
var utc = require('dayjs/plugin/utc');
|
|
25
|
+
var antd = require('antd');
|
|
26
|
+
var gridLayout = require('@enableai-base/grid-layout');
|
|
27
|
+
var icons = require('@ant-design/icons');
|
|
28
|
+
var ui = require('@enableai-base/ui');
|
|
29
|
+
var reactHotkeysHook = require('react-hotkeys-hook');
|
|
30
|
+
var core$1 = require('@enableai-sdk-common/core');
|
|
31
|
+
var VTable = require('@visactor/vtable');
|
|
32
|
+
var VTable_editors = require('@visactor/vtable-editors');
|
|
33
|
+
|
|
34
|
+
function _interopNamespaceDefault(e) {
|
|
35
|
+
var n = Object.create(null);
|
|
36
|
+
if (e) {
|
|
37
|
+
for (var k in e) {
|
|
38
|
+
n[k] = e[k];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
n.default = e;
|
|
42
|
+
return Object.freeze(n);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
var VTable__namespace = /*#__PURE__*/_interopNamespaceDefault(VTable);
|
|
46
|
+
var VTable_editors__namespace = /*#__PURE__*/_interopNamespaceDefault(VTable_editors);
|
|
47
|
+
|
|
48
|
+
const theme = {
|
|
49
|
+
selectionStyle: {
|
|
50
|
+
cellBorderColor: core.COLOR_BORDER_SELECTION,
|
|
51
|
+
cellBgColor: "rgba(255,255,255, 0.1)"
|
|
52
|
+
},
|
|
53
|
+
frameStyle: {
|
|
54
|
+
borderLineWidth: core.BORDER_LINE_WIDTH,
|
|
55
|
+
// 全局边框宽度
|
|
56
|
+
borderColor: core.BORDER_COLOR
|
|
57
|
+
// 全局边框颜色 最外面的方框
|
|
58
|
+
},
|
|
59
|
+
cellInnerBorder: true,
|
|
60
|
+
// 禁用内边框隐藏逻辑
|
|
61
|
+
defaultStyle: {
|
|
62
|
+
fontSize: core.DEFAULT_FONT_SIZE,
|
|
63
|
+
borderColor: core.BORDER_COLOR,
|
|
64
|
+
borderLineWidth: core.BORDER_LINE_WIDTH,
|
|
65
|
+
bgColor: core.COLOR_BG_CELL,
|
|
66
|
+
hover: {
|
|
67
|
+
// CustomCellStyle 设置的样式优先级更高
|
|
68
|
+
// TODO 感觉会变卡,后续优化,将样式设置属性放在 item 数据里面驱动控制
|
|
69
|
+
cellBgColor: ({ table, row, col }) => {
|
|
70
|
+
const cellStyle = table.getCellStyle(col, row);
|
|
71
|
+
const matched = core.CUSTOM_STYLE_LIST.filter((item) => lodash.isMatch(cellStyle, { bgColor: item.bgColor }));
|
|
72
|
+
if (matched.length) return cellStyle.bgColor;
|
|
73
|
+
return core.COLOR_BG_CELL_HOVER;
|
|
74
|
+
},
|
|
75
|
+
inlineRowBgColor: ({ table, row, col }) => {
|
|
76
|
+
const cellStyle = table.getCellStyle(col, row);
|
|
77
|
+
const matched = core.CUSTOM_STYLE_LIST.filter((item) => lodash.isMatch(cellStyle, { bgColor: item.bgColor }));
|
|
78
|
+
if (matched.length) return cellStyle.bgColor;
|
|
79
|
+
return core.COLOR_BG_CELL_HOVER;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
headerStyle: {
|
|
84
|
+
fontSize: core.HEADER_FONT_SIZE
|
|
85
|
+
},
|
|
86
|
+
bodyStyle: {
|
|
87
|
+
fontSize: core.DEFAULT_FONT_SIZE
|
|
88
|
+
},
|
|
89
|
+
frozenColumnLine: {
|
|
90
|
+
shadow: {
|
|
91
|
+
width: 4,
|
|
92
|
+
startColor: "rgba(00, 24, 47, 0.05)",
|
|
93
|
+
endColor: "rgba(00, 24, 47, 0.03)",
|
|
94
|
+
visible: "always"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const { createUseContext, Provider: VTableProvider } = reactHooks.createContextWithProvider(
|
|
100
|
+
({
|
|
101
|
+
id,
|
|
102
|
+
columns,
|
|
103
|
+
initialValues,
|
|
104
|
+
onChange,
|
|
105
|
+
ref,
|
|
106
|
+
theme: theme$1,
|
|
107
|
+
disabled = false,
|
|
108
|
+
debug = false,
|
|
109
|
+
cellMenus,
|
|
110
|
+
headerMenus,
|
|
111
|
+
moreMenus,
|
|
112
|
+
commandManager,
|
|
113
|
+
uploadFileFn,
|
|
114
|
+
innerColumnControl = {
|
|
115
|
+
checkbox: true,
|
|
116
|
+
main: true,
|
|
117
|
+
plus: true
|
|
118
|
+
},
|
|
119
|
+
...rest
|
|
120
|
+
}) => {
|
|
121
|
+
const containerRef = React.useRef(null);
|
|
122
|
+
const editorRef = React.useRef(null);
|
|
123
|
+
React.useImperativeHandle(ref, () => {
|
|
124
|
+
return {
|
|
125
|
+
getEditor: () => editorRef.current
|
|
126
|
+
};
|
|
127
|
+
});
|
|
128
|
+
return {
|
|
129
|
+
id,
|
|
130
|
+
editorRef,
|
|
131
|
+
theme: theme$1 ?? theme,
|
|
132
|
+
columns,
|
|
133
|
+
records: initialValues,
|
|
134
|
+
containerRef,
|
|
135
|
+
disabled,
|
|
136
|
+
cellMenus,
|
|
137
|
+
headerMenus,
|
|
138
|
+
moreMenus,
|
|
139
|
+
onChange,
|
|
140
|
+
commandManager,
|
|
141
|
+
uploadFileFn,
|
|
142
|
+
innerColumnControl,
|
|
143
|
+
debug,
|
|
144
|
+
...rest
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
const useComponentVTable = createUseContext();
|
|
149
|
+
|
|
150
|
+
const INNER_TABLE_COLUMN_KEY_PLUS = "INNER_TABLE_COLUMN_KEY_PLUS";
|
|
151
|
+
const INNER_TABLE_COLUMN_KEY_CHECKBOX = "INNER_TABLE_COLUMN_KEY_CHECKBOX";
|
|
152
|
+
const INNER_TABLE_COLUMN_KEY_LIST = [INNER_TABLE_COLUMN_KEY_PLUS, INNER_TABLE_COLUMN_KEY_CHECKBOX];
|
|
153
|
+
const INNER_TABLE_RECORD_ID_KEY = "INNER_PRESET_RECORD_ID";
|
|
154
|
+
|
|
155
|
+
const highlightMerge = (obj1, obj2) => {
|
|
156
|
+
return lodash.mergeWith({}, obj1, obj2, (objValue, srcValue) => {
|
|
157
|
+
if (Array.isArray(objValue)) {
|
|
158
|
+
return objValue.concat(srcValue);
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
const getColFromColIndex = (colIndex, innerColumnControl) => {
|
|
163
|
+
const hasCheckbox = innerColumnControl.checkbox;
|
|
164
|
+
return colIndex + (hasCheckbox ? 1 : 0);
|
|
165
|
+
};
|
|
166
|
+
const adaptedCellPosition = (col, row, innerColumnControl) => ({
|
|
167
|
+
col: getColFromColIndex(col, innerColumnControl),
|
|
168
|
+
row: getRowFromRowIndex(row)
|
|
169
|
+
});
|
|
170
|
+
const getRowFromRowIndex = (rowIndex) => rowIndex + 1;
|
|
171
|
+
|
|
172
|
+
function isValid(value) {
|
|
173
|
+
return value !== null && value !== void 0;
|
|
174
|
+
}
|
|
175
|
+
function getIconSizeFromFont(fontSize) {
|
|
176
|
+
return fontSize + 2;
|
|
177
|
+
}
|
|
178
|
+
function getFunctionalProp(name, cellStyle, col, row, _table) {
|
|
179
|
+
const prop = cellStyle && isValid(cellStyle[name]) ? cellStyle[name] : void 0;
|
|
180
|
+
if (typeof prop === "function") {
|
|
181
|
+
const arg = {
|
|
182
|
+
col,
|
|
183
|
+
row,
|
|
184
|
+
table: _table,
|
|
185
|
+
value: _table.getCellValue(col, row),
|
|
186
|
+
dataValue: _table.getCellOriginValue(col, row),
|
|
187
|
+
cellHeaderPaths: _table.getCellHeaderPaths(col, row)
|
|
188
|
+
};
|
|
189
|
+
return prop(arg);
|
|
190
|
+
}
|
|
191
|
+
return void 0;
|
|
192
|
+
}
|
|
193
|
+
function getProp(name, cellStyle, col, row, _table) {
|
|
194
|
+
const prop = cellStyle && isValid(cellStyle[name]) ? cellStyle[name] : void 0;
|
|
195
|
+
if (typeof prop === "function") {
|
|
196
|
+
const arg = {
|
|
197
|
+
col,
|
|
198
|
+
row,
|
|
199
|
+
table: _table,
|
|
200
|
+
value: _table.getCellValue(col, row),
|
|
201
|
+
dataValue: _table.getCellOriginValue(col, row),
|
|
202
|
+
cellHeaderPaths: _table.getCellHeaderPaths(col, row)
|
|
203
|
+
};
|
|
204
|
+
return prop(arg);
|
|
205
|
+
}
|
|
206
|
+
return prop ?? core.DEFAULT_FONT_SIZE;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
const resolvePaddingLR = (padding) => {
|
|
210
|
+
if (typeof padding === "number") {
|
|
211
|
+
return [padding, padding];
|
|
212
|
+
} else {
|
|
213
|
+
if (padding.length === 2) {
|
|
214
|
+
return [padding[1], padding[1]];
|
|
215
|
+
} else if (padding.length === 4) {
|
|
216
|
+
return [padding[1], padding[3]];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
throw new Error("padding \u683C\u5F0F\u9519\u8BEF");
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
function getAttribute(graphics) {
|
|
223
|
+
if ("attribute" in graphics) {
|
|
224
|
+
return graphics.attribute;
|
|
225
|
+
} else {
|
|
226
|
+
return graphics.props.attribute;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const createGraphicsWithLoading = (graphics, loading) => {
|
|
230
|
+
const attribute = getAttribute(graphics);
|
|
231
|
+
if (loading) {
|
|
232
|
+
const group = vrender.createGroup({
|
|
233
|
+
width: attribute.width,
|
|
234
|
+
height: attribute.height,
|
|
235
|
+
display: "flex",
|
|
236
|
+
alignItems: "center",
|
|
237
|
+
justifyContent: "center",
|
|
238
|
+
alignContent: "center"
|
|
239
|
+
});
|
|
240
|
+
const loadingImage = vrender.createImage({
|
|
241
|
+
width: 20,
|
|
242
|
+
height: 20,
|
|
243
|
+
image: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTAiIGhlaWdodD0iNTAiIGZpbGw9IiNjYWNhY2EiIHZpZXdCb3g9IjAgMCAxMDI0IDEwMjQiIGZvY3VzYWJsZT0iZmFsc2UiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTk4OCA1NDhjLTE5LjkgMC0zNi0xNi4xLTM2LTM2IDAtNTkuNC0xMS42LTExNy0zNC42LTE3MS4zYTQ0MC40NSA0NDAuNDUgMCAwMC05NC4zLTEzOS45IDQzNy43MSA0MzcuNzEgMCAwMC0xMzkuOS05NC4zQzYyOSA4My42IDU3MS40IDcyIDUxMiA3MmMtMTkuOSAwLTM2LTE2LjEtMzYtMzZzMTYuMS0zNiAzNi0zNmM2OS4xIDAgMTM2LjIgMTMuNSAxOTkuMyA0MC4zQzc3Mi4zIDY2IDgyNyAxMDMgODc0IDE1MGM0NyA0NyA4My45IDEwMS44IDEwOS43IDE2Mi43IDI2LjcgNjMuMSA0MC4yIDEzMC4yIDQwLjIgMTk5LjMuMSAxOS45LTE2IDM2LTM1LjkgMzZ6IiAvPjwvc3ZnPg==",
|
|
244
|
+
anchor: [attribute.width / 2, attribute.height / 2],
|
|
245
|
+
cornerRadius: 10
|
|
246
|
+
});
|
|
247
|
+
loadingImage.animate().to(
|
|
248
|
+
{
|
|
249
|
+
angle: Math.PI * 2
|
|
250
|
+
},
|
|
251
|
+
1e3,
|
|
252
|
+
"linear"
|
|
253
|
+
).loop(Infinity);
|
|
254
|
+
group.add(loadingImage);
|
|
255
|
+
return group;
|
|
256
|
+
} else {
|
|
257
|
+
return graphics;
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const createTextGraphics = (props) => {
|
|
262
|
+
const { table, row, col, rect } = props;
|
|
263
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
264
|
+
const value = props.value?.value ?? "";
|
|
265
|
+
const loading = !!props.value?.loading;
|
|
266
|
+
const cellStyle = table._getCellStyle(col, row);
|
|
267
|
+
const functionalFontSize = getProp("fontSize", cellStyle, col, row, table);
|
|
268
|
+
const functionalColor = getProp("color", cellStyle, col, row, table);
|
|
269
|
+
const parsedColor = props.color ?? functionalColor;
|
|
270
|
+
const padding = getProp("padding", cellStyle, col, row, table);
|
|
271
|
+
const paddingLR = resolvePaddingLR(padding);
|
|
272
|
+
const group = vrender.createGroup({
|
|
273
|
+
width,
|
|
274
|
+
height,
|
|
275
|
+
display: "flex",
|
|
276
|
+
flexWrap: "nowrap",
|
|
277
|
+
justifyContent: "space-around",
|
|
278
|
+
alignContent: "center",
|
|
279
|
+
alignItems: "center"
|
|
280
|
+
// 垂直居中
|
|
281
|
+
});
|
|
282
|
+
const text = vrender.createText({
|
|
283
|
+
fontSize: functionalFontSize,
|
|
284
|
+
fontFamily: "sans-serif",
|
|
285
|
+
text: value,
|
|
286
|
+
fill: parsedColor,
|
|
287
|
+
cursor: "pointer",
|
|
288
|
+
maxLineWidth: width - paddingLR[0] - paddingLR[1],
|
|
289
|
+
boundsPadding: padding
|
|
290
|
+
});
|
|
291
|
+
group.add(text);
|
|
292
|
+
return createGraphicsWithLoading(group, loading);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const createJsonGraphics = (props) => {
|
|
296
|
+
const value = props.value?.value ?? "";
|
|
297
|
+
let parsedValue = "";
|
|
298
|
+
try {
|
|
299
|
+
parsedValue = JSON.stringify(JSON.parse(value));
|
|
300
|
+
return createTextGraphics({
|
|
301
|
+
...props,
|
|
302
|
+
value: {
|
|
303
|
+
...props.value,
|
|
304
|
+
value: parsedValue
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
} catch {
|
|
308
|
+
return createTextGraphics({
|
|
309
|
+
...props,
|
|
310
|
+
color: "red",
|
|
311
|
+
value: {
|
|
312
|
+
...props.value,
|
|
313
|
+
value: "JSON Error"
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
const VTableEditorType = {
|
|
320
|
+
"TEXT_AREA": "textAreaEditor",
|
|
321
|
+
"INPUT": "inputEditor",
|
|
322
|
+
"DATE": "dateInputEditor",
|
|
323
|
+
"MULTI_SELECT": "multiSelectEditor",
|
|
324
|
+
"SINGLE_SELECT": "singleSelectEditor",
|
|
325
|
+
"LINK": "linkEditor",
|
|
326
|
+
"NUMBER": "numberEditor",
|
|
327
|
+
"TEXT": "textEditor",
|
|
328
|
+
"JSON": "jsonEditor"
|
|
329
|
+
};
|
|
330
|
+
|
|
331
|
+
const toolTypeToEditorMap = /* @__PURE__ */ new Map([
|
|
332
|
+
[29, "singleSelectEditor"],
|
|
333
|
+
[30, "multiSelectEditor"],
|
|
334
|
+
[36, "dateInputEditor"],
|
|
335
|
+
[33, "linkEditor"],
|
|
336
|
+
[34, "jsonEditor"],
|
|
337
|
+
[31, "numberEditor"],
|
|
338
|
+
[37, "numberEditor"],
|
|
339
|
+
// 多个 key 映射到同一个 value
|
|
340
|
+
[28, "textEditor"],
|
|
341
|
+
[35, "textEditor"]
|
|
342
|
+
]);
|
|
343
|
+
const getEditorByToolType = (toolType) => {
|
|
344
|
+
return toolTypeToEditorMap.get(toolType) ?? void 0;
|
|
345
|
+
};
|
|
346
|
+
|
|
347
|
+
const baseCreator = (data, _innerColumnControl) => {
|
|
348
|
+
const { id, label, lock, width, type, options } = data;
|
|
349
|
+
const minWidth = 100;
|
|
350
|
+
const baseColumn = {
|
|
351
|
+
field: id,
|
|
352
|
+
title: label,
|
|
353
|
+
lock,
|
|
354
|
+
width: Math.max(minWidth, width ?? 0),
|
|
355
|
+
minWidth,
|
|
356
|
+
tool: type,
|
|
357
|
+
fmt: data.default?.format,
|
|
358
|
+
options,
|
|
359
|
+
request: data.request,
|
|
360
|
+
editor: getEditorByToolType(type),
|
|
361
|
+
// 默认表头渲染函数
|
|
362
|
+
headerCustomLayout: (args) => {
|
|
363
|
+
return {
|
|
364
|
+
rootContainer: createHeaderGraphics(type, args),
|
|
365
|
+
renderDefault: false
|
|
366
|
+
};
|
|
367
|
+
},
|
|
368
|
+
customLayout: (args) => {
|
|
369
|
+
return {
|
|
370
|
+
rootContainer: createTextGraphics(args),
|
|
371
|
+
renderDefault: false
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
return baseColumn;
|
|
376
|
+
};
|
|
377
|
+
const textColumnCreator = (data, innerColumnControl) => {
|
|
378
|
+
const baseColumn = baseCreator(data);
|
|
379
|
+
return {
|
|
380
|
+
...baseColumn,
|
|
381
|
+
customLayout: (args) => {
|
|
382
|
+
return {
|
|
383
|
+
rootContainer: createTextGraphics(args),
|
|
384
|
+
renderDefault: false
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
};
|
|
389
|
+
const simpleSelectColumnCreator = (data, innerColumnControl) => {
|
|
390
|
+
const baseColumn = baseCreator(data);
|
|
391
|
+
return {
|
|
392
|
+
...baseColumn,
|
|
393
|
+
editor: "singleSelectEditor",
|
|
394
|
+
customLayout: (args) => {
|
|
395
|
+
return {
|
|
396
|
+
rootContainer: createSingleSelectGraphic(args),
|
|
397
|
+
renderDefault: false
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
};
|
|
402
|
+
const multiSelectColumnCreator = (data, innerColumnControl) => {
|
|
403
|
+
const baseColumn = baseCreator(data);
|
|
404
|
+
return {
|
|
405
|
+
...baseColumn,
|
|
406
|
+
editor: "multiSelectEditor",
|
|
407
|
+
customLayout: (args) => {
|
|
408
|
+
const { table, row, col, rect } = args;
|
|
409
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
410
|
+
return {
|
|
411
|
+
rootContainer: createMultiSelectGraphic({ width, height, ...args }),
|
|
412
|
+
renderDefault: false
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
};
|
|
417
|
+
const numberColumnCreator = (data, innerColumnControl) => {
|
|
418
|
+
const baseColumn = baseCreator(data);
|
|
419
|
+
return {
|
|
420
|
+
...baseColumn,
|
|
421
|
+
fmt: data.default?.format,
|
|
422
|
+
// editor: "numberEditor",
|
|
423
|
+
customLayout: (args) => {
|
|
424
|
+
return {
|
|
425
|
+
rootContainer: createNumberGraphics({
|
|
426
|
+
...args,
|
|
427
|
+
textAlign: "right"
|
|
428
|
+
}),
|
|
429
|
+
renderDefault: false
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
};
|
|
434
|
+
const attachmentColumnCreator = (data, innerColumnControl) => {
|
|
435
|
+
const baseColumn = baseCreator(data);
|
|
436
|
+
return {
|
|
437
|
+
...baseColumn,
|
|
438
|
+
customLayout: (args) => {
|
|
439
|
+
return {
|
|
440
|
+
rootContainer: createUploadDocumentGraphics(args),
|
|
441
|
+
renderDefault: false
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
};
|
|
445
|
+
};
|
|
446
|
+
const linkColumnCreator = (data, innerColumnControl) => {
|
|
447
|
+
const baseColumn = baseCreator(data);
|
|
448
|
+
return {
|
|
449
|
+
...baseColumn,
|
|
450
|
+
customLayout: (args) => {
|
|
451
|
+
return {
|
|
452
|
+
rootContainer: createLinkGraphics(args),
|
|
453
|
+
renderDefault: false
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
const dateColumnCreator = (data, innerColumnControl) => {
|
|
459
|
+
const baseColumn = baseCreator(data);
|
|
460
|
+
return {
|
|
461
|
+
...baseColumn,
|
|
462
|
+
fmt: data.default?.format,
|
|
463
|
+
customLayout: (args) => {
|
|
464
|
+
return {
|
|
465
|
+
rootContainer: createDateGraphics(args),
|
|
466
|
+
renderDefault: false
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
};
|
|
471
|
+
const timeLenColumnCreator = (data, innerColumnControl) => {
|
|
472
|
+
const baseColumn = baseCreator(data);
|
|
473
|
+
return {
|
|
474
|
+
...baseColumn,
|
|
475
|
+
// NOTE: editor 为 number 输入整型
|
|
476
|
+
fmt: "integer",
|
|
477
|
+
customLayout: (args) => {
|
|
478
|
+
return {
|
|
479
|
+
rootContainer: createTimeLenGraphics(args),
|
|
480
|
+
renderDefault: false
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
};
|
|
485
|
+
const userColumnCreator = (data, innerColumnControl) => {
|
|
486
|
+
const baseColumn = baseCreator(data);
|
|
487
|
+
return {
|
|
488
|
+
...baseColumn,
|
|
489
|
+
customLayout: (args) => {
|
|
490
|
+
return {
|
|
491
|
+
rootContainer: createPeopleGraphics(args),
|
|
492
|
+
renderDefault: false
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
};
|
|
497
|
+
const tagColumnCreator = (data, innerColumnControl) => {
|
|
498
|
+
const baseColumn = baseCreator(data);
|
|
499
|
+
return {
|
|
500
|
+
...baseColumn,
|
|
501
|
+
customLayout: (args) => {
|
|
502
|
+
return {
|
|
503
|
+
rootContainer: createTagGraphic(args),
|
|
504
|
+
renderDefault: false
|
|
505
|
+
};
|
|
506
|
+
}
|
|
507
|
+
};
|
|
508
|
+
};
|
|
509
|
+
const jsonColumnCreator = (data, innerColumnControl) => {
|
|
510
|
+
const baseColumn = baseCreator(data);
|
|
511
|
+
return {
|
|
512
|
+
...baseColumn,
|
|
513
|
+
customLayout: (args) => {
|
|
514
|
+
return {
|
|
515
|
+
rootContainer: createJsonGraphics(args),
|
|
516
|
+
renderDefault: false
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
};
|
|
521
|
+
const dropdownColumnCreator = (data, innerColumnControl) => {
|
|
522
|
+
const baseColumn = baseCreator(data);
|
|
523
|
+
return {
|
|
524
|
+
...baseColumn,
|
|
525
|
+
dragHeader: false,
|
|
526
|
+
customLayout: (args) => {
|
|
527
|
+
return {
|
|
528
|
+
rootContainer: createMoreGraphics(args),
|
|
529
|
+
renderDefault: false
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
};
|
|
534
|
+
const checkboxColumnCreator = (data, innerColumnControl) => {
|
|
535
|
+
const baseColumn = baseCreator(data);
|
|
536
|
+
return {
|
|
537
|
+
...baseColumn,
|
|
538
|
+
lock: true,
|
|
539
|
+
width: 40,
|
|
540
|
+
minWidth: 40,
|
|
541
|
+
headerType: "checkbox",
|
|
542
|
+
//指定表头单元格显示为复选框
|
|
543
|
+
cellType: "checkbox",
|
|
544
|
+
//指定body单元格显示为复选框
|
|
545
|
+
field: INNER_TABLE_COLUMN_KEY_CHECKBOX,
|
|
546
|
+
disable: false,
|
|
547
|
+
disableColumnResize: true,
|
|
548
|
+
disableSelect: true,
|
|
549
|
+
disableHeaderSelect: true,
|
|
550
|
+
dragHeader: false,
|
|
551
|
+
headerStyle: {
|
|
552
|
+
borderLineWidth: [1, 0, 1, 1],
|
|
553
|
+
// 上右下左的边框宽度
|
|
554
|
+
marked: false
|
|
555
|
+
},
|
|
556
|
+
style: {
|
|
557
|
+
borderLineWidth: [1, 0, 1, 1],
|
|
558
|
+
// 上右下左的边框宽度
|
|
559
|
+
marked: false
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
};
|
|
563
|
+
const plusColumnCreator = (data, innerColumnControl) => {
|
|
564
|
+
const baseColumn = baseCreator(data);
|
|
565
|
+
return {
|
|
566
|
+
...baseColumn,
|
|
567
|
+
dragHeader: false,
|
|
568
|
+
field: INNER_TABLE_COLUMN_KEY_PLUS,
|
|
569
|
+
width: 50,
|
|
570
|
+
disable: true,
|
|
571
|
+
disableHover: true,
|
|
572
|
+
disableHeaderSelect: true,
|
|
573
|
+
disableColumnResize: true,
|
|
574
|
+
disableSelect: true,
|
|
575
|
+
headerCustomLayout: (args) => {
|
|
576
|
+
return {
|
|
577
|
+
rootContainer: createPlusHeaderGraphics(args),
|
|
578
|
+
renderDefault: false
|
|
579
|
+
};
|
|
580
|
+
},
|
|
581
|
+
style: {
|
|
582
|
+
borderLineWidth: ({ row, table }) => {
|
|
583
|
+
if (row === 1) return [1, 1, 0, 1];
|
|
584
|
+
if (row === table.rowCount - 1) return [0, 1, 1, 1];
|
|
585
|
+
return [0, 1, 0, 1];
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
};
|
|
589
|
+
};
|
|
590
|
+
const moreColumnCreator = (data, innerColumnControl) => {
|
|
591
|
+
const baseColumn = baseCreator(data);
|
|
592
|
+
return {
|
|
593
|
+
...baseColumn,
|
|
594
|
+
field: "more",
|
|
595
|
+
title: "\u66F4\u591A",
|
|
596
|
+
dragHeader: false,
|
|
597
|
+
customLayout: (args) => {
|
|
598
|
+
return {
|
|
599
|
+
rootContainer: createMoreGraphics(args),
|
|
600
|
+
renderDefault: false
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
};
|
|
605
|
+
const mainColumnCreator = (data, innerColumnControl) => {
|
|
606
|
+
const baseColumn = baseCreator(data);
|
|
607
|
+
const mainKeyColumn = {
|
|
608
|
+
...baseColumn,
|
|
609
|
+
tool: 28,
|
|
610
|
+
lock: true,
|
|
611
|
+
field: data.id,
|
|
612
|
+
dragHeader: false,
|
|
613
|
+
title: data.label,
|
|
614
|
+
width: 200,
|
|
615
|
+
headerStyle: {
|
|
616
|
+
borderLineWidth: [1, 1, 1, 0]
|
|
617
|
+
// 上右下左的边框宽度
|
|
618
|
+
},
|
|
619
|
+
style: {
|
|
620
|
+
borderLineWidth: [1, 1, 1, 0]
|
|
621
|
+
// 上右下左的边框宽度
|
|
622
|
+
},
|
|
623
|
+
headerCustomLayout: (args) => {
|
|
624
|
+
return {
|
|
625
|
+
rootContainer: createHeaderGraphics(28, args),
|
|
626
|
+
renderDefault: false
|
|
627
|
+
};
|
|
628
|
+
},
|
|
629
|
+
customLayout: (args) => {
|
|
630
|
+
return {
|
|
631
|
+
rootContainer: createMainColumnCellGraphics(args),
|
|
632
|
+
renderDefault: false
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
};
|
|
636
|
+
return mainKeyColumn;
|
|
637
|
+
};
|
|
638
|
+
const createColumns = (data, innerColumnControl) => {
|
|
639
|
+
const creator = creatorMap.get(data.type) ?? baseCreator;
|
|
640
|
+
return lodash.castArray(creator(data, innerColumnControl));
|
|
641
|
+
};
|
|
642
|
+
const creatorMap = /* @__PURE__ */ new Map([
|
|
643
|
+
[28, textColumnCreator],
|
|
644
|
+
[29, simpleSelectColumnCreator],
|
|
645
|
+
[30, multiSelectColumnCreator],
|
|
646
|
+
[31, numberColumnCreator],
|
|
647
|
+
[36, dateColumnCreator],
|
|
648
|
+
[33, linkColumnCreator],
|
|
649
|
+
[32, attachmentColumnCreator],
|
|
650
|
+
[37, timeLenColumnCreator],
|
|
651
|
+
[38, userColumnCreator],
|
|
652
|
+
[35, tagColumnCreator],
|
|
653
|
+
[34, jsonColumnCreator],
|
|
654
|
+
[39, dropdownColumnCreator],
|
|
655
|
+
/** 表格内置列 */
|
|
656
|
+
[-1, checkboxColumnCreator],
|
|
657
|
+
[-3, plusColumnCreator],
|
|
658
|
+
[-2, moreColumnCreator],
|
|
659
|
+
[-4, mainColumnCreator]
|
|
660
|
+
]);
|
|
661
|
+
|
|
662
|
+
const adaptColumnStructure = (originalColumns, innerColumnControl) => {
|
|
663
|
+
const hasMainColumn = innerColumnControl.main;
|
|
664
|
+
const columnFeedbacksErrors = [];
|
|
665
|
+
const adaptedColumns = originalColumns.map((column, colIndex) => {
|
|
666
|
+
if (column.feedbacks && column.feedbacks.length > 0) {
|
|
667
|
+
columnFeedbacksErrors.push({
|
|
668
|
+
type: "column",
|
|
669
|
+
col: getColFromColIndex(colIndex, innerColumnControl),
|
|
670
|
+
info: column.feedbacks
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
return createColumns(
|
|
674
|
+
{
|
|
675
|
+
...column,
|
|
676
|
+
// TODO: any
|
|
677
|
+
type: colIndex === 0 && hasMainColumn && [28, 31].includes(column.type) ? -4 : column.type
|
|
678
|
+
},
|
|
679
|
+
innerColumnControl
|
|
680
|
+
);
|
|
681
|
+
}).flat();
|
|
682
|
+
if (innerColumnControl.checkbox) {
|
|
683
|
+
adaptedColumns.unshift(
|
|
684
|
+
checkboxColumnCreator(
|
|
685
|
+
{
|
|
686
|
+
type: -1,
|
|
687
|
+
id: INNER_TABLE_COLUMN_KEY_CHECKBOX,
|
|
688
|
+
label: ""
|
|
689
|
+
})
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
if (innerColumnControl.plus)
|
|
693
|
+
adaptedColumns.push(
|
|
694
|
+
plusColumnCreator(
|
|
695
|
+
{
|
|
696
|
+
type: -3,
|
|
697
|
+
id: INNER_TABLE_COLUMN_KEY_PLUS,
|
|
698
|
+
label: ""
|
|
699
|
+
})
|
|
700
|
+
);
|
|
701
|
+
return {
|
|
702
|
+
columns: adaptedColumns,
|
|
703
|
+
feedbacksHighlight: {
|
|
704
|
+
[core.CUSTOM_CELL_STYLE_FEEDBACK_ERROR]: [...columnFeedbacksErrors]
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
};
|
|
708
|
+
|
|
709
|
+
const adaptRecordStructure = (record) => {
|
|
710
|
+
const { id, cells } = record;
|
|
711
|
+
const cellValues = Object.entries(cells).map(([columnId, data]) => {
|
|
712
|
+
const { id: id2, value, loading, feedbacks } = data ?? {};
|
|
713
|
+
const realId = !id2 ? columnId : id2;
|
|
714
|
+
return [columnId, { id: realId, value, loading, feedbacks }];
|
|
715
|
+
});
|
|
716
|
+
return {
|
|
717
|
+
[INNER_TABLE_RECORD_ID_KEY]: id,
|
|
718
|
+
...Object.fromEntries(cellValues)
|
|
719
|
+
};
|
|
720
|
+
};
|
|
721
|
+
const revertRecordStructure = (tableRecord) => {
|
|
722
|
+
const { [INNER_TABLE_RECORD_ID_KEY]: recordId, ...cellsMap } = tableRecord;
|
|
723
|
+
const cells = Object.fromEntries(
|
|
724
|
+
Object.entries(cellsMap).map(([columnId, cellData]) => {
|
|
725
|
+
const { id, value, loading, feedbacks } = cellData ?? {};
|
|
726
|
+
const realId = !id ? columnId : id;
|
|
727
|
+
return [
|
|
728
|
+
columnId,
|
|
729
|
+
{
|
|
730
|
+
id: realId,
|
|
731
|
+
value,
|
|
732
|
+
loading,
|
|
733
|
+
feedbacks
|
|
734
|
+
}
|
|
735
|
+
];
|
|
736
|
+
})
|
|
737
|
+
);
|
|
738
|
+
return {
|
|
739
|
+
id: recordId,
|
|
740
|
+
cells
|
|
741
|
+
};
|
|
742
|
+
};
|
|
743
|
+
const adaptRecordsStructure = (records, adapterColumns, innerColumnControl) => {
|
|
744
|
+
const fields = adapterColumns.map((column) => column.field);
|
|
745
|
+
const rowFeedbacksErrors = [];
|
|
746
|
+
const cellFeedbacksErrors = [];
|
|
747
|
+
const rows = records.map((record, rowIndex) => {
|
|
748
|
+
const { id, feedbacks, cells } = record;
|
|
749
|
+
const cellValues = Object.entries(cells).map(([columnId, { id: id2, value, loading, feedbacks: feedbacks2 }]) => {
|
|
750
|
+
if (feedbacks2 && feedbacks2.length) {
|
|
751
|
+
cellFeedbacksErrors.push({
|
|
752
|
+
type: "cell",
|
|
753
|
+
col: fields.indexOf(columnId),
|
|
754
|
+
row: getRowFromRowIndex(rowIndex),
|
|
755
|
+
info: feedbacks2 ?? []
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
const realId = !id2 ? columnId : id2;
|
|
759
|
+
return [columnId, { id: realId, value, loading, feedbacks: feedbacks2 }];
|
|
760
|
+
});
|
|
761
|
+
if (feedbacks && feedbacks.length) {
|
|
762
|
+
rowFeedbacksErrors.push({
|
|
763
|
+
type: "row",
|
|
764
|
+
col: getColFromColIndex(0, innerColumnControl),
|
|
765
|
+
row: getRowFromRowIndex(rowIndex),
|
|
766
|
+
info: feedbacks ?? []
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
return {
|
|
770
|
+
[INNER_TABLE_RECORD_ID_KEY]: id,
|
|
771
|
+
...Object.fromEntries(cellValues)
|
|
772
|
+
};
|
|
773
|
+
});
|
|
774
|
+
return {
|
|
775
|
+
records: rows,
|
|
776
|
+
feedbacksHighlight: {
|
|
777
|
+
[core.CUSTOM_CELL_STYLE_FEEDBACK_ERROR]: [...cellFeedbacksErrors, ...rowFeedbacksErrors]
|
|
778
|
+
}
|
|
779
|
+
};
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
const { setDateEditorData, getDateEditorData, useDateEditorData } = store.createAtomStore(
|
|
783
|
+
"dateEditorData",
|
|
784
|
+
jotai.atom()
|
|
785
|
+
);
|
|
786
|
+
const { setDateEditorValue, getDateEditorValue, useDateEditorValue } = store.createAtomStore(
|
|
787
|
+
"dateEditorValue",
|
|
788
|
+
jotai.atom()
|
|
789
|
+
);
|
|
790
|
+
const initDateEditorTool = (value) => {
|
|
791
|
+
const { initialValue } = value;
|
|
792
|
+
setDateEditorData(value);
|
|
793
|
+
setDateEditorValue(initialValue);
|
|
794
|
+
};
|
|
795
|
+
const clearDateEditorTool = () => {
|
|
796
|
+
setDateEditorData(void 0);
|
|
797
|
+
setDateEditorValue(void 0);
|
|
798
|
+
};
|
|
799
|
+
|
|
800
|
+
const { getActiveEditorTable, setActiveEditorTable, useActiveEditorTable } = store.createAtomStore(
|
|
801
|
+
"activeEditorTable",
|
|
802
|
+
jotai.atom(
|
|
803
|
+
(get) => {
|
|
804
|
+
const map = get(editorTableStoreAtom);
|
|
805
|
+
const activeId = get(activeTableIdAtom);
|
|
806
|
+
if (!activeId) throw new Error("activeTableId is empty");
|
|
807
|
+
return map.get(activeId);
|
|
808
|
+
},
|
|
809
|
+
() => {
|
|
810
|
+
throw new Error("activeEditorTable is empty");
|
|
811
|
+
}
|
|
812
|
+
)
|
|
813
|
+
);
|
|
814
|
+
const { setActiveTableId, getActiveTableId, useActiveTableId, activeTableIdAtom } = store.createAtomStore(
|
|
815
|
+
"activeTableId",
|
|
816
|
+
jotai.atom()
|
|
817
|
+
);
|
|
818
|
+
const { setEditorTableStore, getEditorTableStore, useEditorTableStore, editorTableStoreAtom } = store.createAtomStore(
|
|
819
|
+
"editorTableStore",
|
|
820
|
+
jotai.atom(/* @__PURE__ */ new Map())
|
|
821
|
+
);
|
|
822
|
+
|
|
823
|
+
const dateProcess = (data, dateFormat) => {
|
|
824
|
+
const originalFullDayjs = dayjs(data.initialValue);
|
|
825
|
+
const isSpecialFormat = dateFormat === "MM-DD" || dateFormat.includes("MM") && dateFormat.includes("DD") && !dateFormat.includes("YYYY") || dateFormat === "MM/DD/YYYY" || dateFormat === "DD/MM/YYYY";
|
|
826
|
+
if (isSpecialFormat) {
|
|
827
|
+
return originalFullDayjs.isValid() ? originalFullDayjs : dayjs();
|
|
828
|
+
} else {
|
|
829
|
+
return dayjs(data.initialValue, dateFormat).isValid() ? dayjs(data.initialValue, dateFormat) : dayjs();
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
|
|
833
|
+
const DateSelect = () => {
|
|
834
|
+
const data = useDateEditorData();
|
|
835
|
+
if (!data) return null;
|
|
836
|
+
const tableEditor = getActiveEditorTable();
|
|
837
|
+
let dateFormat = "";
|
|
838
|
+
const column = tableEditor?.getColumnDefine(data?.cell?.col);
|
|
839
|
+
if (column.fmt) {
|
|
840
|
+
dateFormat = column.fmt || "YYYY/MM/DD HH:mm";
|
|
841
|
+
}
|
|
842
|
+
setDateEditorValue(data.initialValue);
|
|
843
|
+
const validDayjs = dateProcess(data, dateFormat);
|
|
844
|
+
const TZ_SUFFIX = " (GMT+8)";
|
|
845
|
+
const hasTimezone = dateFormat.endsWith(TZ_SUFFIX);
|
|
846
|
+
const pureFormat = hasTimezone ? dateFormat.replace(TZ_SUFFIX, "") : dateFormat;
|
|
847
|
+
const hasTime = /(HH|hh):mm(:ss)?/.test(pureFormat);
|
|
848
|
+
const formatDateDisplay = (date) => {
|
|
849
|
+
if (!date) return "";
|
|
850
|
+
const baseText = date.format(pureFormat);
|
|
851
|
+
return hasTimezone ? `${baseText} (GMT+8)` : baseText;
|
|
852
|
+
};
|
|
853
|
+
return /* @__PURE__ */ React.createElement(
|
|
854
|
+
antd.Popover,
|
|
855
|
+
{
|
|
856
|
+
trigger: "click",
|
|
857
|
+
className: "popoverDate",
|
|
858
|
+
arrow: false,
|
|
859
|
+
open: true,
|
|
860
|
+
align: {
|
|
861
|
+
points: ["tl", "bl"],
|
|
862
|
+
offset: [0, 10]
|
|
863
|
+
}
|
|
864
|
+
},
|
|
865
|
+
/* @__PURE__ */ React.createElement(
|
|
866
|
+
antd.DatePicker,
|
|
867
|
+
{
|
|
868
|
+
defaultValue: validDayjs,
|
|
869
|
+
format: formatDateDisplay,
|
|
870
|
+
defaultOpen: true,
|
|
871
|
+
showTime: hasTime ? { format: pureFormat } : false,
|
|
872
|
+
allowClear: false,
|
|
873
|
+
onChange: (value) => {
|
|
874
|
+
let targetDayjs;
|
|
875
|
+
if (Array.isArray(value)) {
|
|
876
|
+
targetDayjs = value[0] || null;
|
|
877
|
+
} else {
|
|
878
|
+
targetDayjs = value;
|
|
879
|
+
}
|
|
880
|
+
if (!targetDayjs) return;
|
|
881
|
+
const finalFormat = hasTime ? "YYYY-MM-DD HH:mm:ss" : "YYYY-MM-DD";
|
|
882
|
+
const finalValue = targetDayjs.format(finalFormat);
|
|
883
|
+
if (!hasTime) {
|
|
884
|
+
if (data.initialValue?.value) {
|
|
885
|
+
const originalDayjs = dayjs(data.initialValue.value);
|
|
886
|
+
const hour = originalDayjs.hour();
|
|
887
|
+
const minute = originalDayjs.minute();
|
|
888
|
+
const second = originalDayjs.second();
|
|
889
|
+
const newDayjs = targetDayjs.hour(hour).minute(minute).second(second);
|
|
890
|
+
setDateEditorValue(newDayjs.format("YYYY-MM-DD HH:mm:ss"));
|
|
891
|
+
} else {
|
|
892
|
+
setDateEditorValue(targetDayjs.hour(0).minute(0).second(0).format("YYYY-MM-DD HH:mm:ss"));
|
|
893
|
+
}
|
|
894
|
+
} else {
|
|
895
|
+
setDateEditorValue(finalValue);
|
|
896
|
+
}
|
|
897
|
+
data.endEdit();
|
|
898
|
+
},
|
|
899
|
+
style: {
|
|
900
|
+
position: "absolute",
|
|
901
|
+
left: data.cell.position.x,
|
|
902
|
+
top: data.cell.position.y,
|
|
903
|
+
width: data.cell.width,
|
|
904
|
+
height: data.cell.height
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
)
|
|
908
|
+
);
|
|
909
|
+
};
|
|
910
|
+
|
|
911
|
+
const { setJsonEditorData, getJsonEditorData, useJsonEditorData } = store.createAtomStore(
|
|
912
|
+
"jsonEditorData",
|
|
913
|
+
jotai.atom()
|
|
914
|
+
);
|
|
915
|
+
const { setJsonEditorValue, getJsonEditorValue, useJsonEditorValue } = store.createAtomStore(
|
|
916
|
+
"jsonEditorValue",
|
|
917
|
+
jotai.atom()
|
|
918
|
+
);
|
|
919
|
+
const initJsonEditorTool = (value) => {
|
|
920
|
+
const { initialValue } = value;
|
|
921
|
+
setJsonEditorData(value);
|
|
922
|
+
setJsonEditorValue(initialValue);
|
|
923
|
+
};
|
|
924
|
+
const clearJsonEditorTool = () => {
|
|
925
|
+
setJsonEditorData(void 0);
|
|
926
|
+
setJsonEditorValue(void 0);
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
const TableJsonEditor = () => {
|
|
930
|
+
const jsonEditorData = useJsonEditorData();
|
|
931
|
+
const jsonEditorValue = useJsonEditorValue();
|
|
932
|
+
const clcHeight = React.useMemo(() => {
|
|
933
|
+
const lineCount = (jsonEditorValue ?? "").split("\n").length;
|
|
934
|
+
return lineCount * 20;
|
|
935
|
+
}, [jsonEditorValue]);
|
|
936
|
+
if (!jsonEditorData) return null;
|
|
937
|
+
const editor = getActiveEditorTable();
|
|
938
|
+
if (!editor) throw new Error("TableJsonEditor: editor is null");
|
|
939
|
+
const { cell, table } = jsonEditorData;
|
|
940
|
+
const { position, width } = cell;
|
|
941
|
+
const cellStyle = table._getCellStyle(cell.col, cell.row);
|
|
942
|
+
const fontSize = getProp("fontSize", cellStyle, cell.col, cell.row, table);
|
|
943
|
+
return /* @__PURE__ */ React.createElement(
|
|
944
|
+
"div",
|
|
945
|
+
{
|
|
946
|
+
className: "json-editor-modal-container",
|
|
947
|
+
style: {
|
|
948
|
+
fontSize,
|
|
949
|
+
width,
|
|
950
|
+
height: clcHeight,
|
|
951
|
+
minHeight: 100,
|
|
952
|
+
maxHeight: 300,
|
|
953
|
+
position: "absolute",
|
|
954
|
+
top: position.y,
|
|
955
|
+
left: position.x
|
|
956
|
+
}
|
|
957
|
+
},
|
|
958
|
+
/* @__PURE__ */ React.createElement(gridLayout.JsonEditor, { value: jsonEditorData.initialValue, onChange: (value) => setJsonEditorValue(value), dark: false })
|
|
959
|
+
);
|
|
960
|
+
};
|
|
961
|
+
|
|
962
|
+
const { setLinkEditorData, getLinkEditorData, useLinkEditorData } = store.createAtomStore(
|
|
963
|
+
"linkEditorData",
|
|
964
|
+
jotai.atom()
|
|
965
|
+
);
|
|
966
|
+
const { setLinkEditorValue, getLinkEditorValue, useLinkEditorValue } = store.createAtomStore(
|
|
967
|
+
"linkEditorValue",
|
|
968
|
+
jotai.atom()
|
|
969
|
+
);
|
|
970
|
+
const initLinkEditorTool = (value) => {
|
|
971
|
+
const { initialValue } = value;
|
|
972
|
+
setLinkEditorData(value);
|
|
973
|
+
setLinkEditorValue(initialValue);
|
|
974
|
+
};
|
|
975
|
+
const clearLinkEditorTool = () => {
|
|
976
|
+
setLinkEditorData(void 0);
|
|
977
|
+
setLinkEditorValue(void 0);
|
|
978
|
+
};
|
|
979
|
+
|
|
980
|
+
const LinkEditor = ({}) => {
|
|
981
|
+
const [popContentVisible, setPopContentVisible] = React.useState(false);
|
|
982
|
+
const data = useLinkEditorData();
|
|
983
|
+
const linkValue = useLinkEditorValue();
|
|
984
|
+
const cancel = React.useCallback(() => {
|
|
985
|
+
setLinkEditorValue({ ...data?.initialValue ?? {} });
|
|
986
|
+
data?.endEdit();
|
|
987
|
+
}, [data]);
|
|
988
|
+
const confirm = React.useCallback(() => data?.endEdit(), [data]);
|
|
989
|
+
if (!data) return null;
|
|
990
|
+
return /* @__PURE__ */ React.createElement(
|
|
991
|
+
antd.Popover,
|
|
992
|
+
{
|
|
993
|
+
open: popContentVisible,
|
|
994
|
+
content: /* @__PURE__ */ React.createElement(antd.Form, { className: "link-editor-form", layout: "vertical", style: { width: 300 } }, /* @__PURE__ */ React.createElement(antd.Form.Item, { label: "\u6587\u672C", className: "link-editor-form-item" }, /* @__PURE__ */ React.createElement(
|
|
995
|
+
antd.Input,
|
|
996
|
+
{
|
|
997
|
+
defaultValue: linkValue?.title ?? "",
|
|
998
|
+
onChange: (e) => setLinkEditorValue((v) => ({ ...v ?? {}, title: e.target.value }))
|
|
999
|
+
}
|
|
1000
|
+
)), /* @__PURE__ */ React.createElement(antd.Form.Item, { label: "\u8D85\u94FE\u63A5", className: "link-editor-form-item" }, /* @__PURE__ */ React.createElement(
|
|
1001
|
+
antd.Input,
|
|
1002
|
+
{
|
|
1003
|
+
defaultValue: linkValue?.url ?? "",
|
|
1004
|
+
onChange: (e) => setLinkEditorValue((v) => ({ ...v ?? {}, url: e.target.value }))
|
|
1005
|
+
}
|
|
1006
|
+
)), /* @__PURE__ */ React.createElement(antd.Flex, { justify: "flex-end" }, /* @__PURE__ */ React.createElement(antd.Space, null, /* @__PURE__ */ React.createElement(antd.Button, { onClick: cancel }, "\u53D6\u6D88"), /* @__PURE__ */ React.createElement(antd.Button, { type: "primary", onClick: confirm }, "\u786E\u5B9A")))),
|
|
1007
|
+
rootClassName: "link-editor-popover-root",
|
|
1008
|
+
className: "link-editor-popover",
|
|
1009
|
+
arrow: false,
|
|
1010
|
+
align: {
|
|
1011
|
+
points: ["tl", "bl"],
|
|
1012
|
+
// tl(top-left): 将【pop弹窗】左上角 与 Input bl(bottom-left) 左下角对齐
|
|
1013
|
+
offset: [0, 10]
|
|
1014
|
+
}
|
|
1015
|
+
},
|
|
1016
|
+
/* @__PURE__ */ React.createElement(
|
|
1017
|
+
antd.Flex,
|
|
1018
|
+
{
|
|
1019
|
+
style: {
|
|
1020
|
+
border: `2px solid ${core.COLOR_BORDER_SELECTION}`,
|
|
1021
|
+
backgroundColor: core.COLOR_BG_CELL,
|
|
1022
|
+
borderRadius: 0,
|
|
1023
|
+
position: "absolute",
|
|
1024
|
+
left: data.cell.position.x - 2,
|
|
1025
|
+
top: data.cell.position.y - 2,
|
|
1026
|
+
width: data.cell.width + 4,
|
|
1027
|
+
height: data.cell.height + 4
|
|
1028
|
+
},
|
|
1029
|
+
align: "center"
|
|
1030
|
+
},
|
|
1031
|
+
/* @__PURE__ */ React.createElement(
|
|
1032
|
+
antd.Input,
|
|
1033
|
+
{
|
|
1034
|
+
className: "link-editor-input",
|
|
1035
|
+
style: {
|
|
1036
|
+
color: core.COLOR_LINK,
|
|
1037
|
+
border: "unset",
|
|
1038
|
+
borderRadius: 0,
|
|
1039
|
+
height: data.cell.height - 2,
|
|
1040
|
+
boxSizing: "border-box"
|
|
1041
|
+
},
|
|
1042
|
+
defaultValue: linkValue?.title ?? "",
|
|
1043
|
+
onChange: (e) => setLinkEditorValue((v) => ({ ...v ?? {}, title: e.target.value })),
|
|
1044
|
+
onFocus: () => setPopContentVisible(false)
|
|
1045
|
+
}
|
|
1046
|
+
),
|
|
1047
|
+
/* @__PURE__ */ React.createElement(
|
|
1048
|
+
antd.Button,
|
|
1049
|
+
{
|
|
1050
|
+
type: "text",
|
|
1051
|
+
icon: /* @__PURE__ */ React.createElement(icons.LinkOutlined, null),
|
|
1052
|
+
style: {
|
|
1053
|
+
border: "unset",
|
|
1054
|
+
borderRadius: 0,
|
|
1055
|
+
height: data.cell.height - 2,
|
|
1056
|
+
boxSizing: "border-box"
|
|
1057
|
+
},
|
|
1058
|
+
onClick: () => setPopContentVisible(!popContentVisible)
|
|
1059
|
+
}
|
|
1060
|
+
)
|
|
1061
|
+
)
|
|
1062
|
+
);
|
|
1063
|
+
};
|
|
1064
|
+
|
|
1065
|
+
const { setNumEditorValue, getNumEditorValue, useNumEditorValue } = store.createAtomStore(
|
|
1066
|
+
"numEditorValue",
|
|
1067
|
+
jotai.atom()
|
|
1068
|
+
);
|
|
1069
|
+
const { setNumEditorData, getNumEditorData, useNumEditorData } = store.createAtomStore(
|
|
1070
|
+
"numEditorData",
|
|
1071
|
+
jotai.atom()
|
|
1072
|
+
);
|
|
1073
|
+
const initNumEditorTool = (data) => {
|
|
1074
|
+
setNumEditorData(data);
|
|
1075
|
+
setNumEditorValue(data.initialValue);
|
|
1076
|
+
};
|
|
1077
|
+
const clearNumEditorTool = () => {
|
|
1078
|
+
setNumEditorData(void 0);
|
|
1079
|
+
setNumEditorValue(void 0);
|
|
1080
|
+
};
|
|
1081
|
+
|
|
1082
|
+
const NumEditor = () => {
|
|
1083
|
+
const numEditorData = useNumEditorData();
|
|
1084
|
+
if (!numEditorData) return null;
|
|
1085
|
+
const { cell, table } = numEditorData;
|
|
1086
|
+
const { position, width, height } = cell;
|
|
1087
|
+
const cellStyle = table._getCellStyle(cell.col, cell.row);
|
|
1088
|
+
const fontSize = getProp("fontSize", cellStyle, cell.col, cell.row, table);
|
|
1089
|
+
const bgColor = getProp("bgColor", cellStyle, cell.col, cell.row, table);
|
|
1090
|
+
return /* @__PURE__ */ React.createElement(
|
|
1091
|
+
antd.InputNumber,
|
|
1092
|
+
{
|
|
1093
|
+
defaultValue: numEditorData.initialValue,
|
|
1094
|
+
onChange: (value) => setNumEditorValue(value),
|
|
1095
|
+
controls: false,
|
|
1096
|
+
className: "num-editor-input",
|
|
1097
|
+
style: {
|
|
1098
|
+
position: "absolute",
|
|
1099
|
+
left: position.x - 2,
|
|
1100
|
+
top: position.y - 2,
|
|
1101
|
+
width: width + 4,
|
|
1102
|
+
minHeight: height + 4,
|
|
1103
|
+
background: bgColor,
|
|
1104
|
+
border: "2px solid #0404ff",
|
|
1105
|
+
borderRadius: 0,
|
|
1106
|
+
fontSize,
|
|
1107
|
+
scrollbarWidth: "none"
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
);
|
|
1111
|
+
};
|
|
1112
|
+
|
|
1113
|
+
const { setSelectEditorData, getSelectEditorData, useSelectEditorData } = store.createAtomStore(
|
|
1114
|
+
"selectEditorData",
|
|
1115
|
+
jotai.atom(null)
|
|
1116
|
+
);
|
|
1117
|
+
const { setSelectEditorValue, getSelectEditorValue, useSelectEditorValue } = store.createAtomStore(
|
|
1118
|
+
"selectEditorValue",
|
|
1119
|
+
jotai.atom([])
|
|
1120
|
+
);
|
|
1121
|
+
const initSelectEditorTool = (value) => {
|
|
1122
|
+
const { initialValue } = value;
|
|
1123
|
+
setSelectEditorData(value);
|
|
1124
|
+
setSelectEditorValue(initialValue);
|
|
1125
|
+
};
|
|
1126
|
+
const clearSelectEditorTool = () => {
|
|
1127
|
+
setSelectEditorData(null);
|
|
1128
|
+
setSelectEditorValue([]);
|
|
1129
|
+
};
|
|
1130
|
+
|
|
1131
|
+
const TableChangeEvent = {
|
|
1132
|
+
"CELLS_UPDATE": "cells::update",
|
|
1133
|
+
"CELL_CLICK": "cell::click",
|
|
1134
|
+
"CELL_ATTACHMENT_PREVIEW": "cell::attachment::preview",
|
|
1135
|
+
"SELECT_OPTIONS_UPDATE": "select::options::update",
|
|
1136
|
+
"RECORD_OPEN_DETAIL_DRAWER": "record::open::detail::drawer",
|
|
1137
|
+
"RECORD_CHECKBOX_STATE_CHANGE": "record::checkbox::state::change",
|
|
1138
|
+
"COLUMN_WIDTH_UPDATE": "column::width::update",
|
|
1139
|
+
"COLUMN_DRAG_MOVE_END": "column::drag::move::end",
|
|
1140
|
+
"COLUMN_ADD_FROM_INNER_PLUS": "column::add::from::inner::plus"
|
|
1141
|
+
};
|
|
1142
|
+
|
|
1143
|
+
const EDIT_TABLE_CELL_DATA_COMMAND_ID = Symbol("EDIT_TABLE_CELL_DATA_COMMAND_ID");
|
|
1144
|
+
const EDIT_TABLE_CELL_DATA_COMMAND_LABEL = "\u7F16\u8F91\u8868\u683C\u5355\u5143\u683C\u6570\u636E\u901A\u7528\u547D\u4EE4";
|
|
1145
|
+
class EditTableCellDataCommand extends command.Command {
|
|
1146
|
+
constructor(editor, col, row, value, oldValue) {
|
|
1147
|
+
super();
|
|
1148
|
+
this.editor = editor;
|
|
1149
|
+
this.col = col;
|
|
1150
|
+
this.row = row;
|
|
1151
|
+
this.value = value;
|
|
1152
|
+
this.oldValue = oldValue;
|
|
1153
|
+
this.id = EDIT_TABLE_CELL_DATA_COMMAND_ID;
|
|
1154
|
+
this.label = EDIT_TABLE_CELL_DATA_COMMAND_LABEL;
|
|
1155
|
+
}
|
|
1156
|
+
get readonly() {
|
|
1157
|
+
const columnDefine = this.editor.getColumnDefine(this.col);
|
|
1158
|
+
return this.editor.lock || !!columnDefine?.lock;
|
|
1159
|
+
}
|
|
1160
|
+
execute(_props) {
|
|
1161
|
+
this.editor.updateCellData(this.col, this.row, this.value);
|
|
1162
|
+
const { columnId, recordId } = this.editor.getInteractiveCell(this.col, this.row);
|
|
1163
|
+
this.editor.dispatch("cells::update", {
|
|
1164
|
+
editor: this.editor,
|
|
1165
|
+
data: [
|
|
1166
|
+
{
|
|
1167
|
+
recordId,
|
|
1168
|
+
columnId,
|
|
1169
|
+
previous: this.oldValue,
|
|
1170
|
+
current: this.value
|
|
1171
|
+
}
|
|
1172
|
+
]
|
|
1173
|
+
});
|
|
1174
|
+
}
|
|
1175
|
+
undo(_props) {
|
|
1176
|
+
this.editor.updateCellData(this.col, this.row, this.oldValue);
|
|
1177
|
+
const { columnId, recordId } = this.editor.getInteractiveCell(this.col, this.row);
|
|
1178
|
+
this.editor.dispatch("cells::update", {
|
|
1179
|
+
editor: this.editor,
|
|
1180
|
+
data: [
|
|
1181
|
+
{
|
|
1182
|
+
recordId,
|
|
1183
|
+
columnId,
|
|
1184
|
+
previous: this.value,
|
|
1185
|
+
current: this.oldValue
|
|
1186
|
+
}
|
|
1187
|
+
]
|
|
1188
|
+
});
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
const EDIT_TABLE_CELL_DATA_FUNCTIONAL_COMMAND_ID = Symbol("EDIT_TABLE_CELL_DATA_FUNCTIONAL_COMMAND_ID");
|
|
1192
|
+
const EDIT_TABLE_CELL_DATA_FUNCTIONAL_COMMAND_LABEL = "\u7F16\u8F91\u8868\u683C\u5355\u5143\u683C\u6570\u636E\u901A\u7528\u51FD\u6570\u5F0F\u547D\u4EE4";
|
|
1193
|
+
class EditTableCellDataFunctionalCommand extends command.Command {
|
|
1194
|
+
constructor(table, fn) {
|
|
1195
|
+
super();
|
|
1196
|
+
this.table = table;
|
|
1197
|
+
this.fn = fn;
|
|
1198
|
+
this.id = EDIT_TABLE_CELL_DATA_FUNCTIONAL_COMMAND_ID;
|
|
1199
|
+
this.label = EDIT_TABLE_CELL_DATA_FUNCTIONAL_COMMAND_LABEL;
|
|
1200
|
+
}
|
|
1201
|
+
get readonly() {
|
|
1202
|
+
return this.table.lock;
|
|
1203
|
+
}
|
|
1204
|
+
execute(_props) {
|
|
1205
|
+
const { restore } = this.fn();
|
|
1206
|
+
this._restore = restore;
|
|
1207
|
+
}
|
|
1208
|
+
undo(_props) {
|
|
1209
|
+
if (!this._restore) {
|
|
1210
|
+
throw new Error(`[EditTableCellCommand id: ${this.id.toString()} label: ${this.label}] \u672A\u6307\u5B9A\u6062\u590D\u51FD\u6570`);
|
|
1211
|
+
}
|
|
1212
|
+
this._restore();
|
|
1213
|
+
this._restore = void 0;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
const updateSelectEditorCell = (col, row, value, oldValue) => {
|
|
1218
|
+
const commandManager = command.getCommandManager();
|
|
1219
|
+
const tableEditor = getActiveEditorTable();
|
|
1220
|
+
if (!commandManager) return;
|
|
1221
|
+
if (!tableEditor) return;
|
|
1222
|
+
command.startTransaction((command2) => command2 instanceof EditTableCellDataFunctionalCommand);
|
|
1223
|
+
const run = () => {
|
|
1224
|
+
const previous = tableEditor.getCellOriginValue(col, row);
|
|
1225
|
+
const current = { ...previous, value };
|
|
1226
|
+
tableEditor.updateCellData(col, row, current);
|
|
1227
|
+
const position = tableEditor.getInteractiveCell(col, row);
|
|
1228
|
+
tableEditor.dispatch("cells::update", {
|
|
1229
|
+
editor: tableEditor,
|
|
1230
|
+
data: [
|
|
1231
|
+
{
|
|
1232
|
+
previous,
|
|
1233
|
+
current,
|
|
1234
|
+
...position
|
|
1235
|
+
}
|
|
1236
|
+
]
|
|
1237
|
+
});
|
|
1238
|
+
const curData = getSelectEditorData();
|
|
1239
|
+
if (curData && curData.cell.col === col && curData.cell.row === row) {
|
|
1240
|
+
setSelectEditorValue(value);
|
|
1241
|
+
}
|
|
1242
|
+
return {
|
|
1243
|
+
restore: () => {
|
|
1244
|
+
const curData2 = getSelectEditorData();
|
|
1245
|
+
tableEditor.updateCellData(col, row, previous);
|
|
1246
|
+
tableEditor.dispatch("cells::update", {
|
|
1247
|
+
editor: tableEditor,
|
|
1248
|
+
data: [
|
|
1249
|
+
{
|
|
1250
|
+
previous: current,
|
|
1251
|
+
current: previous,
|
|
1252
|
+
...position
|
|
1253
|
+
}
|
|
1254
|
+
]
|
|
1255
|
+
});
|
|
1256
|
+
if (!curData2) return;
|
|
1257
|
+
if (curData2.cell.col !== col || curData2.cell.row !== row) return;
|
|
1258
|
+
setSelectEditorValue(oldValue);
|
|
1259
|
+
}
|
|
1260
|
+
};
|
|
1261
|
+
};
|
|
1262
|
+
const command$1 = new EditTableCellDataFunctionalCommand(tableEditor, run);
|
|
1263
|
+
commandManager.execute(command$1);
|
|
1264
|
+
command.stopTransaction();
|
|
1265
|
+
};
|
|
1266
|
+
|
|
1267
|
+
const SelectEditor = ({
|
|
1268
|
+
listHeight = 300,
|
|
1269
|
+
itemHeight = 32,
|
|
1270
|
+
emptyText = "\u6682\u65E0\u6570\u636E",
|
|
1271
|
+
multiple = true
|
|
1272
|
+
}) => {
|
|
1273
|
+
const data = useSelectEditorData();
|
|
1274
|
+
const table = useActiveEditorTable();
|
|
1275
|
+
if (!data) throw new Error("SelectEditorData is null in SelectEditor");
|
|
1276
|
+
if (!table) throw new Error("Table is null in SelectEditor");
|
|
1277
|
+
const editValue = useSelectEditorValue();
|
|
1278
|
+
const updateOption = (option) => {
|
|
1279
|
+
setSelectEditorData((prev) => {
|
|
1280
|
+
if (!prev) {
|
|
1281
|
+
return prev;
|
|
1282
|
+
}
|
|
1283
|
+
const newOptions = prev.options.map((opt) => {
|
|
1284
|
+
if (opt.value === option.value) {
|
|
1285
|
+
return { ...opt, label: option.label, color: option.color || opt.color };
|
|
1286
|
+
}
|
|
1287
|
+
return opt;
|
|
1288
|
+
});
|
|
1289
|
+
const col = data.cell.col;
|
|
1290
|
+
table.updateColumn(col, { options: newOptions });
|
|
1291
|
+
table.dispatch("select::options::update", {
|
|
1292
|
+
editor: table,
|
|
1293
|
+
columnId: String(table.getColumnDefine(data.cell.col)?.field || ""),
|
|
1294
|
+
options: newOptions
|
|
1295
|
+
});
|
|
1296
|
+
return { ...prev, options: newOptions };
|
|
1297
|
+
});
|
|
1298
|
+
setSelectEditorValue((prev) => {
|
|
1299
|
+
if (!prev) {
|
|
1300
|
+
return prev;
|
|
1301
|
+
}
|
|
1302
|
+
return prev.map((item) => item.value === option.value ? option : item);
|
|
1303
|
+
});
|
|
1304
|
+
};
|
|
1305
|
+
const createOption = async (option) => {
|
|
1306
|
+
const column = table.getColumnDefine(data.cell.col);
|
|
1307
|
+
if (!column) throw new Error("SelectEditor createOption column is null");
|
|
1308
|
+
if (column.request) option = await column.request(option).catch(() => option);
|
|
1309
|
+
setSelectEditorData((prev) => {
|
|
1310
|
+
if (!prev) return prev;
|
|
1311
|
+
const col = data.cell.col;
|
|
1312
|
+
table.updateColumn(col, { options: [...prev.options, option] });
|
|
1313
|
+
table.dispatch("select::options::update", {
|
|
1314
|
+
editor: table,
|
|
1315
|
+
columnId: String(table.getColumnDefine(data.cell.col)?.field || ""),
|
|
1316
|
+
options: [...prev.options, option]
|
|
1317
|
+
});
|
|
1318
|
+
return { ...prev, options: [...prev.options, option] };
|
|
1319
|
+
});
|
|
1320
|
+
return option;
|
|
1321
|
+
};
|
|
1322
|
+
const selectOption = (option) => {
|
|
1323
|
+
const newEditValue = editValue || [];
|
|
1324
|
+
if (multiple) {
|
|
1325
|
+
const newSelected = newEditValue.map((item) => item.value).includes(option.value) ? newEditValue : [...newEditValue, option];
|
|
1326
|
+
updateSelectEditorCell(data.cell.col, data.cell.row, newSelected, newEditValue);
|
|
1327
|
+
} else {
|
|
1328
|
+
updateSelectEditorCell(data.cell.col, data.cell.row, [option], newEditValue);
|
|
1329
|
+
}
|
|
1330
|
+
};
|
|
1331
|
+
const deselectOption = (option) => {
|
|
1332
|
+
const newEditValue = editValue || [];
|
|
1333
|
+
const filterValue = newEditValue.filter((item) => item.value !== option.value);
|
|
1334
|
+
updateSelectEditorCell(data.cell.col, data.cell.row, filterValue, newEditValue);
|
|
1335
|
+
};
|
|
1336
|
+
const handleChange = (value) => {
|
|
1337
|
+
setSelectEditorValue(value);
|
|
1338
|
+
};
|
|
1339
|
+
return /* @__PURE__ */ React.createElement(
|
|
1340
|
+
ui.Select,
|
|
1341
|
+
{
|
|
1342
|
+
listHeight,
|
|
1343
|
+
itemHeight,
|
|
1344
|
+
emptyText,
|
|
1345
|
+
multiple,
|
|
1346
|
+
options: data.options,
|
|
1347
|
+
value: editValue || [],
|
|
1348
|
+
onChange: handleChange,
|
|
1349
|
+
onOptionChange: updateOption,
|
|
1350
|
+
onOptionCreate: createOption,
|
|
1351
|
+
onSelect: selectOption,
|
|
1352
|
+
onDeselect: deselectOption,
|
|
1353
|
+
tagAreaStyle: {
|
|
1354
|
+
position: "absolute",
|
|
1355
|
+
left: data.cell.position.x - 2,
|
|
1356
|
+
top: data.cell.position.y - 2,
|
|
1357
|
+
width: data.cell.width + 4,
|
|
1358
|
+
minHeight: data.cell.height + 4,
|
|
1359
|
+
border: `2px solid ${core.COLOR_BORDER_SELECTION}`,
|
|
1360
|
+
backgroundColor: core.COLOR_BG_CELL
|
|
1361
|
+
},
|
|
1362
|
+
width: data.cell.width + 4,
|
|
1363
|
+
tagAreaHeight: data.cell.height,
|
|
1364
|
+
showDownIcon: true
|
|
1365
|
+
}
|
|
1366
|
+
);
|
|
1367
|
+
};
|
|
1368
|
+
|
|
1369
|
+
const TableSelectEditor = () => {
|
|
1370
|
+
const data = useSelectEditorData();
|
|
1371
|
+
if (!data) {
|
|
1372
|
+
return null;
|
|
1373
|
+
}
|
|
1374
|
+
return /* @__PURE__ */ React.createElement(SelectEditor, { multiple: data.isMultiple });
|
|
1375
|
+
};
|
|
1376
|
+
|
|
1377
|
+
const { setTextEditorValue, getTextEditorValue, useTextEditorValue } = store.createAtomStore(
|
|
1378
|
+
"textEditorValue",
|
|
1379
|
+
jotai.atom()
|
|
1380
|
+
);
|
|
1381
|
+
const { setTextEditorData, getTextEditorData, useTextEditorData } = store.createAtomStore(
|
|
1382
|
+
"textEditorData",
|
|
1383
|
+
jotai.atom()
|
|
1384
|
+
);
|
|
1385
|
+
const initTextEditorTool = (data) => {
|
|
1386
|
+
setTextEditorData(data);
|
|
1387
|
+
setTextEditorValue(data.initialValue);
|
|
1388
|
+
};
|
|
1389
|
+
const clearTextEditorTool = () => {
|
|
1390
|
+
setTextEditorData(void 0);
|
|
1391
|
+
setTextEditorValue(void 0);
|
|
1392
|
+
};
|
|
1393
|
+
|
|
1394
|
+
const TextEditor = () => {
|
|
1395
|
+
const textEditorData = useTextEditorData();
|
|
1396
|
+
if (!textEditorData) return null;
|
|
1397
|
+
const { cell, table } = textEditorData;
|
|
1398
|
+
const { position, width, height } = cell;
|
|
1399
|
+
const cellStyle = table._getCellStyle(cell.col, cell.row);
|
|
1400
|
+
const fontSize = getProp("fontSize", cellStyle, cell.col, cell.row, table);
|
|
1401
|
+
const bgColor = getProp("bgColor", cellStyle, cell.col, cell.row, table);
|
|
1402
|
+
return /* @__PURE__ */ React.createElement(
|
|
1403
|
+
antd.Input.TextArea,
|
|
1404
|
+
{
|
|
1405
|
+
defaultValue: textEditorData.initialValue,
|
|
1406
|
+
onChange: (e) => setTextEditorValue(e.target.value),
|
|
1407
|
+
autoSize: { minRows: 1 },
|
|
1408
|
+
style: {
|
|
1409
|
+
position: "absolute",
|
|
1410
|
+
left: position.x - 2,
|
|
1411
|
+
top: position.y - 2,
|
|
1412
|
+
width: width + 4,
|
|
1413
|
+
height: height + 4,
|
|
1414
|
+
padding: 5,
|
|
1415
|
+
background: bgColor,
|
|
1416
|
+
fontSize,
|
|
1417
|
+
border: "2px solid #0404ff",
|
|
1418
|
+
borderRadius: 0,
|
|
1419
|
+
scrollbarWidth: "none"
|
|
1420
|
+
}
|
|
1421
|
+
}
|
|
1422
|
+
);
|
|
1423
|
+
};
|
|
1424
|
+
|
|
1425
|
+
const { setUserShowId, getUserShowId, useUserShowId } = store.createAtomStore("userShowId", jotai.atom(null));
|
|
1426
|
+
const { setUserShowData, getUserShowData, useUserShowData } = store.createAtomStore(
|
|
1427
|
+
"userShowData",
|
|
1428
|
+
jotai.atom(null)
|
|
1429
|
+
);
|
|
1430
|
+
const initUserShowTool = (data) => {
|
|
1431
|
+
setUserShowData(data);
|
|
1432
|
+
setUserShowId(data.id);
|
|
1433
|
+
};
|
|
1434
|
+
const clearUserShowTool = () => {
|
|
1435
|
+
setUserShowData(null);
|
|
1436
|
+
setUserShowId(null);
|
|
1437
|
+
};
|
|
1438
|
+
|
|
1439
|
+
const UserShow = () => {
|
|
1440
|
+
const data = useUserShowData();
|
|
1441
|
+
const valueId = useUserShowId();
|
|
1442
|
+
const col = data?.cell?.col;
|
|
1443
|
+
const row = data?.cell?.row;
|
|
1444
|
+
const table = data?.table;
|
|
1445
|
+
let cellStyle, fontSize;
|
|
1446
|
+
if (table && typeof col === "number" && typeof row === "number") {
|
|
1447
|
+
cellStyle = table._getCellStyle(col, row);
|
|
1448
|
+
fontSize = getProp("fontSize", cellStyle, col, row, table);
|
|
1449
|
+
} else {
|
|
1450
|
+
cellStyle = void 0;
|
|
1451
|
+
fontSize = 14;
|
|
1452
|
+
}
|
|
1453
|
+
const [popoverKey, setPopoverKey] = React.useState(0);
|
|
1454
|
+
const [open, setOpen] = React.useState(false);
|
|
1455
|
+
React.useEffect(() => {
|
|
1456
|
+
if (data) {
|
|
1457
|
+
setPopoverKey((prev) => prev + 1);
|
|
1458
|
+
setOpen(true);
|
|
1459
|
+
}
|
|
1460
|
+
}, [data, valueId, col]);
|
|
1461
|
+
if (!data || valueId === "-2") return null;
|
|
1462
|
+
return /* @__PURE__ */ React.createElement(
|
|
1463
|
+
"div",
|
|
1464
|
+
{
|
|
1465
|
+
style: {
|
|
1466
|
+
position: "absolute",
|
|
1467
|
+
left: data.cell.position.x,
|
|
1468
|
+
top: data.cell.position.y - 8,
|
|
1469
|
+
zIndex: 9999,
|
|
1470
|
+
pointerEvents: "auto",
|
|
1471
|
+
transform: "translateX(-50%) translateY(-100%)"
|
|
1472
|
+
}
|
|
1473
|
+
},
|
|
1474
|
+
/* @__PURE__ */ React.createElement(
|
|
1475
|
+
antd.Popover,
|
|
1476
|
+
{
|
|
1477
|
+
key: popoverKey,
|
|
1478
|
+
content: /* @__PURE__ */ React.createElement(
|
|
1479
|
+
ui.AvatarPopoverContent,
|
|
1480
|
+
{
|
|
1481
|
+
id: valueId,
|
|
1482
|
+
column: getActiveEditorTable()?.getColumnDefine(col),
|
|
1483
|
+
fontSize
|
|
1484
|
+
}
|
|
1485
|
+
),
|
|
1486
|
+
open,
|
|
1487
|
+
onOpenChange: setOpen,
|
|
1488
|
+
placement: "top",
|
|
1489
|
+
autoAdjustOverflow: false,
|
|
1490
|
+
mouseEnterDelay: 0.3,
|
|
1491
|
+
mouseLeaveDelay: 0.3,
|
|
1492
|
+
arrow: { pointAtCenter: true },
|
|
1493
|
+
getPopupContainer: () => document.body
|
|
1494
|
+
}
|
|
1495
|
+
)
|
|
1496
|
+
);
|
|
1497
|
+
};
|
|
1498
|
+
|
|
1499
|
+
const { setMenu, getMenu, useMenu } = store.createAtomStore("menu", jotai.atom(null));
|
|
1500
|
+
|
|
1501
|
+
const CellContextMenu = ({}) => {
|
|
1502
|
+
const menu = useMenu();
|
|
1503
|
+
const { cellMenus } = useComponentVTable();
|
|
1504
|
+
const tableEditor = useActiveEditorTable();
|
|
1505
|
+
if (!tableEditor) return null;
|
|
1506
|
+
if (!menu || menu.type !== "cell" || !cellMenus?.length) return null;
|
|
1507
|
+
return /* @__PURE__ */ React.createElement(
|
|
1508
|
+
CellContextMenuInner,
|
|
1509
|
+
{
|
|
1510
|
+
menu,
|
|
1511
|
+
cellMenus,
|
|
1512
|
+
tableEditor,
|
|
1513
|
+
offsetParent: tableEditor.container
|
|
1514
|
+
}
|
|
1515
|
+
);
|
|
1516
|
+
};
|
|
1517
|
+
const CellContextMenuInner = ({ menu, cellMenus, tableEditor, offsetParent = null }) => {
|
|
1518
|
+
const menuItems = React.useMemo(() => {
|
|
1519
|
+
if (!menu || menu.type !== "cell") return;
|
|
1520
|
+
return cellMenus?.map((item) => {
|
|
1521
|
+
const { onCellClick, ...rest } = item;
|
|
1522
|
+
return {
|
|
1523
|
+
...rest,
|
|
1524
|
+
onClick: (info) => {
|
|
1525
|
+
onCellClick?.({
|
|
1526
|
+
menuInfo: info,
|
|
1527
|
+
tableEditor,
|
|
1528
|
+
cell: {
|
|
1529
|
+
col: menu.cell.col,
|
|
1530
|
+
row: menu.cell.row,
|
|
1531
|
+
recordId: menu.cell.recordId,
|
|
1532
|
+
columnId: menu.cell.columnId,
|
|
1533
|
+
rect: menu.cell.rect
|
|
1534
|
+
}
|
|
1535
|
+
});
|
|
1536
|
+
setMenu(null);
|
|
1537
|
+
}
|
|
1538
|
+
};
|
|
1539
|
+
});
|
|
1540
|
+
}, [cellMenus, menu, tableEditor]);
|
|
1541
|
+
return /* @__PURE__ */ React.createElement(
|
|
1542
|
+
gridLayout.TableMenuModal,
|
|
1543
|
+
{
|
|
1544
|
+
isOpen: menu?.open,
|
|
1545
|
+
offsetParent,
|
|
1546
|
+
position: menu.position,
|
|
1547
|
+
menuItems: menuItems ?? [],
|
|
1548
|
+
onPositionChange: (position) => setMenu(
|
|
1549
|
+
(prev) => prev ? { ...prev, position: typeof position === "function" ? position(prev.position) : position } : null
|
|
1550
|
+
)
|
|
1551
|
+
}
|
|
1552
|
+
);
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
const HeaderContextMenu = ({}) => {
|
|
1556
|
+
const { headerMenus } = useComponentVTable();
|
|
1557
|
+
const menu = useMenu();
|
|
1558
|
+
const tableEditor = useActiveEditorTable();
|
|
1559
|
+
if (!tableEditor) return null;
|
|
1560
|
+
if (!menu || menu.type !== "header" || !headerMenus?.length) return null;
|
|
1561
|
+
return /* @__PURE__ */ React.createElement(
|
|
1562
|
+
HeaderContextMenuInner,
|
|
1563
|
+
{
|
|
1564
|
+
menu,
|
|
1565
|
+
headerMenus,
|
|
1566
|
+
tableEditor,
|
|
1567
|
+
offsetParent: tableEditor.container
|
|
1568
|
+
}
|
|
1569
|
+
);
|
|
1570
|
+
};
|
|
1571
|
+
const HeaderContextMenuInner = ({
|
|
1572
|
+
menu,
|
|
1573
|
+
headerMenus,
|
|
1574
|
+
tableEditor,
|
|
1575
|
+
offsetParent = null
|
|
1576
|
+
}) => {
|
|
1577
|
+
const menuItems = React.useMemo(() => {
|
|
1578
|
+
if (!menu || menu.type !== "header") return;
|
|
1579
|
+
return headerMenus?.map((item) => {
|
|
1580
|
+
const { onCellClick, ...rest } = item;
|
|
1581
|
+
return {
|
|
1582
|
+
...rest,
|
|
1583
|
+
onClick: (info) => {
|
|
1584
|
+
onCellClick?.({
|
|
1585
|
+
menuInfo: info,
|
|
1586
|
+
tableEditor,
|
|
1587
|
+
cell: {
|
|
1588
|
+
col: menu.cell.col,
|
|
1589
|
+
row: menu.cell.row,
|
|
1590
|
+
recordId: menu.cell.recordId,
|
|
1591
|
+
columnId: menu.cell.columnId,
|
|
1592
|
+
rect: menu.cell.rect
|
|
1593
|
+
}
|
|
1594
|
+
});
|
|
1595
|
+
setMenu(null);
|
|
1596
|
+
}
|
|
1597
|
+
};
|
|
1598
|
+
});
|
|
1599
|
+
}, [headerMenus, menu, tableEditor]);
|
|
1600
|
+
return /* @__PURE__ */ React.createElement(
|
|
1601
|
+
gridLayout.TableMenuModal,
|
|
1602
|
+
{
|
|
1603
|
+
isOpen: menu?.open,
|
|
1604
|
+
width: 210,
|
|
1605
|
+
offsetParent,
|
|
1606
|
+
position: menu.position,
|
|
1607
|
+
menuItems: menuItems ?? [],
|
|
1608
|
+
onPositionChange: (position) => setMenu(
|
|
1609
|
+
(prev) => prev ? { ...prev, position: typeof position === "function" ? position(prev.position) : position } : null
|
|
1610
|
+
)
|
|
1611
|
+
}
|
|
1612
|
+
);
|
|
1613
|
+
};
|
|
1614
|
+
|
|
1615
|
+
const MoreContextMenu = () => {
|
|
1616
|
+
const menu = useMenu();
|
|
1617
|
+
const tableEditor = useActiveEditorTable();
|
|
1618
|
+
const { moreMenus } = useComponentVTable();
|
|
1619
|
+
if (!tableEditor) return null;
|
|
1620
|
+
if (!menu || menu.type !== "more") return null;
|
|
1621
|
+
return /* @__PURE__ */ React.createElement(MoreContextMenuInner, { menu, moreMenus, tableEditor });
|
|
1622
|
+
};
|
|
1623
|
+
const MoreContextMenuInner = ({ menu, moreMenus, tableEditor }) => {
|
|
1624
|
+
const menuItems = React.useMemo(() => {
|
|
1625
|
+
if (!menu || menu.type !== "more") return;
|
|
1626
|
+
return moreMenus?.map((item) => {
|
|
1627
|
+
const { onCellClick, ...rest } = item;
|
|
1628
|
+
return {
|
|
1629
|
+
...rest,
|
|
1630
|
+
onClick: (info) => {
|
|
1631
|
+
onCellClick?.({
|
|
1632
|
+
menuInfo: info,
|
|
1633
|
+
tableEditor,
|
|
1634
|
+
cell: {
|
|
1635
|
+
col: menu.cell.col,
|
|
1636
|
+
row: menu.cell.row,
|
|
1637
|
+
recordId: menu.cell.recordId,
|
|
1638
|
+
columnId: menu.cell.columnId,
|
|
1639
|
+
rect: menu.cell.rect
|
|
1640
|
+
}
|
|
1641
|
+
});
|
|
1642
|
+
}
|
|
1643
|
+
};
|
|
1644
|
+
});
|
|
1645
|
+
}, [moreMenus, menu, tableEditor]);
|
|
1646
|
+
return /* @__PURE__ */ React.createElement(
|
|
1647
|
+
"div",
|
|
1648
|
+
{
|
|
1649
|
+
onMouseMove: () => setMenu({ ...menu }),
|
|
1650
|
+
onMouseLeave: () => setMenu(null),
|
|
1651
|
+
onMouseEnter: () => setMenu({ ...menu })
|
|
1652
|
+
},
|
|
1653
|
+
/* @__PURE__ */ React.createElement(
|
|
1654
|
+
antd.Dropdown,
|
|
1655
|
+
{
|
|
1656
|
+
menu: {
|
|
1657
|
+
items: menuItems ?? []
|
|
1658
|
+
},
|
|
1659
|
+
align: {
|
|
1660
|
+
offset: [0, -4]
|
|
1661
|
+
},
|
|
1662
|
+
placement: "bottom",
|
|
1663
|
+
arrow: false
|
|
1664
|
+
},
|
|
1665
|
+
/* @__PURE__ */ React.createElement(
|
|
1666
|
+
"div",
|
|
1667
|
+
{
|
|
1668
|
+
style: {
|
|
1669
|
+
left: menu.position.x,
|
|
1670
|
+
top: menu.position.y,
|
|
1671
|
+
position: "absolute",
|
|
1672
|
+
width: 16,
|
|
1673
|
+
height: 20,
|
|
1674
|
+
cursor: "pointer"
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
)
|
|
1678
|
+
)
|
|
1679
|
+
);
|
|
1680
|
+
};
|
|
1681
|
+
|
|
1682
|
+
const Delete = () => {
|
|
1683
|
+
reactHotkeysHook.useHotkeys(
|
|
1684
|
+
["backspace", "delete"],
|
|
1685
|
+
() => {
|
|
1686
|
+
const editor = getActiveEditorTable();
|
|
1687
|
+
if (!editor) return;
|
|
1688
|
+
const run = () => {
|
|
1689
|
+
const selectedCellGroup = editor.getSelectedCell() ?? [];
|
|
1690
|
+
const selectedCells = selectedCellGroup.flat().map((item) => ({
|
|
1691
|
+
col: item.col,
|
|
1692
|
+
row: item.row
|
|
1693
|
+
})).filter((item) => item.row !== 0);
|
|
1694
|
+
const payload = selectedCells.map((item) => {
|
|
1695
|
+
return {
|
|
1696
|
+
...editor.getInteractiveCell(item.col, item.row),
|
|
1697
|
+
previous: editor.getCellOriginValue(item.col, item.row)
|
|
1698
|
+
};
|
|
1699
|
+
});
|
|
1700
|
+
const { recordsForRestore } = editor.removeSelectedCell();
|
|
1701
|
+
const selectedCellNewValues = selectedCells.map((item) => editor.getCellOriginValue(item.col, item.row));
|
|
1702
|
+
const data = payload.map((item, index) => {
|
|
1703
|
+
return {
|
|
1704
|
+
...item,
|
|
1705
|
+
current: selectedCellNewValues[index]
|
|
1706
|
+
};
|
|
1707
|
+
});
|
|
1708
|
+
editor.dispatch("cells::update", {
|
|
1709
|
+
editor,
|
|
1710
|
+
data
|
|
1711
|
+
});
|
|
1712
|
+
return {
|
|
1713
|
+
restore() {
|
|
1714
|
+
const payload2 = selectedCells.map((item) => {
|
|
1715
|
+
return {
|
|
1716
|
+
...editor.getInteractiveCell(item.col, item.row),
|
|
1717
|
+
previous: editor.getCellOriginValue(item.col, item.row)
|
|
1718
|
+
};
|
|
1719
|
+
});
|
|
1720
|
+
editor.updateRecordsData(recordsForRestore);
|
|
1721
|
+
const selectedCellNewValues2 = selectedCells.map((item) => editor.getCellOriginValue(item.col, item.row));
|
|
1722
|
+
const data2 = payload2.map((item, index) => {
|
|
1723
|
+
return {
|
|
1724
|
+
...item,
|
|
1725
|
+
current: selectedCellNewValues2[index]
|
|
1726
|
+
};
|
|
1727
|
+
});
|
|
1728
|
+
editor.dispatch("cells::update", {
|
|
1729
|
+
editor,
|
|
1730
|
+
data: data2
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
};
|
|
1734
|
+
};
|
|
1735
|
+
const command = new EditTableCellDataFunctionalCommand(editor, run);
|
|
1736
|
+
editor.commandManager.execute(command);
|
|
1737
|
+
},
|
|
1738
|
+
[],
|
|
1739
|
+
{
|
|
1740
|
+
enabled: true,
|
|
1741
|
+
enableOnContentEditable: false
|
|
1742
|
+
}
|
|
1743
|
+
);
|
|
1744
|
+
return null;
|
|
1745
|
+
};
|
|
1746
|
+
|
|
1747
|
+
const History = () => {
|
|
1748
|
+
const tableEditor = useActiveEditorTable();
|
|
1749
|
+
const commandManager = tableEditor?.commandManager;
|
|
1750
|
+
reactHotkeysHook.useHotkeys(
|
|
1751
|
+
"mod+z",
|
|
1752
|
+
() => {
|
|
1753
|
+
if (!commandManager) return;
|
|
1754
|
+
commandManager.undo();
|
|
1755
|
+
},
|
|
1756
|
+
[commandManager],
|
|
1757
|
+
{
|
|
1758
|
+
enabled: !!commandManager,
|
|
1759
|
+
enableOnContentEditable: false,
|
|
1760
|
+
enableOnFormTags: true
|
|
1761
|
+
}
|
|
1762
|
+
);
|
|
1763
|
+
reactHotkeysHook.useHotkeys(
|
|
1764
|
+
"mod+shift+z",
|
|
1765
|
+
() => {
|
|
1766
|
+
if (!commandManager) return;
|
|
1767
|
+
commandManager.redo();
|
|
1768
|
+
},
|
|
1769
|
+
[commandManager],
|
|
1770
|
+
{
|
|
1771
|
+
enabled: !!commandManager,
|
|
1772
|
+
enableOnContentEditable: false,
|
|
1773
|
+
enableOnFormTags: true
|
|
1774
|
+
}
|
|
1775
|
+
);
|
|
1776
|
+
return null;
|
|
1777
|
+
};
|
|
1778
|
+
|
|
1779
|
+
const Hotkeys = () => {
|
|
1780
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Delete, null), /* @__PURE__ */ React.createElement(History, null));
|
|
1781
|
+
};
|
|
1782
|
+
|
|
1783
|
+
class TableEditorEvent extends core$1.DestroyClass {
|
|
1784
|
+
constructor(editor, instance, container) {
|
|
1785
|
+
super();
|
|
1786
|
+
this.editor = editor;
|
|
1787
|
+
this.instance = instance;
|
|
1788
|
+
this.container = container;
|
|
1789
|
+
this.cancels.push(this.initEvent());
|
|
1790
|
+
}
|
|
1791
|
+
initEvent() {
|
|
1792
|
+
const handleContextMenuCell = (e) => {
|
|
1793
|
+
const event = e.event;
|
|
1794
|
+
const { recordId, columnId } = this.editor.getInteractiveCell(e.col, e.row);
|
|
1795
|
+
const columnDefine = this.instance.getBodyColumnDefine(e.col, e.row);
|
|
1796
|
+
if (columnDefine.disableSelect) {
|
|
1797
|
+
if (this.editor.debug) console.info("\u5F53\u524D\u5217\u7981\u7528\u9009\u4E2D\uFF0C\u65E0\u6CD5\u89E6\u53D1\u4E0A\u4E0B\u6587\u83DC\u5355", e, columnDefine);
|
|
1798
|
+
return;
|
|
1799
|
+
}
|
|
1800
|
+
const containerRect = this.instance.getContainer().getBoundingClientRect();
|
|
1801
|
+
const rect = this.instance.getCellRelativeRect(e.col, e.row);
|
|
1802
|
+
rect.left += containerRect.left;
|
|
1803
|
+
rect.top += containerRect.top;
|
|
1804
|
+
rect.right += containerRect.left;
|
|
1805
|
+
rect.bottom += containerRect.top;
|
|
1806
|
+
const isHeader = e.row === 0;
|
|
1807
|
+
const position = !isHeader ? { x: event.clientX, y: event.clientY } : { x: rect.left, y: rect.bottom + 1 };
|
|
1808
|
+
setMenu({
|
|
1809
|
+
open: true,
|
|
1810
|
+
type: isHeader ? "header" : "cell",
|
|
1811
|
+
position,
|
|
1812
|
+
cell: { col: e.col, row: e.row, recordId, columnId, rect }
|
|
1813
|
+
});
|
|
1814
|
+
};
|
|
1815
|
+
const hideMenu = (e) => {
|
|
1816
|
+
if (e.target.closest(".menu-container")) return;
|
|
1817
|
+
else setMenu(null);
|
|
1818
|
+
};
|
|
1819
|
+
const handleContextMenu = (e) => {
|
|
1820
|
+
e.preventDefault();
|
|
1821
|
+
e.stopPropagation();
|
|
1822
|
+
};
|
|
1823
|
+
const dbClickHandler = ({ col, row }) => {
|
|
1824
|
+
const columnDefine = this.instance.getBodyColumnDefine(col, row);
|
|
1825
|
+
const cellValue = this.instance.getCellValue(col, row);
|
|
1826
|
+
if (this.editor.debug) {
|
|
1827
|
+
console.group("\u53CC\u51FB\u5355\u5143\u683C\u4E8B\u4EF6");
|
|
1828
|
+
console.log("\u5F53\u524D\u5355\u5143\u683C\u9501\u5B9A&loading\u72B6\u6001:", {
|
|
1829
|
+
editor: this.editor.lock,
|
|
1830
|
+
column: columnDefine.lock,
|
|
1831
|
+
loading: cellValue?.loading
|
|
1832
|
+
});
|
|
1833
|
+
console.log("\u5F53\u524D\u5355\u5143\u683C\u5DF2\u9501\u5B9A\u6216\u6B63\u5728\u52A0\u8F7D\u4E2D\uFF0C\u65E0\u6CD5\u7F16\u8F91");
|
|
1834
|
+
console.groupEnd();
|
|
1835
|
+
}
|
|
1836
|
+
if (this.editor.lock || columnDefine?.lock || cellValue?.loading) return;
|
|
1837
|
+
this.instance.startEditCell(col, row);
|
|
1838
|
+
};
|
|
1839
|
+
const cellClickHandler = ({ col, row }) => {
|
|
1840
|
+
const columnDefine = this.instance.getBodyColumnDefine(col, row);
|
|
1841
|
+
const record = this.instance.getRecordByCell(col, row);
|
|
1842
|
+
const recordData = record ? revertRecordStructure(record) : void 0;
|
|
1843
|
+
const cellValue = this.instance.getCellValue(col, row);
|
|
1844
|
+
if (this.editor.debug) {
|
|
1845
|
+
console.group("\u5355\u51FB\u5355\u5143\u683C\u4E8B\u4EF6");
|
|
1846
|
+
console.log("\u5F53\u524D\u5217\u914D\u7F6E:", columnDefine);
|
|
1847
|
+
console.log("\u5355\u5143\u683C\u6570\u636E:", cellValue);
|
|
1848
|
+
console.log("\u5F53\u524D\u884C\u6570\u636E:", recordData);
|
|
1849
|
+
console.log("\u5F53\u524D\u5355\u5143\u683C\u9501\u5B9A\u72B6\u6001:", {
|
|
1850
|
+
editor: this.editor.lock,
|
|
1851
|
+
column: columnDefine.lock
|
|
1852
|
+
});
|
|
1853
|
+
console.log("\u5F53\u524D\u8868\u683C\u6570\u636E\u7BA1\u7406\u5668:", this.editor.recordsManager);
|
|
1854
|
+
console.groupEnd();
|
|
1855
|
+
}
|
|
1856
|
+
this.editor.dispatch("cell::click", {
|
|
1857
|
+
editor: this.editor,
|
|
1858
|
+
columnDefine,
|
|
1859
|
+
record,
|
|
1860
|
+
cellValue
|
|
1861
|
+
});
|
|
1862
|
+
};
|
|
1863
|
+
const changeHeaderPositionHandler = () => {
|
|
1864
|
+
this.editor.dispatch("column::drag::move::end", {
|
|
1865
|
+
editor: this.editor,
|
|
1866
|
+
columnIds: this.editor.columnIds.filter((item) => !INNER_TABLE_COLUMN_KEY_LIST.includes(item))
|
|
1867
|
+
});
|
|
1868
|
+
};
|
|
1869
|
+
const resizeColumnEndHandler = ({ col, colWidths }) => {
|
|
1870
|
+
const define = this.editor.getColumnDefine(col);
|
|
1871
|
+
if (INNER_TABLE_COLUMN_KEY_LIST.includes(define.field)) return;
|
|
1872
|
+
this.editor.dispatch("column::width::update", {
|
|
1873
|
+
editor: this.editor,
|
|
1874
|
+
columnId: define.field,
|
|
1875
|
+
width: colWidths[col]
|
|
1876
|
+
});
|
|
1877
|
+
};
|
|
1878
|
+
const checkboxStateChangeHandler = (event) => {
|
|
1879
|
+
const { field } = event;
|
|
1880
|
+
if (field != INNER_TABLE_COLUMN_KEY_CHECKBOX) return;
|
|
1881
|
+
const recordIds = this.editor.interactive.selectedRecords;
|
|
1882
|
+
this.editor.dispatch("record::checkbox::state::change", {
|
|
1883
|
+
editor: this.editor,
|
|
1884
|
+
selectedRecordIds: recordIds
|
|
1885
|
+
});
|
|
1886
|
+
};
|
|
1887
|
+
this.instance.on("contextmenu_cell", handleContextMenuCell);
|
|
1888
|
+
this.instance.on("dblclick_cell", dbClickHandler);
|
|
1889
|
+
this.instance.on("click_cell", cellClickHandler);
|
|
1890
|
+
this.instance.on("change_header_position", changeHeaderPositionHandler);
|
|
1891
|
+
this.instance.on("resize_column_end", resizeColumnEndHandler);
|
|
1892
|
+
this.instance.on("checkbox_state_change", checkboxStateChangeHandler);
|
|
1893
|
+
const parent = this.container.parentElement;
|
|
1894
|
+
parent.addEventListener("contextmenu", handleContextMenu);
|
|
1895
|
+
window.addEventListener("click", hideMenu);
|
|
1896
|
+
return () => {
|
|
1897
|
+
this.instance.off("contextmenu_cell", handleContextMenuCell);
|
|
1898
|
+
this.instance.off("dblclick_cell", dbClickHandler);
|
|
1899
|
+
this.instance.off("click_cell", cellClickHandler);
|
|
1900
|
+
this.instance.off("change_header_position", changeHeaderPositionHandler);
|
|
1901
|
+
this.instance.off("resize_column_end", resizeColumnEndHandler);
|
|
1902
|
+
this.instance.off("checkbox_state_change", checkboxStateChangeHandler);
|
|
1903
|
+
parent.removeEventListener("contextmenu", handleContextMenu);
|
|
1904
|
+
window.removeEventListener("click", hideMenu);
|
|
1905
|
+
this.instance.eventManager.release();
|
|
1906
|
+
};
|
|
1907
|
+
}
|
|
1908
|
+
destroy() {
|
|
1909
|
+
super.destroy();
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
class BaseTableInteractive {
|
|
1914
|
+
constructor(editor) {
|
|
1915
|
+
this.editor = editor;
|
|
1916
|
+
}
|
|
1917
|
+
get selectedRecords() {
|
|
1918
|
+
const records = this.editor.getSelectedRecord();
|
|
1919
|
+
return records.map((record) => record[INNER_TABLE_RECORD_ID_KEY]);
|
|
1920
|
+
}
|
|
1921
|
+
get selectedCells() {
|
|
1922
|
+
const selectedCells = this.editor.getSelectedCell() ?? [];
|
|
1923
|
+
const cellGroups = selectedCells.filter((group) => group[0].row !== 0);
|
|
1924
|
+
const cells = cellGroups.flat();
|
|
1925
|
+
return cells.map((item) => {
|
|
1926
|
+
const { col, row } = item;
|
|
1927
|
+
const { columnId, recordId } = this.editor.getInteractiveCell(col, row);
|
|
1928
|
+
return {
|
|
1929
|
+
cell: { columnId, recordId },
|
|
1930
|
+
data: item.value
|
|
1931
|
+
};
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1934
|
+
getRecordsManagerStore() {
|
|
1935
|
+
return this.editor.recordsManager.store;
|
|
1936
|
+
}
|
|
1937
|
+
filters(recordIds) {
|
|
1938
|
+
this.editor.recordsManager.filters = recordIds;
|
|
1939
|
+
}
|
|
1940
|
+
selectCell(cell) {
|
|
1941
|
+
const { col, row } = this.editor.getInteractiveCellPosition(cell);
|
|
1942
|
+
this.editor.selectCell(col, row);
|
|
1943
|
+
}
|
|
1944
|
+
selectColumnByIndex(columnIndex) {
|
|
1945
|
+
const col = getColFromColIndex(columnIndex, this.editor.innerColumnControl);
|
|
1946
|
+
this.editor.instance.selectCol(col);
|
|
1947
|
+
}
|
|
1948
|
+
selectRowByIndex(recordIndex) {
|
|
1949
|
+
const row = getRowFromRowIndex(recordIndex);
|
|
1950
|
+
this.editor.instance.selectRow(row);
|
|
1951
|
+
}
|
|
1952
|
+
selectCellByIndex(cell) {
|
|
1953
|
+
const [recordIndex, colIndex] = cell;
|
|
1954
|
+
const col = getColFromColIndex(colIndex, this.editor.innerColumnControl);
|
|
1955
|
+
const row = getRowFromRowIndex(recordIndex);
|
|
1956
|
+
this.editor.selectCell(col, row);
|
|
1957
|
+
}
|
|
1958
|
+
clearSelect() {
|
|
1959
|
+
this.editor.instance.clearSelected();
|
|
1960
|
+
}
|
|
1961
|
+
setRecordsSelectState(records, state = true) {
|
|
1962
|
+
const columnIndex = 0;
|
|
1963
|
+
const columnDefine = this.editor.getColumnDefine(0);
|
|
1964
|
+
if (columnDefine.field !== INNER_TABLE_COLUMN_KEY_CHECKBOX) throw new Error("\u5F53\u524D\u8868\u683C\u7B2C\u4E00\u5217\u4E0D\u662F\u590D\u9009\u6846\u5217");
|
|
1965
|
+
if (records === "all") {
|
|
1966
|
+
const rowCount = this.editor.rowCount;
|
|
1967
|
+
for (let row = 0; row < rowCount; row++) {
|
|
1968
|
+
this.editor.setCheckboxState(columnIndex, row, state);
|
|
1969
|
+
}
|
|
1970
|
+
} else {
|
|
1971
|
+
const cellPositions = records.map(
|
|
1972
|
+
(item) => this.editor.getInteractiveCellPosition({ recordId: item, columnId: INNER_TABLE_COLUMN_KEY_CHECKBOX })
|
|
1973
|
+
);
|
|
1974
|
+
cellPositions.forEach((item) => this.editor.setCheckboxState(columnIndex, item.row, state));
|
|
1975
|
+
}
|
|
1976
|
+
}
|
|
1977
|
+
getRecord(recordId) {
|
|
1978
|
+
const { row } = this.editor.getInteractiveCellPosition({ recordId, columnId: INNER_TABLE_COLUMN_KEY_CHECKBOX });
|
|
1979
|
+
const data = this.editor.getRecordByCell(0, row);
|
|
1980
|
+
const record = data ? revertRecordStructure(data) : void 0;
|
|
1981
|
+
return record;
|
|
1982
|
+
}
|
|
1983
|
+
getRecords(recordIds) {
|
|
1984
|
+
const records = recordIds.map((item) => this.getRecord(item));
|
|
1985
|
+
return records;
|
|
1986
|
+
}
|
|
1987
|
+
updateRecords(records) {
|
|
1988
|
+
this.editor.recordsManager.updateRecords(records);
|
|
1989
|
+
}
|
|
1990
|
+
addRecords(_records) {
|
|
1991
|
+
this.editor.recordsManager.addRecords(_records);
|
|
1992
|
+
}
|
|
1993
|
+
removeRecords(_recordIds) {
|
|
1994
|
+
this.editor.recordsManager.removeRecords(_recordIds);
|
|
1995
|
+
}
|
|
1996
|
+
focus(cell) {
|
|
1997
|
+
const { col, row } = this.editor.getInteractiveCellPosition(cell);
|
|
1998
|
+
this.editor.focusCell(col, row);
|
|
1999
|
+
}
|
|
2000
|
+
focusByIndex(cell) {
|
|
2001
|
+
const [recordIndex, colIndex] = cell;
|
|
2002
|
+
const col = getColFromColIndex(colIndex, this.editor.innerColumnControl);
|
|
2003
|
+
const row = getRowFromRowIndex(recordIndex);
|
|
2004
|
+
this.editor.focusCell(col, row);
|
|
2005
|
+
}
|
|
2006
|
+
highlight(cells, _key = core.CUSTOM_CELL_STYLE_HIGHLIGHT_FOCUS) {
|
|
2007
|
+
const positions = cells.map((cell) => this.editor.getInteractiveCellPosition(cell));
|
|
2008
|
+
this.editor.highlightCells(_key, positions);
|
|
2009
|
+
}
|
|
2010
|
+
highlightByIndex(cells, _key = core.CUSTOM_CELL_STYLE_HIGHLIGHT_FOCUS) {
|
|
2011
|
+
const positions = cells.map(([recordIndex, colIndex]) => ({
|
|
2012
|
+
row: getRowFromRowIndex(recordIndex),
|
|
2013
|
+
col: getColFromColIndex(colIndex, this.editor.innerColumnControl)
|
|
2014
|
+
}));
|
|
2015
|
+
this.editor.highlightCells(_key, positions);
|
|
2016
|
+
}
|
|
2017
|
+
clearHighlight(key = core.CUSTOM_CELL_STYLE_HIGHLIGHT_FOCUS) {
|
|
2018
|
+
this.editor.clearHighlight(key);
|
|
2019
|
+
}
|
|
2020
|
+
// 冻结列的数量,此处count是用户可感知列的数量
|
|
2021
|
+
setFreezeCount(count) {
|
|
2022
|
+
const { checkbox } = this.editor.innerColumnControl;
|
|
2023
|
+
const realCount = count + (checkbox ? 1 : 0);
|
|
2024
|
+
this.editor.setFreezeCount(realCount);
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
class RecordsManager extends core$1.DestroyClass {
|
|
2029
|
+
constructor(editor) {
|
|
2030
|
+
super();
|
|
2031
|
+
this.editor = editor;
|
|
2032
|
+
this.recordsMap = jotai.atom(/* @__PURE__ */ new Map());
|
|
2033
|
+
this._filters = jotai.atom(void 0);
|
|
2034
|
+
/**
|
|
2035
|
+
* 当前表格records数量
|
|
2036
|
+
*
|
|
2037
|
+
* 如果filters不存在,直接返回 recordsMap 数量,
|
|
2038
|
+
*
|
|
2039
|
+
* 如果filters存在,则返回 filters 中存在的 records 数量
|
|
2040
|
+
*/
|
|
2041
|
+
this.size = jotai.atom((get) => {
|
|
2042
|
+
const records = get(this.recordsMap);
|
|
2043
|
+
const filters = get(this._filters);
|
|
2044
|
+
let count = 0;
|
|
2045
|
+
if (lodash.isNil(filters)) count = records.size;
|
|
2046
|
+
else {
|
|
2047
|
+
count = filters.map((recordId) => records.get(recordId)).filter(Boolean).length;
|
|
2048
|
+
}
|
|
2049
|
+
return count;
|
|
2050
|
+
});
|
|
2051
|
+
}
|
|
2052
|
+
get filters() {
|
|
2053
|
+
return window.store.get(this._filters);
|
|
2054
|
+
}
|
|
2055
|
+
set filters(value) {
|
|
2056
|
+
window.store.set(this._filters, value);
|
|
2057
|
+
this.renderRecords();
|
|
2058
|
+
}
|
|
2059
|
+
initRecords(records) {
|
|
2060
|
+
const recordsMap = window.store.get(this.recordsMap);
|
|
2061
|
+
records.forEach((item) => recordsMap.set(item.INNER_PRESET_RECORD_ID, item));
|
|
2062
|
+
window.store.set(this.recordsMap, new Map(recordsMap));
|
|
2063
|
+
}
|
|
2064
|
+
renderRecords() {
|
|
2065
|
+
const recordsMap = window.store.get(this.recordsMap);
|
|
2066
|
+
const records = this.filters ? this.filters.map((filter) => recordsMap.get(filter)) : [...recordsMap.values()];
|
|
2067
|
+
const data = records.filter(Boolean);
|
|
2068
|
+
this.editor.setRecords(data);
|
|
2069
|
+
}
|
|
2070
|
+
updateRecords(records) {
|
|
2071
|
+
const recordsMap = window.store.get(this.recordsMap);
|
|
2072
|
+
records.forEach((item) => {
|
|
2073
|
+
const adaptedRecord = adaptRecordStructure(item);
|
|
2074
|
+
recordsMap.set(adaptedRecord[INNER_TABLE_RECORD_ID_KEY], adaptedRecord);
|
|
2075
|
+
});
|
|
2076
|
+
const ids = records.map((item) => item.id);
|
|
2077
|
+
const values = [...recordsMap.values()];
|
|
2078
|
+
const data = values.map((item, index) => {
|
|
2079
|
+
return ids.includes(item.INNER_PRESET_RECORD_ID) ? [item, index] : void 0;
|
|
2080
|
+
}).filter(Boolean);
|
|
2081
|
+
this.editor.instance.updateRecords(
|
|
2082
|
+
data.map(([record]) => record),
|
|
2083
|
+
data.map(([, rowIndex]) => rowIndex)
|
|
2084
|
+
);
|
|
2085
|
+
window.store.set(this.recordsMap, new Map(recordsMap));
|
|
2086
|
+
}
|
|
2087
|
+
addRecords(records) {
|
|
2088
|
+
const recordsMap = window.store.get(this.recordsMap);
|
|
2089
|
+
records.forEach((item) => {
|
|
2090
|
+
const adaptedRecord = adaptRecordStructure(item);
|
|
2091
|
+
if (recordsMap.has(adaptedRecord[INNER_TABLE_RECORD_ID_KEY])) {
|
|
2092
|
+
throw new Error("record id already exists " + adaptedRecord[INNER_TABLE_RECORD_ID_KEY]);
|
|
2093
|
+
}
|
|
2094
|
+
recordsMap.set(adaptedRecord[INNER_TABLE_RECORD_ID_KEY], adaptedRecord);
|
|
2095
|
+
});
|
|
2096
|
+
const recordsAdapted = records.map((item) => recordsMap.get(item.id)).filter(Boolean);
|
|
2097
|
+
this.editor.addRecords(recordsAdapted);
|
|
2098
|
+
window.store.set(this.recordsMap, new Map(recordsMap));
|
|
2099
|
+
}
|
|
2100
|
+
removeRecords(recordIds) {
|
|
2101
|
+
const recordsMap = window.store.get(this.recordsMap);
|
|
2102
|
+
recordIds.forEach((id) => recordsMap.delete(id));
|
|
2103
|
+
const indexes = recordIds.map((id) => this.editor.getInteractiveRecordIndex(id)).filter((i) => i !== -1);
|
|
2104
|
+
this.editor.deleteRecords(indexes);
|
|
2105
|
+
window.store.set(this.recordsMap, new Map(recordsMap));
|
|
2106
|
+
}
|
|
2107
|
+
get store() {
|
|
2108
|
+
return window.store.get(this.recordsMap);
|
|
2109
|
+
}
|
|
2110
|
+
get(recordId) {
|
|
2111
|
+
const recordsMap = window.store.get(this.recordsMap);
|
|
2112
|
+
return recordsMap.get(recordId);
|
|
2113
|
+
}
|
|
2114
|
+
set(recordId, record) {
|
|
2115
|
+
const recordsMap = window.store.get(this.recordsMap);
|
|
2116
|
+
recordsMap.set(recordId, record);
|
|
2117
|
+
window.store.set(this.recordsMap, new Map(recordsMap));
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
|
|
2121
|
+
const createHeaderGraphics = (type, props) => {
|
|
2122
|
+
const { table, row, col, rect, value } = props;
|
|
2123
|
+
const headerStyle = table._getCellStyle(col, row);
|
|
2124
|
+
const columnDefine = table.getBodyColumnDefine(col, row);
|
|
2125
|
+
const lock = !!columnDefine.lock;
|
|
2126
|
+
const functionalFontSize = getProp("fontSize", headerStyle, col, row, table);
|
|
2127
|
+
const functionalColor = getProp("color", headerStyle, col, row, table);
|
|
2128
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
2129
|
+
const headerIconSize = getIconSizeFromFont(functionalFontSize);
|
|
2130
|
+
const g = vrender.createGroup({
|
|
2131
|
+
width,
|
|
2132
|
+
height,
|
|
2133
|
+
display: "flex",
|
|
2134
|
+
flexWrap: "nowrap",
|
|
2135
|
+
justifyContent: "space-between",
|
|
2136
|
+
alignContent: "center",
|
|
2137
|
+
alignItems: "center"
|
|
2138
|
+
// 垂直居中
|
|
2139
|
+
});
|
|
2140
|
+
const lg = vrender.createGroup({
|
|
2141
|
+
width: width - 30,
|
|
2142
|
+
height,
|
|
2143
|
+
display: "flex",
|
|
2144
|
+
flexWrap: "nowrap",
|
|
2145
|
+
justifyContent: "flex-start",
|
|
2146
|
+
alignContent: "center",
|
|
2147
|
+
alignItems: "center"
|
|
2148
|
+
});
|
|
2149
|
+
const rg = vrender.createGroup({
|
|
2150
|
+
display: "flex",
|
|
2151
|
+
width: 30,
|
|
2152
|
+
height,
|
|
2153
|
+
alignContent: "center",
|
|
2154
|
+
alignItems: "center"
|
|
2155
|
+
});
|
|
2156
|
+
const arrowIcon = createIconGraphics("arrow_down", {
|
|
2157
|
+
size: headerIconSize,
|
|
2158
|
+
color: functionalColor,
|
|
2159
|
+
cursor: "pointer",
|
|
2160
|
+
hoverBg: true
|
|
2161
|
+
});
|
|
2162
|
+
rg.add(arrowIcon);
|
|
2163
|
+
const toolContainer = vrender.createGroup({
|
|
2164
|
+
display: "flex",
|
|
2165
|
+
width: 30,
|
|
2166
|
+
height,
|
|
2167
|
+
alignContent: "center",
|
|
2168
|
+
alignItems: "center"
|
|
2169
|
+
});
|
|
2170
|
+
const toolIcon = createIconGraphics(lock ? "lock" : core.TOOL_ICON[type], {
|
|
2171
|
+
size: headerIconSize,
|
|
2172
|
+
color: functionalColor
|
|
2173
|
+
});
|
|
2174
|
+
toolContainer.add(toolIcon);
|
|
2175
|
+
const titleContainer = vrender.createGroup({
|
|
2176
|
+
display: "flex",
|
|
2177
|
+
width: width - 60,
|
|
2178
|
+
height,
|
|
2179
|
+
alignContent: "center",
|
|
2180
|
+
alignItems: "center"
|
|
2181
|
+
});
|
|
2182
|
+
const title = vrender.createText({
|
|
2183
|
+
text: value,
|
|
2184
|
+
dy: -functionalFontSize / 2,
|
|
2185
|
+
fontSize: functionalFontSize,
|
|
2186
|
+
fill: functionalColor,
|
|
2187
|
+
lineHeight: height,
|
|
2188
|
+
maxLineWidth: width - 30,
|
|
2189
|
+
textAlign: "left",
|
|
2190
|
+
textBaseline: "middle"
|
|
2191
|
+
});
|
|
2192
|
+
titleContainer.add(title);
|
|
2193
|
+
lg.add(toolContainer);
|
|
2194
|
+
lg.add(titleContainer);
|
|
2195
|
+
g.add(lg);
|
|
2196
|
+
g.add(rg);
|
|
2197
|
+
arrowIcon.addEventListener("click", () => {
|
|
2198
|
+
});
|
|
2199
|
+
return g;
|
|
2200
|
+
};
|
|
2201
|
+
|
|
2202
|
+
const isColumnEditable = (table, col) => {
|
|
2203
|
+
const column = table.getBodyColumnDefine(col, 0);
|
|
2204
|
+
const lock = column.lock;
|
|
2205
|
+
return !lock;
|
|
2206
|
+
};
|
|
2207
|
+
const createDefaultColumnConfig = () => {
|
|
2208
|
+
return {
|
|
2209
|
+
field: id.getUUID(),
|
|
2210
|
+
title: "\u6587\u672C",
|
|
2211
|
+
tool: 28,
|
|
2212
|
+
// TODO: 改成自定义的文本输入组件
|
|
2213
|
+
editor: "textEditor",
|
|
2214
|
+
headerCustomLayout: (args) => {
|
|
2215
|
+
return {
|
|
2216
|
+
rootContainer: createHeaderGraphics(28, args),
|
|
2217
|
+
renderDefault: false
|
|
2218
|
+
};
|
|
2219
|
+
}
|
|
2220
|
+
};
|
|
2221
|
+
};
|
|
2222
|
+
|
|
2223
|
+
class TableEditor extends core$1.DestroyClass {
|
|
2224
|
+
constructor(id, container, onChange, config, commandManager, uploadFile, innerColumnControl) {
|
|
2225
|
+
super();
|
|
2226
|
+
this.id = id;
|
|
2227
|
+
this.container = container;
|
|
2228
|
+
this.commandManager = commandManager;
|
|
2229
|
+
this.uploadFile = uploadFile;
|
|
2230
|
+
this.innerColumnControl = innerColumnControl;
|
|
2231
|
+
this._lock = jotai.atom(false);
|
|
2232
|
+
this.customCellStyleArrangement = /* @__PURE__ */ new Map();
|
|
2233
|
+
this.recordsManager = new RecordsManager(this);
|
|
2234
|
+
/**
|
|
2235
|
+
* 当前是否处于debug状态,一般开发的时候为true,会打印一些需要调试的日志
|
|
2236
|
+
*/
|
|
2237
|
+
this.debug = false;
|
|
2238
|
+
/**
|
|
2239
|
+
* 供外部调用的接口
|
|
2240
|
+
*/
|
|
2241
|
+
this.interactive = new BaseTableInteractive(this);
|
|
2242
|
+
this.dispatch = onChange;
|
|
2243
|
+
const editorMap = getEditorTableStore();
|
|
2244
|
+
const editor = editorMap.get(this.id);
|
|
2245
|
+
if (editor) throw new Error("TableEditor \u5DF2\u5B58\u5728");
|
|
2246
|
+
this.instance = new VTable.ListTable(container, config);
|
|
2247
|
+
editorMap.set(id, this);
|
|
2248
|
+
setEditorTableStore(new Map([...editorMap]));
|
|
2249
|
+
this.event = new TableEditorEvent(this, this.instance, this.container);
|
|
2250
|
+
this.recordsManager.initRecords(this.instance.records);
|
|
2251
|
+
this.load();
|
|
2252
|
+
}
|
|
2253
|
+
get lock() {
|
|
2254
|
+
return window.store.get(this._lock);
|
|
2255
|
+
}
|
|
2256
|
+
set lock(value) {
|
|
2257
|
+
window.store.set(this._lock, value);
|
|
2258
|
+
}
|
|
2259
|
+
get colCount() {
|
|
2260
|
+
return this.instance.colCount;
|
|
2261
|
+
}
|
|
2262
|
+
get rowCount() {
|
|
2263
|
+
return this.instance.rowCount;
|
|
2264
|
+
}
|
|
2265
|
+
/**
|
|
2266
|
+
* 用于限定列的操作范围
|
|
2267
|
+
* 前两列 0 1 是关键主列,不进行任何操作,并且顺序永远在最前面
|
|
2268
|
+
* 最后两列 colCount - 1:Plus列, colCount - 2:more列 同样是固定列
|
|
2269
|
+
*/
|
|
2270
|
+
get colActionLimit() {
|
|
2271
|
+
return {
|
|
2272
|
+
min: 2,
|
|
2273
|
+
max: this.instance.colCount - 2
|
|
2274
|
+
};
|
|
2275
|
+
}
|
|
2276
|
+
get columnIds() {
|
|
2277
|
+
return this.columns.map((item) => item.field);
|
|
2278
|
+
}
|
|
2279
|
+
get columns() {
|
|
2280
|
+
return this.instance.columns;
|
|
2281
|
+
}
|
|
2282
|
+
updateCellData(col, row, value) {
|
|
2283
|
+
const { field } = this.getColumnDefine(col);
|
|
2284
|
+
const record = this.instance.getRecordByCell(col, row);
|
|
2285
|
+
const recordId = record[INNER_TABLE_RECORD_ID_KEY];
|
|
2286
|
+
const recordData = this.recordsManager.get(recordId);
|
|
2287
|
+
if (!recordData) throw new Error(`[updateCellData] recordId ${recordId} \u4E0D\u5B58\u5728`);
|
|
2288
|
+
recordData[field] = value;
|
|
2289
|
+
this.updateCell(col, row, value);
|
|
2290
|
+
}
|
|
2291
|
+
getRecordByCell(col, row) {
|
|
2292
|
+
return this.instance.getRecordByCell(col, row);
|
|
2293
|
+
}
|
|
2294
|
+
getInteractiveCell(col, row) {
|
|
2295
|
+
const record = this.instance.getRecordByCell(col, row) ?? {};
|
|
2296
|
+
const columnDefine = this.instance.getBodyColumnDefine(col, row);
|
|
2297
|
+
const recordId = record[INNER_TABLE_RECORD_ID_KEY];
|
|
2298
|
+
const columnId = columnDefine.field;
|
|
2299
|
+
return { columnId, recordId };
|
|
2300
|
+
}
|
|
2301
|
+
getInteractiveRecordIndex(recordId) {
|
|
2302
|
+
return this.instance.records.findIndex((record) => record[INNER_TABLE_RECORD_ID_KEY] === recordId);
|
|
2303
|
+
}
|
|
2304
|
+
getInteractiveCellPosition(cell) {
|
|
2305
|
+
const { recordId, columnId } = cell;
|
|
2306
|
+
const fields = this.instance.columns.map((item) => item.field);
|
|
2307
|
+
const rowIndex = this.instance.records.findIndex((record) => record[INNER_TABLE_RECORD_ID_KEY] === recordId);
|
|
2308
|
+
const col = fields.findIndex((field) => field === columnId);
|
|
2309
|
+
return { col, row: getRowFromRowIndex(rowIndex) };
|
|
2310
|
+
}
|
|
2311
|
+
updateColumns(columns) {
|
|
2312
|
+
this.instance.updateColumns(columns);
|
|
2313
|
+
}
|
|
2314
|
+
getSelectedRecord() {
|
|
2315
|
+
const selected = this.instance.getCheckboxState(INNER_TABLE_COLUMN_KEY_CHECKBOX);
|
|
2316
|
+
return this.instance.records.filter((_, index) => selected[index]);
|
|
2317
|
+
}
|
|
2318
|
+
setCheckboxState(col, row, state) {
|
|
2319
|
+
this.instance.setCellCheckboxState(col, row, state);
|
|
2320
|
+
}
|
|
2321
|
+
getColumnDefine(col) {
|
|
2322
|
+
return this.instance.getBodyColumnDefine(col, 0);
|
|
2323
|
+
}
|
|
2324
|
+
getSelectedCell() {
|
|
2325
|
+
return this.instance.getSelectedCellInfos();
|
|
2326
|
+
}
|
|
2327
|
+
focusCell(col, row) {
|
|
2328
|
+
this.instance.scrollToCell({ col, row });
|
|
2329
|
+
}
|
|
2330
|
+
highlightCells(customCellStyleKey, cells) {
|
|
2331
|
+
this.clearHighlight(customCellStyleKey);
|
|
2332
|
+
cells.forEach((cell) => this.instance.arrangeCustomCellStyle(cell, customCellStyleKey));
|
|
2333
|
+
this.customCellStyleArrangement.set(customCellStyleKey, cells);
|
|
2334
|
+
}
|
|
2335
|
+
clearHighlight(customCellStyleKey) {
|
|
2336
|
+
if (!customCellStyleKey) {
|
|
2337
|
+
this.instance.arrangeCustomCellStyle(
|
|
2338
|
+
{
|
|
2339
|
+
range: {
|
|
2340
|
+
start: { col: 0, row: 0 },
|
|
2341
|
+
end: { col: this.instance.colCount - 1, row: this.instance.rowCount - 1 }
|
|
2342
|
+
}
|
|
2343
|
+
},
|
|
2344
|
+
"",
|
|
2345
|
+
true
|
|
2346
|
+
);
|
|
2347
|
+
this.customCellStyleArrangement.clear();
|
|
2348
|
+
} else {
|
|
2349
|
+
const cells = this.customCellStyleArrangement.get(customCellStyleKey) || [];
|
|
2350
|
+
cells.forEach((cell) => this.instance.arrangeCustomCellStyle(cell, ""));
|
|
2351
|
+
this.customCellStyleArrangement.delete(customCellStyleKey);
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
updateColumn(col, options) {
|
|
2355
|
+
const newColumns = [...this.instance.columns];
|
|
2356
|
+
newColumns[col] = {
|
|
2357
|
+
...newColumns[col],
|
|
2358
|
+
...options
|
|
2359
|
+
};
|
|
2360
|
+
this.instance.updateColumns(newColumns);
|
|
2361
|
+
}
|
|
2362
|
+
setRecords(_records) {
|
|
2363
|
+
this.instance.setRecords(_records, { sortState: null });
|
|
2364
|
+
}
|
|
2365
|
+
addRecords(_records) {
|
|
2366
|
+
this.instance.addRecords(_records);
|
|
2367
|
+
}
|
|
2368
|
+
selectCell(col, row) {
|
|
2369
|
+
this.instance.selectCell(col, row);
|
|
2370
|
+
}
|
|
2371
|
+
/**
|
|
2372
|
+
* 删除选中单元格
|
|
2373
|
+
* 1. 过滤表头行
|
|
2374
|
+
* 2. 只修改没有被锁定的列内容
|
|
2375
|
+
*/
|
|
2376
|
+
removeSelectedCell() {
|
|
2377
|
+
const selectedCells = this.getSelectedCell() ?? [];
|
|
2378
|
+
const cellGroups = selectedCells.filter((group) => group[0].row !== 0);
|
|
2379
|
+
const rows = cellGroups.map((cells) => this.instance.getRecordShowIndexByCell(cells[0].col, cells[0].row));
|
|
2380
|
+
const row1 = cellGroups[0];
|
|
2381
|
+
const cols = row1.map((cell) => cell.col).filter((col) => isColumnEditable(this.instance, col));
|
|
2382
|
+
const fields = cols.map((col) => this.instance.columns[col].field).filter(Boolean);
|
|
2383
|
+
const recordsForRestore = rows.map((row) => [
|
|
2384
|
+
structuredClone(this.instance.records[row]),
|
|
2385
|
+
row
|
|
2386
|
+
]);
|
|
2387
|
+
const records = rows.map((row) => {
|
|
2388
|
+
const record = structuredClone(this.instance.records[row]);
|
|
2389
|
+
fields.forEach((field) => record[field].value = void 0);
|
|
2390
|
+
return [record, row];
|
|
2391
|
+
});
|
|
2392
|
+
this.instance.updateRecords(
|
|
2393
|
+
records.map(([record]) => record),
|
|
2394
|
+
records.map(([, row]) => row)
|
|
2395
|
+
);
|
|
2396
|
+
return {
|
|
2397
|
+
records,
|
|
2398
|
+
recordsForRestore
|
|
2399
|
+
};
|
|
2400
|
+
}
|
|
2401
|
+
/**
|
|
2402
|
+
* 添加数据 支持多条数据
|
|
2403
|
+
* @param records 多条数据
|
|
2404
|
+
* @param recordIndex 向数据源中要插入的位置,从0开始。不设置recordIndex的话 默认追加到最后。
|
|
2405
|
+
* 如果设置了排序规则recordIndex无效,会自动适应排序逻辑确定插入顺序。
|
|
2406
|
+
* recordIndex 可以通过接口getRecordShowIndexByCell获取
|
|
2407
|
+
*/
|
|
2408
|
+
createRows(count, recordBodyIndex) {
|
|
2409
|
+
const index = recordBodyIndex ?? this.instance.recordsCount;
|
|
2410
|
+
const columns = this.instance.columns.map((item) => [item.field, item.defaultValue ?? void 0]);
|
|
2411
|
+
const defaultRecord = Object.fromEntries(columns);
|
|
2412
|
+
const newRecords = Array.from({ length: count }).map(() => lodash.clone(defaultRecord));
|
|
2413
|
+
this.instance.addRecords([...newRecords], index);
|
|
2414
|
+
const indexes = [];
|
|
2415
|
+
for (let i = 0; i < count; i++) {
|
|
2416
|
+
indexes.push(index + i);
|
|
2417
|
+
}
|
|
2418
|
+
return {
|
|
2419
|
+
newRecords,
|
|
2420
|
+
newRecordIndexes: indexes
|
|
2421
|
+
};
|
|
2422
|
+
}
|
|
2423
|
+
deleteRecords(recordIndexes) {
|
|
2424
|
+
this.instance.deleteRecords(recordIndexes);
|
|
2425
|
+
}
|
|
2426
|
+
/**
|
|
2427
|
+
* 删除行
|
|
2428
|
+
*/
|
|
2429
|
+
removeRow(count, recordBodyIndex) {
|
|
2430
|
+
if (this.lock) throw new Error("\u9501\u5B9A\u8868\u683C\uFF0C\u4E0D\u5141\u8BB8\u5220\u9664\u884C");
|
|
2431
|
+
const index = recordBodyIndex;
|
|
2432
|
+
const indexes = [];
|
|
2433
|
+
for (let i = 0; i < count; i++) {
|
|
2434
|
+
indexes.push(index + i);
|
|
2435
|
+
}
|
|
2436
|
+
const records = structuredClone(indexes.map((index2) => this.instance.records[index2]));
|
|
2437
|
+
this.instance.deleteRecords(lodash.clone(indexes));
|
|
2438
|
+
return {
|
|
2439
|
+
oldRecords: records,
|
|
2440
|
+
oldRecordIndexes: indexes
|
|
2441
|
+
};
|
|
2442
|
+
}
|
|
2443
|
+
/**
|
|
2444
|
+
* 新增默认列
|
|
2445
|
+
* @param count 新增列数
|
|
2446
|
+
* @param insertIndex 新增列索引,默认在最后一列前新增
|
|
2447
|
+
*/
|
|
2448
|
+
createColumn(count, insertIndex) {
|
|
2449
|
+
if (this.lock) throw new Error("\u9501\u5B9A\u8868\u683C\uFF0C\u4E0D\u5141\u8BB8\u65B0\u589E\u5217");
|
|
2450
|
+
const columns = [...this.instance.columns];
|
|
2451
|
+
const newColumns = [...this.instance.columns];
|
|
2452
|
+
const index = lodash.clamp(insertIndex, this.colActionLimit.min, this.colActionLimit.max);
|
|
2453
|
+
const createdColumns = Array.from({ length: count }).map(() => createDefaultColumnConfig());
|
|
2454
|
+
newColumns.splice(index, 0, ...createdColumns);
|
|
2455
|
+
this.instance.updateColumns(newColumns);
|
|
2456
|
+
return {
|
|
2457
|
+
oldColumns: columns,
|
|
2458
|
+
newColumns
|
|
2459
|
+
};
|
|
2460
|
+
}
|
|
2461
|
+
/**
|
|
2462
|
+
* 删除列
|
|
2463
|
+
*/
|
|
2464
|
+
removeColumn(count, startIndex) {
|
|
2465
|
+
if (this.lock) throw new Error("\u9501\u5B9A\u8868\u683C\uFF0C\u4E0D\u5141\u8BB8\u5220\u9664\u5217");
|
|
2466
|
+
const oldColumns = [...this.instance.columns];
|
|
2467
|
+
const newColumns = [...this.instance.columns];
|
|
2468
|
+
const min = this.colActionLimit.min;
|
|
2469
|
+
const max = this.colActionLimit.max;
|
|
2470
|
+
const plannedIndexes = Array.from({ length: count }, (_, i) => startIndex + i);
|
|
2471
|
+
const inRangeIndexes = plannedIndexes.filter((i) => i >= min && i <= max);
|
|
2472
|
+
if (inRangeIndexes.length === 0) {
|
|
2473
|
+
console.warn(
|
|
2474
|
+
`[removeColumn] \u6CA1\u6709\u4EFB\u4F55\u5217\u843D\u5728\u53EF\u64CD\u4F5C\u8303\u56F4\u5185\u3002startIndex=${startIndex}, count=${count}, \u8303\u56F4=[${min}, ${max}]`
|
|
2475
|
+
);
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
const removableIndexes = inRangeIndexes.filter((i) => isColumnEditable(this.instance, i));
|
|
2479
|
+
const notEditableIndexes = inRangeIndexes.filter((i) => !isColumnEditable(this.instance, i));
|
|
2480
|
+
if (notEditableIndexes.length > 0) {
|
|
2481
|
+
console.warn(`[removeColumn] \u4EE5\u4E0B\u5217\u88AB\u9501\u5B9A\uFF0C\u4E0D\u53C2\u4E0E\u5220\u9664: ${notEditableIndexes.join(", ")}`);
|
|
2482
|
+
}
|
|
2483
|
+
if (removableIndexes.length === 0) {
|
|
2484
|
+
console.warn(`[removeColumn] \u53EF\u64CD\u4F5C\u8303\u56F4\u5185\u7684\u5217\u5747\u4E0D\u53EF\u5220\u9664\u3002startIndex=${startIndex}, count=${count}`);
|
|
2485
|
+
return;
|
|
2486
|
+
}
|
|
2487
|
+
removableIndexes.sort((a, b) => b - a);
|
|
2488
|
+
removableIndexes.forEach((index) => {
|
|
2489
|
+
newColumns.splice(index, 1);
|
|
2490
|
+
});
|
|
2491
|
+
this.instance.updateColumns(newColumns);
|
|
2492
|
+
return {
|
|
2493
|
+
oldColumns,
|
|
2494
|
+
newColumns
|
|
2495
|
+
};
|
|
2496
|
+
}
|
|
2497
|
+
/**
|
|
2498
|
+
* 复制列
|
|
2499
|
+
* @param sourceIndex 要复制的列索引
|
|
2500
|
+
* @param insertIndex 插入位置,默认在源列之后
|
|
2501
|
+
*/
|
|
2502
|
+
copyColumn(sourceIndex, insertIndex = sourceIndex + 1) {
|
|
2503
|
+
if (this.lock) throw new Error("\u9501\u5B9A\u8868\u683C\uFF0C\u4E0D\u5141\u8BB8\u590D\u5236\u5217");
|
|
2504
|
+
const oldColumns = [...this.instance.columns];
|
|
2505
|
+
const newColumns = [...this.instance.columns];
|
|
2506
|
+
const sourceColumn = oldColumns[sourceIndex];
|
|
2507
|
+
const newColumn = lodash.clone(sourceColumn);
|
|
2508
|
+
newColumn.field = id.getUUID();
|
|
2509
|
+
newColumn.title = `${newColumn.title} \u590D\u5236`;
|
|
2510
|
+
newColumns.splice(insertIndex, 0, newColumn);
|
|
2511
|
+
this.instance.updateColumns(newColumns);
|
|
2512
|
+
return {
|
|
2513
|
+
oldColumns,
|
|
2514
|
+
newColumns
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
/**
|
|
2518
|
+
* 冻结列
|
|
2519
|
+
* @param count 要冻结的列数
|
|
2520
|
+
* 注意:count >= 2,否则会将关键主列于checkbox拆分
|
|
2521
|
+
*/
|
|
2522
|
+
setFreezeCount(count) {
|
|
2523
|
+
if (this.lock) throw new Error("\u9501\u5B9A\u8868\u683C\uFF0C\u4E0D\u5141\u8BB8\u51BB\u7ED3\u5217");
|
|
2524
|
+
const oldFrozenColCount = this.instance.frozenColCount;
|
|
2525
|
+
const newFrozenColCount = count;
|
|
2526
|
+
this.instance.setFrozenColCount(count);
|
|
2527
|
+
return {
|
|
2528
|
+
oldValue: oldFrozenColCount,
|
|
2529
|
+
newValue: newFrozenColCount
|
|
2530
|
+
};
|
|
2531
|
+
}
|
|
2532
|
+
getCellOriginValue(col, row) {
|
|
2533
|
+
return this.instance.getCellOriginValue(col, row);
|
|
2534
|
+
}
|
|
2535
|
+
updateCell(col, row, value) {
|
|
2536
|
+
if (this.lock) throw new Error("\u9501\u5B9A\u8868\u683C\uFF0C\u4E0D\u5141\u8BB8\u4FEE\u6539\u5355\u5143\u683C\u6570\u636E");
|
|
2537
|
+
if (!isColumnEditable(this.instance, col)) throw new Error(`\u9501\u5B9A\u5217\uFF0C\u4E0D\u5141\u8BB8\u4FEE\u6539 column: ${col}`);
|
|
2538
|
+
const rowIndex = this.instance.getRecordShowIndexByCell(col, row);
|
|
2539
|
+
const oldValue = this.instance.getCellValue(col, row);
|
|
2540
|
+
const field = this.instance.columns[col].field;
|
|
2541
|
+
const record = this.instance.records[rowIndex];
|
|
2542
|
+
this.instance.updateRecords([{ ...record, [field]: value }], [rowIndex]);
|
|
2543
|
+
return {
|
|
2544
|
+
record,
|
|
2545
|
+
rowIndex,
|
|
2546
|
+
oldValue,
|
|
2547
|
+
newValue: value
|
|
2548
|
+
};
|
|
2549
|
+
}
|
|
2550
|
+
updateRecordsData(records) {
|
|
2551
|
+
records.forEach(([item]) => {
|
|
2552
|
+
const recordId = item[INNER_TABLE_RECORD_ID_KEY];
|
|
2553
|
+
this.recordsManager.set(recordId, item);
|
|
2554
|
+
});
|
|
2555
|
+
this.instance.updateRecords(
|
|
2556
|
+
records.map(([record]) => record),
|
|
2557
|
+
records.map(([, rowIndex]) => rowIndex)
|
|
2558
|
+
);
|
|
2559
|
+
}
|
|
2560
|
+
getCellStyle(col, row) {
|
|
2561
|
+
return this.instance.getCellStyle(col, row);
|
|
2562
|
+
}
|
|
2563
|
+
load() {
|
|
2564
|
+
this.cancels.push(
|
|
2565
|
+
...[
|
|
2566
|
+
() => this.event.destroy(),
|
|
2567
|
+
() => this.instance.release(),
|
|
2568
|
+
() => {
|
|
2569
|
+
const editorMap = getEditorTableStore();
|
|
2570
|
+
editorMap.delete(this.id);
|
|
2571
|
+
setEditorTableStore(new Map([...editorMap]));
|
|
2572
|
+
}
|
|
2573
|
+
]
|
|
2574
|
+
);
|
|
2575
|
+
}
|
|
2576
|
+
unload() {
|
|
2577
|
+
this.cancels.forEach((cancel) => cancel());
|
|
2578
|
+
}
|
|
2579
|
+
destroy() {
|
|
2580
|
+
super.destroy();
|
|
2581
|
+
this.unload();
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
const createBaseTableEditor = (config) => {
|
|
2585
|
+
const {
|
|
2586
|
+
id,
|
|
2587
|
+
onChange,
|
|
2588
|
+
columns,
|
|
2589
|
+
records,
|
|
2590
|
+
theme,
|
|
2591
|
+
commandManager,
|
|
2592
|
+
container,
|
|
2593
|
+
uploadFileFn,
|
|
2594
|
+
innerColumnControl,
|
|
2595
|
+
...rest
|
|
2596
|
+
} = config;
|
|
2597
|
+
const defaultChangeHandler = (e, payload) => {
|
|
2598
|
+
console.info("\u9ED8\u8BA4\u53D8\u66F4\u5904\u7406\u51FD\u6570", e, payload);
|
|
2599
|
+
};
|
|
2600
|
+
const dispatch = onChange ?? defaultChangeHandler;
|
|
2601
|
+
const frozenColCount = [innerColumnControl.checkbox, innerColumnControl.main].filter(Boolean).length;
|
|
2602
|
+
const options = {
|
|
2603
|
+
columns,
|
|
2604
|
+
records,
|
|
2605
|
+
theme,
|
|
2606
|
+
hover: {
|
|
2607
|
+
highlightMode: "cross"
|
|
2608
|
+
},
|
|
2609
|
+
customCellStyle: [core.CUSTOM_CELL_STYLE, core.CUSTOM_CELL_FOCUS_STYLE, core.CUSTOM_CELL_FEEDBACK_ERROR_STYLE],
|
|
2610
|
+
dragOrder: {
|
|
2611
|
+
dragHeaderMode: "column",
|
|
2612
|
+
// 仅启用列表头拖拽换位
|
|
2613
|
+
validateDragOrderOnEnd: (source, target) => {
|
|
2614
|
+
const tableEditor = getActiveEditorTable();
|
|
2615
|
+
if (!tableEditor) throw new Error("\u672A\u6FC0\u6D3B\u7684\u8868\u683C\u7F16\u8F91\u5668");
|
|
2616
|
+
if (source.col <= 1) return false;
|
|
2617
|
+
if (target.col <= 1) return false;
|
|
2618
|
+
if (target.col >= tableEditor.colCount - 2) return false;
|
|
2619
|
+
return true;
|
|
2620
|
+
}
|
|
2621
|
+
},
|
|
2622
|
+
// 如果有checkbox,前两列默认固定 一列checkbox 一列题目名称
|
|
2623
|
+
// 如果没有checkbox,第一列默认固定
|
|
2624
|
+
frozenColCount,
|
|
2625
|
+
defaultColWidth: 150,
|
|
2626
|
+
defaultRowHeight: core.TABLE_DEFAULT_ROW_HEIGHT,
|
|
2627
|
+
enableLineBreak: true,
|
|
2628
|
+
heightMode: "standard",
|
|
2629
|
+
editCellTrigger: "api",
|
|
2630
|
+
showHeader: true,
|
|
2631
|
+
...rest
|
|
2632
|
+
};
|
|
2633
|
+
const editor = new TableEditor(id, container, dispatch, options, commandManager, uploadFileFn, innerColumnControl);
|
|
2634
|
+
return editor;
|
|
2635
|
+
};
|
|
2636
|
+
|
|
2637
|
+
const TableView = ({}) => {
|
|
2638
|
+
const {
|
|
2639
|
+
id,
|
|
2640
|
+
editorRef,
|
|
2641
|
+
containerRef,
|
|
2642
|
+
records,
|
|
2643
|
+
columns,
|
|
2644
|
+
theme,
|
|
2645
|
+
commandManager,
|
|
2646
|
+
onChange,
|
|
2647
|
+
uploadFileFn,
|
|
2648
|
+
innerColumnControl,
|
|
2649
|
+
disabled,
|
|
2650
|
+
maxHeight,
|
|
2651
|
+
debug,
|
|
2652
|
+
...rest
|
|
2653
|
+
} = useComponentVTable();
|
|
2654
|
+
const [recordsState] = React.useState(records);
|
|
2655
|
+
const innerColumnControlState = React.useMemo(() => {
|
|
2656
|
+
return {
|
|
2657
|
+
main: innerColumnControl.main,
|
|
2658
|
+
plus: innerColumnControl.plus,
|
|
2659
|
+
checkbox: innerColumnControl.checkbox
|
|
2660
|
+
};
|
|
2661
|
+
}, [innerColumnControl.checkbox, innerColumnControl.main, innerColumnControl.plus]);
|
|
2662
|
+
React.useEffect(() => {
|
|
2663
|
+
if (!editorRef.current) return;
|
|
2664
|
+
editorRef.current.lock = disabled;
|
|
2665
|
+
editorRef.current.debug = debug;
|
|
2666
|
+
}, [disabled, editorRef, debug]);
|
|
2667
|
+
const adaptedData = React.useMemo(() => {
|
|
2668
|
+
const adaptedColumns = adaptColumnStructure(columns, innerColumnControlState);
|
|
2669
|
+
const adaptedRecords = adaptRecordsStructure(recordsState, adaptedColumns.columns, innerColumnControlState);
|
|
2670
|
+
return {
|
|
2671
|
+
columns: adaptedColumns.columns,
|
|
2672
|
+
records: adaptedRecords.records,
|
|
2673
|
+
highlight: highlightMerge(adaptedRecords.feedbacksHighlight, adaptedColumns.feedbacksHighlight)
|
|
2674
|
+
};
|
|
2675
|
+
}, [columns, innerColumnControlState, recordsState]);
|
|
2676
|
+
React.useEffect(() => {
|
|
2677
|
+
if (!containerRef.current) return;
|
|
2678
|
+
if (editorRef.current) {
|
|
2679
|
+
editorRef.current.updateColumns(adaptedData.columns);
|
|
2680
|
+
editorRef.current.innerColumnControl = innerColumnControl;
|
|
2681
|
+
return;
|
|
2682
|
+
}
|
|
2683
|
+
editorRef.current = createBaseTableEditor({
|
|
2684
|
+
id,
|
|
2685
|
+
onChange,
|
|
2686
|
+
container: containerRef.current,
|
|
2687
|
+
columns: adaptedData.columns,
|
|
2688
|
+
records: adaptedData.records,
|
|
2689
|
+
theme,
|
|
2690
|
+
commandManager,
|
|
2691
|
+
uploadFileFn,
|
|
2692
|
+
innerColumnControl,
|
|
2693
|
+
...rest
|
|
2694
|
+
});
|
|
2695
|
+
editorRef.current.lock = disabled;
|
|
2696
|
+
editorRef.current.debug = debug;
|
|
2697
|
+
return () => {
|
|
2698
|
+
editorRef.current?.destroy();
|
|
2699
|
+
editorRef.current = null;
|
|
2700
|
+
};
|
|
2701
|
+
}, []);
|
|
2702
|
+
React.useEffect(() => {
|
|
2703
|
+
if (!editorRef.current) return;
|
|
2704
|
+
editorRef.current.updateColumns(adaptedData.columns);
|
|
2705
|
+
}, [adaptedData.columns, editorRef]);
|
|
2706
|
+
React.useEffect(() => {
|
|
2707
|
+
if (!editorRef.current) return;
|
|
2708
|
+
const highlight = adaptedData.highlight;
|
|
2709
|
+
const highlightCellsGroup = Object.entries(highlight).map(([styleKey, cells]) => {
|
|
2710
|
+
return {
|
|
2711
|
+
styleKey,
|
|
2712
|
+
cells
|
|
2713
|
+
};
|
|
2714
|
+
});
|
|
2715
|
+
highlightCellsGroup.forEach((group) => {
|
|
2716
|
+
if (!editorRef.current) return;
|
|
2717
|
+
const cells = group.cells.map((cell) => {
|
|
2718
|
+
if (cell.type === "cell") return { row: cell.row, col: cell.col };
|
|
2719
|
+
else if (cell.type === "row") {
|
|
2720
|
+
return {
|
|
2721
|
+
range: {
|
|
2722
|
+
start: { col: 0 + 1, row: cell.row + 1 },
|
|
2723
|
+
end: { col: editorRef.current.colCount, row: cell.row }
|
|
2724
|
+
}
|
|
2725
|
+
};
|
|
2726
|
+
} else if (cell.type === "column") {
|
|
2727
|
+
return {
|
|
2728
|
+
range: {
|
|
2729
|
+
start: { col: cell.col, row: 0 },
|
|
2730
|
+
end: { col: cell.col, row: editorRef.current.rowCount }
|
|
2731
|
+
}
|
|
2732
|
+
};
|
|
2733
|
+
} else throw new Error(`Unknown cell type ${cell.type}`);
|
|
2734
|
+
});
|
|
2735
|
+
editorRef.current.highlightCells(group.styleKey, cells);
|
|
2736
|
+
});
|
|
2737
|
+
editorRef.current.innerColumnControl = innerColumnControlState;
|
|
2738
|
+
editorRef.current.updateColumns(adaptedData.columns);
|
|
2739
|
+
}, [editorRef, adaptedData.highlight, innerColumnControlState, adaptedData.columns]);
|
|
2740
|
+
const [recordCount, setRecordCount] = React.useState(adaptedData.records.length);
|
|
2741
|
+
React.useEffect(() => {
|
|
2742
|
+
if (!editorRef.current) {
|
|
2743
|
+
setRecordCount(0);
|
|
2744
|
+
return;
|
|
2745
|
+
}
|
|
2746
|
+
const sizeUpdate = () => {
|
|
2747
|
+
if (!editorRef.current) setRecordCount(0);
|
|
2748
|
+
else setRecordCount(window.store.get(editorRef.current.recordsManager.size));
|
|
2749
|
+
};
|
|
2750
|
+
const cancel = window.store.sub(editorRef.current.recordsManager.size, sizeUpdate);
|
|
2751
|
+
return () => cancel();
|
|
2752
|
+
}, [editorRef, adaptedData.records, recordCount]);
|
|
2753
|
+
const calcHeight = React.useMemo(() => {
|
|
2754
|
+
if (!maxHeight) return "100%";
|
|
2755
|
+
const calHeight = recordCount * core.TABLE_DEFAULT_ROW_HEIGHT + core.TABLE_DEFAULT_ROW_HEIGHT + 2;
|
|
2756
|
+
const height = lodash.max([lodash.min([calHeight, maxHeight]), core.TABLE_DEFAULT_ROW_HEIGHT]);
|
|
2757
|
+
return height;
|
|
2758
|
+
}, [recordCount, maxHeight]);
|
|
2759
|
+
return /* @__PURE__ */ React.createElement(
|
|
2760
|
+
"div",
|
|
2761
|
+
{
|
|
2762
|
+
contentEditable: false,
|
|
2763
|
+
className: `table-wrapper`,
|
|
2764
|
+
style: { width: "100%", height: calcHeight, position: "relative" }
|
|
2765
|
+
},
|
|
2766
|
+
/* @__PURE__ */ React.createElement("div", { className: "table-container", ref: containerRef, style: { width: "100%", height: "100%" } }),
|
|
2767
|
+
/* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(TableSelectEditor, null), /* @__PURE__ */ React.createElement(LinkEditor, null), /* @__PURE__ */ React.createElement(UserShow, null), /* @__PURE__ */ React.createElement(DateSelect, null), /* @__PURE__ */ React.createElement(TextEditor, null), /* @__PURE__ */ React.createElement(NumEditor, null), /* @__PURE__ */ React.createElement(TableJsonEditor, null)),
|
|
2768
|
+
/* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(CellContextMenu, null), /* @__PURE__ */ React.createElement(HeaderContextMenu, null), /* @__PURE__ */ React.createElement(MoreContextMenu, null))
|
|
2769
|
+
);
|
|
2770
|
+
};
|
|
2771
|
+
const TableLayout = () => {
|
|
2772
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(TableView, null), /* @__PURE__ */ React.createElement(Hotkeys, null));
|
|
2773
|
+
};
|
|
2774
|
+
const Table = (props) => {
|
|
2775
|
+
return /* @__PURE__ */ React.createElement(VTableProvider, { ...props }, /* @__PURE__ */ React.createElement(TableLayout, null));
|
|
2776
|
+
};
|
|
2777
|
+
|
|
2778
|
+
const MenuItemInputLabel = ({ icon, direction, type, onCellClick, disabled }) => {
|
|
2779
|
+
const menu = useMenu();
|
|
2780
|
+
const tableEditor = useActiveEditorTable();
|
|
2781
|
+
if (!menu) throw new Error("menu \u5FC5\u987B\u5B58\u5728");
|
|
2782
|
+
if (!tableEditor) throw new Error("tableEditor \u5FC5\u987B\u5B58\u5728");
|
|
2783
|
+
const [inputValue, setInputValue] = React.useState(1);
|
|
2784
|
+
const directionLabel = React.useMemo(() => {
|
|
2785
|
+
if (direction === "left") return "\u5DE6";
|
|
2786
|
+
if (direction === "right") return "\u53F3";
|
|
2787
|
+
if (direction === "up") return "\u4E0A";
|
|
2788
|
+
if (direction === "down") return "\u4E0B";
|
|
2789
|
+
}, [direction]);
|
|
2790
|
+
const onClick = (e) => {
|
|
2791
|
+
onCellClick?.({ cell: menu.cell, tableEditor, e }, inputValue);
|
|
2792
|
+
};
|
|
2793
|
+
return /* @__PURE__ */ React.createElement(antd.Flex, { align: "center", onClick, gap: 10 }, icon, /* @__PURE__ */ React.createElement(antd.Flex, { gap: 10, style: { width: "100%" }, align: "center" }, /* @__PURE__ */ React.createElement("span", null, "\u5411", directionLabel, "\u63D2\u5165"), /* @__PURE__ */ React.createElement(
|
|
2794
|
+
antd.InputNumber,
|
|
2795
|
+
{
|
|
2796
|
+
defaultValue: 1,
|
|
2797
|
+
disabled,
|
|
2798
|
+
rootClassName: "menu-item-label-input",
|
|
2799
|
+
onClick: (e) => {
|
|
2800
|
+
e.stopPropagation();
|
|
2801
|
+
},
|
|
2802
|
+
style: { width: 40 },
|
|
2803
|
+
value: inputValue,
|
|
2804
|
+
onChange: (value) => setInputValue(value || 1),
|
|
2805
|
+
controls: false
|
|
2806
|
+
}
|
|
2807
|
+
), /* @__PURE__ */ React.createElement("span", null, type === "row" ? "\u884C" : "\u5217")));
|
|
2808
|
+
};
|
|
2809
|
+
|
|
2810
|
+
function initEditorTool(type, value) {
|
|
2811
|
+
switch (type) {
|
|
2812
|
+
case 30:
|
|
2813
|
+
case 29:
|
|
2814
|
+
initSelectEditorTool(value);
|
|
2815
|
+
break;
|
|
2816
|
+
case 33:
|
|
2817
|
+
initLinkEditorTool(value);
|
|
2818
|
+
break;
|
|
2819
|
+
case 36:
|
|
2820
|
+
initDateEditorTool(value);
|
|
2821
|
+
break;
|
|
2822
|
+
case 31:
|
|
2823
|
+
initNumEditorTool(value);
|
|
2824
|
+
break;
|
|
2825
|
+
case 28:
|
|
2826
|
+
initTextEditorTool(value);
|
|
2827
|
+
break;
|
|
2828
|
+
case 34:
|
|
2829
|
+
initJsonEditorTool(value);
|
|
2830
|
+
break;
|
|
2831
|
+
case 38:
|
|
2832
|
+
break;
|
|
2833
|
+
default:
|
|
2834
|
+
throw new Error(`[initEditorTool] \u4E0D\u652F\u6301\u7684\u5DE5\u5177\u7C7B\u578B ${type}`);
|
|
2835
|
+
}
|
|
2836
|
+
}
|
|
2837
|
+
const clearEditorTool = () => {
|
|
2838
|
+
clearSelectEditorTool();
|
|
2839
|
+
clearLinkEditorTool();
|
|
2840
|
+
clearDateEditorTool();
|
|
2841
|
+
clearTextEditorTool();
|
|
2842
|
+
clearNumEditorTool();
|
|
2843
|
+
clearJsonEditorTool();
|
|
2844
|
+
};
|
|
2845
|
+
|
|
2846
|
+
class DateSelectEditorTool {
|
|
2847
|
+
onStart(props) {
|
|
2848
|
+
const { col, row, table, value, endEdit } = props;
|
|
2849
|
+
this.row = row;
|
|
2850
|
+
this.col = col;
|
|
2851
|
+
this.table = table;
|
|
2852
|
+
this.oldValue = value;
|
|
2853
|
+
const rect = table.getCellRelativeRect?.(col, row);
|
|
2854
|
+
if (!rect) throw new Error("[DateSelectEditorTool::onStart] rect is Nil");
|
|
2855
|
+
initEditorTool(36, {
|
|
2856
|
+
cell: {
|
|
2857
|
+
col,
|
|
2858
|
+
row,
|
|
2859
|
+
position: { x: rect.left, y: rect.top },
|
|
2860
|
+
width: rect.width,
|
|
2861
|
+
height: rect.height
|
|
2862
|
+
},
|
|
2863
|
+
endEdit,
|
|
2864
|
+
table,
|
|
2865
|
+
initialValue: value?.value
|
|
2866
|
+
});
|
|
2867
|
+
}
|
|
2868
|
+
//校验
|
|
2869
|
+
validateValue(newValue, oldValue) {
|
|
2870
|
+
this.newValue = newValue;
|
|
2871
|
+
this.oldValue = oldValue;
|
|
2872
|
+
return VTable_editors.ValidateEnum.invalidateExit;
|
|
2873
|
+
}
|
|
2874
|
+
setValue() {
|
|
2875
|
+
}
|
|
2876
|
+
// 结束编辑时触发,返回编辑后的值
|
|
2877
|
+
getValue() {
|
|
2878
|
+
return { ...this.oldValue, value: getDateEditorValue() };
|
|
2879
|
+
}
|
|
2880
|
+
// 退出编辑状态
|
|
2881
|
+
onEnd() {
|
|
2882
|
+
const tableEditor = getActiveEditorTable();
|
|
2883
|
+
if (lodash.isNil(this.col) || lodash.isNil(this.row)) return;
|
|
2884
|
+
if (!tableEditor) {
|
|
2885
|
+
throw new Error("[DateSelectEditorTool::onEnd] tableEditor is Nil");
|
|
2886
|
+
}
|
|
2887
|
+
const command = new EditTableCellDataCommand(tableEditor, this.col, this.row, this.newValue, this.oldValue);
|
|
2888
|
+
tableEditor.commandManager.execute(command);
|
|
2889
|
+
clearEditorTool();
|
|
2890
|
+
}
|
|
2891
|
+
isEditorElement(target) {
|
|
2892
|
+
return !!target.closest(".ant-picker-dropdown");
|
|
2893
|
+
}
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2896
|
+
class JsonEditorTool {
|
|
2897
|
+
// 双击单元格触发,进入编辑状态
|
|
2898
|
+
onStart(props) {
|
|
2899
|
+
const { col, row, table, value, endEdit } = props;
|
|
2900
|
+
this.row = row;
|
|
2901
|
+
this.col = col;
|
|
2902
|
+
this.table = table;
|
|
2903
|
+
this.oldValue = value;
|
|
2904
|
+
const rect = table.getCellRelativeRect(col, row);
|
|
2905
|
+
if (!rect) throw new Error("[LinkEditor::onStart] rect is Nil");
|
|
2906
|
+
initEditorTool(34, {
|
|
2907
|
+
cell: {
|
|
2908
|
+
col,
|
|
2909
|
+
row,
|
|
2910
|
+
position: { x: rect.left, y: rect.top },
|
|
2911
|
+
width: rect.width,
|
|
2912
|
+
height: rect.height
|
|
2913
|
+
},
|
|
2914
|
+
endEdit,
|
|
2915
|
+
table,
|
|
2916
|
+
initialValue: value?.value
|
|
2917
|
+
});
|
|
2918
|
+
}
|
|
2919
|
+
validateValue(newValue, oldValue) {
|
|
2920
|
+
this.newValue = newValue;
|
|
2921
|
+
this.oldValue = oldValue;
|
|
2922
|
+
return VTable_editors.ValidateEnum.invalidateExit;
|
|
2923
|
+
}
|
|
2924
|
+
// 不可删除,否则会报错
|
|
2925
|
+
setValue() {
|
|
2926
|
+
}
|
|
2927
|
+
// 结束编辑时触发,返回编辑后的值
|
|
2928
|
+
getValue() {
|
|
2929
|
+
return { ...this.oldValue, value: getJsonEditorValue() };
|
|
2930
|
+
}
|
|
2931
|
+
// 退出编辑状态
|
|
2932
|
+
onEnd() {
|
|
2933
|
+
if (lodash.isNil(this.col) || lodash.isNil(this.row)) return;
|
|
2934
|
+
const tableEditor = getActiveEditorTable();
|
|
2935
|
+
if (!tableEditor) throw new Error("[JsonEditor::onEnd] tableEditor is Nil");
|
|
2936
|
+
if (lodash.isNil(this.col) || lodash.isNil(this.row)) throw new Error("[JsonEditor::onEnd] col or row is Nil");
|
|
2937
|
+
const command = new EditTableCellDataCommand(tableEditor, this.col, this.row, this.newValue, this.oldValue);
|
|
2938
|
+
tableEditor.commandManager.execute(command);
|
|
2939
|
+
clearEditorTool();
|
|
2940
|
+
}
|
|
2941
|
+
/**
|
|
2942
|
+
* 如果提供了此函数,VTable 将会在用户点击其他地方时调用此函数。
|
|
2943
|
+
* 如果此函数返回了一个假值,VTable 将会调用 `onEnd` 并退出编辑状态。
|
|
2944
|
+
* 如果未定义此函数或此函数返回了一个真值, VTable 将不会做任何事。
|
|
2945
|
+
* 这意味着,你需要手动调用 `onStart` 中提供的 `endEdit` 来结束编辑模式。
|
|
2946
|
+
*/
|
|
2947
|
+
isEditorElement(target) {
|
|
2948
|
+
return !!target.closest(".json-editor-modal-container");
|
|
2949
|
+
}
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2952
|
+
class LinkEditorTool {
|
|
2953
|
+
// 双击单元格触发,进入编辑状态
|
|
2954
|
+
onStart(props) {
|
|
2955
|
+
const { col, row, table, value, endEdit } = props;
|
|
2956
|
+
this.row = row;
|
|
2957
|
+
this.col = col;
|
|
2958
|
+
this.table = table;
|
|
2959
|
+
this.oldValue = value;
|
|
2960
|
+
const rect = table.getCellRelativeRect(col, row);
|
|
2961
|
+
if (!rect) throw new Error("[LinkEditor::onStart] rect is Nil");
|
|
2962
|
+
initEditorTool(33, {
|
|
2963
|
+
cell: {
|
|
2964
|
+
col,
|
|
2965
|
+
row,
|
|
2966
|
+
position: { x: rect.left, y: rect.top },
|
|
2967
|
+
width: rect.width,
|
|
2968
|
+
height: rect.height
|
|
2969
|
+
},
|
|
2970
|
+
endEdit,
|
|
2971
|
+
table,
|
|
2972
|
+
initialValue: value?.value
|
|
2973
|
+
});
|
|
2974
|
+
}
|
|
2975
|
+
validateValue(newValue, oldValue) {
|
|
2976
|
+
this.newValue = newValue;
|
|
2977
|
+
this.oldValue = oldValue;
|
|
2978
|
+
return VTable_editors.ValidateEnum.invalidateExit;
|
|
2979
|
+
}
|
|
2980
|
+
// 不可删除,否则会报错
|
|
2981
|
+
setValue() {
|
|
2982
|
+
}
|
|
2983
|
+
// 结束编辑时触发,返回编辑后的值
|
|
2984
|
+
getValue() {
|
|
2985
|
+
return { ...this.oldValue, value: getLinkEditorValue() };
|
|
2986
|
+
}
|
|
2987
|
+
// 退出编辑状态
|
|
2988
|
+
onEnd() {
|
|
2989
|
+
if (lodash.isNil(this.col) || lodash.isNil(this.row)) return;
|
|
2990
|
+
const tableEditor = getActiveEditorTable();
|
|
2991
|
+
if (!tableEditor) throw new Error("[LinkEditor::onEnd] tableEditor is Nil");
|
|
2992
|
+
if (lodash.isNil(this.col) || lodash.isNil(this.row)) throw new Error("[LinkEditor::onEnd] col or row is Nil");
|
|
2993
|
+
const command = new EditTableCellDataCommand(tableEditor, this.col, this.row, this.newValue, this.oldValue);
|
|
2994
|
+
tableEditor.commandManager.execute(command);
|
|
2995
|
+
clearEditorTool();
|
|
2996
|
+
}
|
|
2997
|
+
/**
|
|
2998
|
+
* 如果提供了此函数,VTable 将会在用户点击其他地方时调用此函数。
|
|
2999
|
+
* 如果此函数返回了一个假值,VTable 将会调用 `onEnd` 并退出编辑状态。
|
|
3000
|
+
* 如果未定义此函数或此函数返回了一个真值, VTable 将不会做任何事。
|
|
3001
|
+
* 这意味着,你需要手动调用 `onStart` 中提供的 `endEdit` 来结束编辑模式。
|
|
3002
|
+
*/
|
|
3003
|
+
isEditorElement(target) {
|
|
3004
|
+
return !!target.closest(".link-editor-popover-root") || !!target.closest(".link-editor-popover");
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
|
|
3008
|
+
class NumEditorTool {
|
|
3009
|
+
// 双击单元格触发,进入编辑状态
|
|
3010
|
+
onStart(props) {
|
|
3011
|
+
const { col, row, table, value, endEdit } = props;
|
|
3012
|
+
this.row = row;
|
|
3013
|
+
this.col = col;
|
|
3014
|
+
this.oldValue = value;
|
|
3015
|
+
const rect = table.getCellRelativeRect(col, row);
|
|
3016
|
+
if (!rect) throw new Error("[NumEditor::onStart] rect is Nil");
|
|
3017
|
+
initEditorTool(31, {
|
|
3018
|
+
endEdit,
|
|
3019
|
+
initialValue: value?.value,
|
|
3020
|
+
table,
|
|
3021
|
+
cell: {
|
|
3022
|
+
col,
|
|
3023
|
+
row,
|
|
3024
|
+
position: { x: rect.left, y: rect.top },
|
|
3025
|
+
width: rect.width,
|
|
3026
|
+
height: rect.height
|
|
3027
|
+
}
|
|
3028
|
+
});
|
|
3029
|
+
}
|
|
3030
|
+
validateValue(newValue, oldValue) {
|
|
3031
|
+
this.newValue = newValue;
|
|
3032
|
+
this.oldValue = oldValue;
|
|
3033
|
+
return VTable_editors.ValidateEnum.invalidateExit;
|
|
3034
|
+
}
|
|
3035
|
+
setValue() {
|
|
3036
|
+
}
|
|
3037
|
+
// 结束编辑时触发,返回编辑后的值
|
|
3038
|
+
getValue() {
|
|
3039
|
+
return { ...this.oldValue, value: getNumEditorValue() };
|
|
3040
|
+
}
|
|
3041
|
+
// 退出编辑状态
|
|
3042
|
+
onEnd() {
|
|
3043
|
+
if (lodash.isNil(this.col) || lodash.isNil(this.row)) return;
|
|
3044
|
+
const tableEditor = getActiveEditorTable();
|
|
3045
|
+
if (!tableEditor) throw new Error("[NumEditor::onEnd] tableEditor is Nil");
|
|
3046
|
+
if (lodash.isNil(this.col) || lodash.isNil(this.row)) throw new Error("[NumEditor::onEnd] col or row is Nil");
|
|
3047
|
+
const command = new EditTableCellDataCommand(tableEditor, this.col, this.row, this.newValue, this.oldValue);
|
|
3048
|
+
tableEditor.commandManager.execute(command);
|
|
3049
|
+
clearEditorTool();
|
|
3050
|
+
}
|
|
3051
|
+
isEditorElement(target) {
|
|
3052
|
+
return target.className.includes("ant-input-number");
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
|
|
3056
|
+
class MultiSelectEditorTool {
|
|
3057
|
+
// 双击单元格触发,进入编辑状态
|
|
3058
|
+
onStart(props) {
|
|
3059
|
+
const { col, row, table, value, endEdit } = props;
|
|
3060
|
+
this.table = table;
|
|
3061
|
+
this.col = col;
|
|
3062
|
+
this.row = row;
|
|
3063
|
+
this.oldValue = value;
|
|
3064
|
+
const rect = table.getCellRelativeRect(col, row);
|
|
3065
|
+
if (!rect) throw new Error("[MultiSelectEditor::onStart] rect is Nil");
|
|
3066
|
+
const options = table.getBodyColumnDefine(col, 0)?.options || [];
|
|
3067
|
+
initEditorTool(30, {
|
|
3068
|
+
initialValue: value?.value ?? [],
|
|
3069
|
+
endEdit,
|
|
3070
|
+
options,
|
|
3071
|
+
table,
|
|
3072
|
+
cell: {
|
|
3073
|
+
col,
|
|
3074
|
+
row,
|
|
3075
|
+
position: { x: rect.left, y: rect.top },
|
|
3076
|
+
width: rect.width,
|
|
3077
|
+
height: rect.height
|
|
3078
|
+
},
|
|
3079
|
+
isMultiple: true
|
|
3080
|
+
});
|
|
3081
|
+
}
|
|
3082
|
+
validateValue(newValue, oldValue) {
|
|
3083
|
+
this.newValue = newValue;
|
|
3084
|
+
this.oldValue = oldValue;
|
|
3085
|
+
return VTable_editors.ValidateEnum.invalidateExit;
|
|
3086
|
+
}
|
|
3087
|
+
setValue() {
|
|
3088
|
+
}
|
|
3089
|
+
// 结束编辑时触发,返回编辑后的值
|
|
3090
|
+
getValue() {
|
|
3091
|
+
return { ...this.oldValue, value: getSelectEditorValue() };
|
|
3092
|
+
}
|
|
3093
|
+
// 退出编辑状态
|
|
3094
|
+
onEnd() {
|
|
3095
|
+
clearEditorTool();
|
|
3096
|
+
}
|
|
3097
|
+
/**
|
|
3098
|
+
* 如果提供了此函数,VTable 将会在用户点击其他地方时调用此函数。
|
|
3099
|
+
* 如果此函数返回了一个假值,VTable 将会调用 `onEnd` 并退出编辑状态。
|
|
3100
|
+
* 如果未定义此函数或此函数返回了一个真值, VTable 将不会做任何事。
|
|
3101
|
+
* 这意味着,你需要手动调用 `onStart` 中提供的 `endEdit` 来结束编辑模式。
|
|
3102
|
+
*/
|
|
3103
|
+
isEditorElement(target) {
|
|
3104
|
+
return !!target.closest(".multi-select-editor-popover-root") || !!target.closest(".multi-select-editor-popover") || !!target.closest(".selector-color-picker") || !!target.closest(".option-item-modal");
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
class SingleSelectEditorTool {
|
|
3109
|
+
// 双击单元格触发,进入编辑状态
|
|
3110
|
+
onStart(props) {
|
|
3111
|
+
const { col, row, table, value, endEdit } = props;
|
|
3112
|
+
this.table = table;
|
|
3113
|
+
this.col = col;
|
|
3114
|
+
this.row = row;
|
|
3115
|
+
this.oldValue = value;
|
|
3116
|
+
const rect = table.getCellRelativeRect(col, row);
|
|
3117
|
+
if (!rect) throw new Error("[SingleSelectEditor::onStart] rect is Nil");
|
|
3118
|
+
const options = table.getBodyColumnDefine(col, 0)?.options || [];
|
|
3119
|
+
initEditorTool(29, {
|
|
3120
|
+
initialValue: value?.value ?? [],
|
|
3121
|
+
endEdit,
|
|
3122
|
+
options,
|
|
3123
|
+
table,
|
|
3124
|
+
cell: {
|
|
3125
|
+
col,
|
|
3126
|
+
row,
|
|
3127
|
+
position: { x: rect.left, y: rect.top },
|
|
3128
|
+
width: rect.width,
|
|
3129
|
+
height: rect.height
|
|
3130
|
+
},
|
|
3131
|
+
isMultiple: false
|
|
3132
|
+
});
|
|
3133
|
+
}
|
|
3134
|
+
validateValue(newValue, oldValue) {
|
|
3135
|
+
this.newValue = newValue;
|
|
3136
|
+
this.oldValue = oldValue;
|
|
3137
|
+
return VTable_editors.ValidateEnum.invalidateExit;
|
|
3138
|
+
}
|
|
3139
|
+
setValue() {
|
|
3140
|
+
}
|
|
3141
|
+
// 结束编辑时触发,返回编辑后的值
|
|
3142
|
+
getValue() {
|
|
3143
|
+
return { ...this.oldValue, value: getSelectEditorValue() };
|
|
3144
|
+
}
|
|
3145
|
+
// 退出编辑状态
|
|
3146
|
+
onEnd() {
|
|
3147
|
+
clearEditorTool();
|
|
3148
|
+
}
|
|
3149
|
+
/**
|
|
3150
|
+
* 如果提供了此函数,VTable 将会在用户点击其他地方时调用此函数。
|
|
3151
|
+
* 如果此函数返回了一个假值,VTable 将会调用 `onEnd` 并退出编辑状态。
|
|
3152
|
+
* 如果未定义此函数或此函数返回了一个真值, VTable 将不会做任何事。
|
|
3153
|
+
* 这意味着,你需要手动调用 `onStart` 中提供的 `endEdit` 来结束编辑模式。
|
|
3154
|
+
*/
|
|
3155
|
+
isEditorElement(target) {
|
|
3156
|
+
return !!target.closest(".multi-select-editor-popover-root") || !!target.closest(".multi-select-editor-popover") || !!target.closest(".selector-color-picker") || !!target.closest(".option-item-modal");
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3159
|
+
|
|
3160
|
+
class TextEditorTool {
|
|
3161
|
+
// 双击单元格触发,进入编辑状态
|
|
3162
|
+
onStart(props) {
|
|
3163
|
+
const { col, row, table, value, endEdit } = props;
|
|
3164
|
+
this.row = row;
|
|
3165
|
+
this.col = col;
|
|
3166
|
+
this.oldValue = value;
|
|
3167
|
+
const rect = table.getCellRelativeRect(col, row);
|
|
3168
|
+
if (!rect) throw new Error("[TextEditor::onStart] rect is Nil");
|
|
3169
|
+
initEditorTool(28, {
|
|
3170
|
+
endEdit,
|
|
3171
|
+
initialValue: value?.value ?? "",
|
|
3172
|
+
table,
|
|
3173
|
+
cell: {
|
|
3174
|
+
col,
|
|
3175
|
+
row,
|
|
3176
|
+
position: { x: rect.left, y: rect.top },
|
|
3177
|
+
width: rect.width,
|
|
3178
|
+
height: rect.height
|
|
3179
|
+
}
|
|
3180
|
+
});
|
|
3181
|
+
}
|
|
3182
|
+
validateValue(newValue, oldValue) {
|
|
3183
|
+
this.newValue = newValue;
|
|
3184
|
+
this.oldValue = oldValue;
|
|
3185
|
+
return VTable_editors.ValidateEnum.invalidateExit;
|
|
3186
|
+
}
|
|
3187
|
+
setValue() {
|
|
3188
|
+
}
|
|
3189
|
+
// 结束编辑时触发,返回编辑后的值
|
|
3190
|
+
getValue() {
|
|
3191
|
+
return { ...this.oldValue, value: getTextEditorValue() };
|
|
3192
|
+
}
|
|
3193
|
+
// 退出编辑状态
|
|
3194
|
+
onEnd() {
|
|
3195
|
+
if (lodash.isNil(this.col) || lodash.isNil(this.row)) return;
|
|
3196
|
+
const tableEditor = getActiveEditorTable();
|
|
3197
|
+
if (!tableEditor) throw new Error("[TextEditor::onEnd] tableEditor is Nil");
|
|
3198
|
+
if (lodash.isNil(this.col) || lodash.isNil(this.row)) throw new Error("[TextEditor::onEnd] col or row is Nil");
|
|
3199
|
+
const command = new EditTableCellDataCommand(tableEditor, this.col, this.row, this.newValue, this.oldValue);
|
|
3200
|
+
tableEditor.commandManager.execute(command);
|
|
3201
|
+
clearEditorTool();
|
|
3202
|
+
}
|
|
3203
|
+
isEditorElement(target) {
|
|
3204
|
+
return target.className.includes("ant-input");
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
|
|
3208
|
+
const inputEditor = new VTable_editors__namespace.InputEditor();
|
|
3209
|
+
const dateInputEditor = new VTable_editors__namespace.DateInputEditor();
|
|
3210
|
+
const textAreaEditor = new VTable_editors__namespace.TextAreaEditor({ readonly: false });
|
|
3211
|
+
const linkEditor = new LinkEditorTool();
|
|
3212
|
+
const dateRangeEditor = new DateSelectEditorTool();
|
|
3213
|
+
const textEditor = new TextEditorTool();
|
|
3214
|
+
const numberEditor = new NumEditorTool();
|
|
3215
|
+
const multiSelectEditor = new MultiSelectEditorTool();
|
|
3216
|
+
const singleSelectEditor = new SingleSelectEditorTool();
|
|
3217
|
+
const jsonEditor = new JsonEditorTool();
|
|
3218
|
+
const editorRegistry = () => {
|
|
3219
|
+
VTable__namespace.register.editor("inputEditor", inputEditor);
|
|
3220
|
+
VTable__namespace.register.editor("dateInputEditor", dateInputEditor);
|
|
3221
|
+
VTable__namespace.register.editor("textAreaEditor", textAreaEditor);
|
|
3222
|
+
VTable__namespace.register.editor("multiSelectEditor", multiSelectEditor);
|
|
3223
|
+
VTable__namespace.register.editor("linkEditor", linkEditor);
|
|
3224
|
+
VTable__namespace.register.editor("dateInputEditor", dateRangeEditor);
|
|
3225
|
+
VTable__namespace.register.editor("textEditor", textEditor);
|
|
3226
|
+
VTable__namespace.register.editor("numberEditor", numberEditor);
|
|
3227
|
+
VTable__namespace.register.editor("singleSelectEditor", singleSelectEditor);
|
|
3228
|
+
VTable__namespace.register.editor("jsonEditor", jsonEditor);
|
|
3229
|
+
};
|
|
3230
|
+
|
|
3231
|
+
const padding = 4;
|
|
3232
|
+
const createIconGraphics = (name, props) => {
|
|
3233
|
+
const { disabled, cursor, x = 0, y = 0, size = 20, color = core.COLOR_ICON, hoverBg, onClick } = props ?? {};
|
|
3234
|
+
const u = fontIconEnableaiBase.EnableAIBaseFontIcon.get(name, "unicode");
|
|
3235
|
+
const group = vrender.createGroup({
|
|
3236
|
+
display: "flex",
|
|
3237
|
+
x,
|
|
3238
|
+
y,
|
|
3239
|
+
width: size + padding,
|
|
3240
|
+
height: size + padding,
|
|
3241
|
+
cornerRadius: 4,
|
|
3242
|
+
cursor: disabled ? void 0 : cursor,
|
|
3243
|
+
alignContent: "center",
|
|
3244
|
+
alignItems: "center",
|
|
3245
|
+
justifyContent: "center"
|
|
3246
|
+
});
|
|
3247
|
+
const text = vrender.createText({
|
|
3248
|
+
text: u,
|
|
3249
|
+
fontSize: size,
|
|
3250
|
+
fontFamily: fontIconEnableaiBase.EnableAIBaseFontIcon.fontFamily,
|
|
3251
|
+
fill: color,
|
|
3252
|
+
cursor: disabled ? void 0 : cursor,
|
|
3253
|
+
textBaseline: "alphabetic"
|
|
3254
|
+
});
|
|
3255
|
+
if (hoverBg && !disabled) {
|
|
3256
|
+
group.addEventListener("mouseover", () => {
|
|
3257
|
+
group.setAttribute("background", "#f0f0f0");
|
|
3258
|
+
group.stage?.renderNextFrame();
|
|
3259
|
+
});
|
|
3260
|
+
group.addEventListener("mouseleave", () => {
|
|
3261
|
+
group.setAttribute("background", "");
|
|
3262
|
+
group.stage?.renderNextFrame();
|
|
3263
|
+
});
|
|
3264
|
+
if (onClick) group.addEventListener("click", onClick);
|
|
3265
|
+
}
|
|
3266
|
+
group.add(text);
|
|
3267
|
+
return group;
|
|
3268
|
+
};
|
|
3269
|
+
|
|
3270
|
+
const createPlusHeaderGraphics = (props) => {
|
|
3271
|
+
const { table, row, col, rect } = props;
|
|
3272
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
3273
|
+
const group = vrender.createGroup({
|
|
3274
|
+
display: "flex",
|
|
3275
|
+
alignContent: "center",
|
|
3276
|
+
alignItems: "center",
|
|
3277
|
+
justifyContent: "center",
|
|
3278
|
+
width,
|
|
3279
|
+
height,
|
|
3280
|
+
cursor: "pointer"
|
|
3281
|
+
});
|
|
3282
|
+
const icon = createIconGraphics("plus", {
|
|
3283
|
+
cursor: "pointer"
|
|
3284
|
+
});
|
|
3285
|
+
group.add(icon);
|
|
3286
|
+
group.addEventListener("click", () => {
|
|
3287
|
+
const editor = getActiveEditorTable();
|
|
3288
|
+
if (!editor) throw new Error("[createPlusHeaderGraphics::onClick]editor is not found");
|
|
3289
|
+
editor.dispatch("column::add::from::inner::plus", {
|
|
3290
|
+
editor
|
|
3291
|
+
});
|
|
3292
|
+
});
|
|
3293
|
+
return group;
|
|
3294
|
+
};
|
|
3295
|
+
|
|
3296
|
+
dayjs.extend(utc);
|
|
3297
|
+
dayjs.extend(timezone);
|
|
3298
|
+
dayjs.extend(customParseFormat);
|
|
3299
|
+
const FIXED_TIMEZONE_LABEL = "(GMT+8)";
|
|
3300
|
+
const createDateGraphics = (props) => {
|
|
3301
|
+
const { table, row, col, rect } = props;
|
|
3302
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
3303
|
+
const loading = !!props.value?.loading;
|
|
3304
|
+
const columnDefine = table.getBodyColumnDefine(col, row);
|
|
3305
|
+
const type = columnDefine.fmt;
|
|
3306
|
+
const cellStyle = table._getCellStyle(col, row);
|
|
3307
|
+
const functionalFontSize = getProp("fontSize", cellStyle, col, row, table);
|
|
3308
|
+
const functionalColor = getProp("color", cellStyle, col, row, table);
|
|
3309
|
+
const headerIconSize = getIconSizeFromFont(functionalFontSize);
|
|
3310
|
+
const padding = [5, 10];
|
|
3311
|
+
const group = vrender.createGroup({
|
|
3312
|
+
width,
|
|
3313
|
+
height,
|
|
3314
|
+
display: "flex",
|
|
3315
|
+
flexWrap: "nowrap",
|
|
3316
|
+
justifyContent: "flex-start",
|
|
3317
|
+
alignContent: "center",
|
|
3318
|
+
alignItems: "center"
|
|
3319
|
+
});
|
|
3320
|
+
const value = props.value?.value ?? "";
|
|
3321
|
+
const getPureDateFormat = (format) => {
|
|
3322
|
+
return format.replace(/\s*\(GMT\+8\)$/i, "").replace(/\s*\(G1T\+8\)$/i, "").replace(/\s*\(G10T\+8\)$/i, "").replace(/G1T\+8/gi, "").replace(/G10T\+8/gi, "").trim();
|
|
3323
|
+
};
|
|
3324
|
+
const formattedValue1 = (() => {
|
|
3325
|
+
const cleanedValue = value && value?.replace(/\s*\([^)]+\)$/gi, "").replace(/:/g, ":").replace(/\s+/g, " ").replace(/(|)/g, "").replace(/[\u200B-\u200D\uFEFF]/g, "").replace(/[^0-9\/\-\s:]/g, "");
|
|
3326
|
+
const pureDateTimeMatch = cleanedValue.match(/(\d{4}[-\/]\d{2}[-\/]\d{2}(?:\s+\d{2}:\d{2})?)/);
|
|
3327
|
+
const pureDateTime = pureDateTimeMatch?.[1]?.trim() || "";
|
|
3328
|
+
if (!pureDateTime) return "";
|
|
3329
|
+
const pureDateFormat = getPureDateFormat(type);
|
|
3330
|
+
if (!pureDateFormat) return "";
|
|
3331
|
+
const parseFormats = [pureDateFormat, "YYYY/MM/DD HH:mm", "YYYY-MM-DD HH:mm", "YYYY/MM/DD", "YYYY-MM-DD"];
|
|
3332
|
+
let finalParsedDate = dayjs(pureDateTime, parseFormats[0], true);
|
|
3333
|
+
for (const format of parseFormats.slice(1)) {
|
|
3334
|
+
if (!finalParsedDate.isValid()) {
|
|
3335
|
+
finalParsedDate = dayjs(pureDateTime, format, true);
|
|
3336
|
+
} else break;
|
|
3337
|
+
}
|
|
3338
|
+
if (!finalParsedDate.isValid()) return "";
|
|
3339
|
+
const pureFormattedDate = finalParsedDate.format(pureDateFormat);
|
|
3340
|
+
return type.includes("GMT+8") || type.includes("G1T+8") || type.includes("G10T+8") ? pureFormattedDate + " " + FIXED_TIMEZONE_LABEL : pureFormattedDate;
|
|
3341
|
+
})();
|
|
3342
|
+
const text = vrender.createText({
|
|
3343
|
+
fontSize: headerIconSize,
|
|
3344
|
+
fontFamily: "sans-serif",
|
|
3345
|
+
text: formattedValue1,
|
|
3346
|
+
fill: functionalColor,
|
|
3347
|
+
maxLineWidth: width - padding[1] * 2,
|
|
3348
|
+
boundsPadding: [5, 12, 5, 10]
|
|
3349
|
+
});
|
|
3350
|
+
group.add(text);
|
|
3351
|
+
return createGraphicsWithLoading(group, loading);
|
|
3352
|
+
};
|
|
3353
|
+
|
|
3354
|
+
const createLinkGraphics = (props) => {
|
|
3355
|
+
const { value, table, rect, col, row } = props;
|
|
3356
|
+
const { title, url } = value?.value ?? {};
|
|
3357
|
+
const loading = value?.loading ?? false;
|
|
3358
|
+
const padding = [5, 10];
|
|
3359
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
3360
|
+
const group = vrender.createGroup({
|
|
3361
|
+
width,
|
|
3362
|
+
height,
|
|
3363
|
+
display: "flex",
|
|
3364
|
+
flexWrap: "nowrap",
|
|
3365
|
+
justifyContent: "space-around",
|
|
3366
|
+
alignContent: "center",
|
|
3367
|
+
alignItems: "center"
|
|
3368
|
+
// 垂直居中
|
|
3369
|
+
});
|
|
3370
|
+
const text = vrender.createText({
|
|
3371
|
+
fontSize: 12,
|
|
3372
|
+
fontFamily: "sans-serif",
|
|
3373
|
+
text: title,
|
|
3374
|
+
fill: core.COLOR_LINK,
|
|
3375
|
+
cursor: "pointer",
|
|
3376
|
+
maxLineWidth: width - padding[1] * 2,
|
|
3377
|
+
boundsPadding: [5, 12, 5, 10]
|
|
3378
|
+
});
|
|
3379
|
+
text.addEventListener("click", () => window.open(url));
|
|
3380
|
+
text.addEventListener("mouseover", () => {
|
|
3381
|
+
text.setAttribute("underline", 1);
|
|
3382
|
+
text.stage?.renderNextFrame();
|
|
3383
|
+
});
|
|
3384
|
+
text.addEventListener("mouseleave", () => {
|
|
3385
|
+
text.setAttribute("underline", 0);
|
|
3386
|
+
text.stage?.renderNextFrame();
|
|
3387
|
+
});
|
|
3388
|
+
group.add(text);
|
|
3389
|
+
return createGraphicsWithLoading(group, loading);
|
|
3390
|
+
};
|
|
3391
|
+
|
|
3392
|
+
const createMainColumnCellGraphics = (props) => {
|
|
3393
|
+
const { row, col, rect, table } = props;
|
|
3394
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
3395
|
+
const loading = !!props.value?.loading;
|
|
3396
|
+
const cellStyle = table._getCellStyle(col, row);
|
|
3397
|
+
const functionalFontSize = getProp("fontSize", cellStyle, col, row, table);
|
|
3398
|
+
const group = vrender.createGroup({
|
|
3399
|
+
width,
|
|
3400
|
+
height,
|
|
3401
|
+
display: "flex",
|
|
3402
|
+
alignItems: "center",
|
|
3403
|
+
justifyContent: "space-between"
|
|
3404
|
+
});
|
|
3405
|
+
const text = vrender.createText({
|
|
3406
|
+
fontSize: functionalFontSize,
|
|
3407
|
+
text: props.value?.value ?? "",
|
|
3408
|
+
fill: getProp("color", cellStyle, col, row, table),
|
|
3409
|
+
cursor: "pointer",
|
|
3410
|
+
maxLineWidth: width - 30
|
|
3411
|
+
});
|
|
3412
|
+
group.add(text);
|
|
3413
|
+
const ig = vrender.createGroup({
|
|
3414
|
+
width: 30,
|
|
3415
|
+
height,
|
|
3416
|
+
display: "flex",
|
|
3417
|
+
alignItems: "center",
|
|
3418
|
+
justifyContent: "center"
|
|
3419
|
+
});
|
|
3420
|
+
const detailIcon = createIconGraphics("drawer", {
|
|
3421
|
+
hoverBg: true,
|
|
3422
|
+
cursor: "pointer",
|
|
3423
|
+
size: functionalFontSize,
|
|
3424
|
+
onClick: () => {
|
|
3425
|
+
const editor = getActiveEditorTable();
|
|
3426
|
+
if (!editor) throw new Error("createMainColumnCellGraphics::detailIcon onclick \u672A\u83B7\u53D6\u5230activeEditorTable");
|
|
3427
|
+
const { recordId } = editor.getInteractiveCell(col, row);
|
|
3428
|
+
editor.dispatch("record::open::detail::drawer", { editor, recordId });
|
|
3429
|
+
}
|
|
3430
|
+
});
|
|
3431
|
+
ig.add(detailIcon);
|
|
3432
|
+
ig.removeChild(detailIcon);
|
|
3433
|
+
group.addEventListener("mouseover", () => {
|
|
3434
|
+
ig.setAttribute("visible", true);
|
|
3435
|
+
ig.add(detailIcon);
|
|
3436
|
+
group.stage?.renderNextFrame();
|
|
3437
|
+
});
|
|
3438
|
+
group.addEventListener("mouseleave", () => {
|
|
3439
|
+
ig.setAttribute("visible", false);
|
|
3440
|
+
ig.removeChild(detailIcon);
|
|
3441
|
+
group.stage?.renderNextFrame();
|
|
3442
|
+
});
|
|
3443
|
+
group.add(ig);
|
|
3444
|
+
return createGraphicsWithLoading(group, loading);
|
|
3445
|
+
};
|
|
3446
|
+
|
|
3447
|
+
const createMoreGraphics = (props) => {
|
|
3448
|
+
const { onClick, onCancel, record, row, col, table, rect, value } = props;
|
|
3449
|
+
const loading = !!value?.loading;
|
|
3450
|
+
const cellStyle = table._getCellStyle(col, row);
|
|
3451
|
+
const functionalFontSize = getProp("fontSize", cellStyle, col, row, table);
|
|
3452
|
+
const functionalColor = getProp("color", cellStyle, col, row, table);
|
|
3453
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
3454
|
+
const group = vrender.createGroup({
|
|
3455
|
+
width,
|
|
3456
|
+
height,
|
|
3457
|
+
display: "flex",
|
|
3458
|
+
cursor: "pointer",
|
|
3459
|
+
justifyContent: "center",
|
|
3460
|
+
alignItems: "center"
|
|
3461
|
+
});
|
|
3462
|
+
const icon = createIconGraphics("more", {
|
|
3463
|
+
size: getIconSizeFromFont(functionalFontSize),
|
|
3464
|
+
color: functionalColor,
|
|
3465
|
+
x: (width - 16) / 2,
|
|
3466
|
+
y: (height - 16) / 2,
|
|
3467
|
+
cursor: "pointer"
|
|
3468
|
+
});
|
|
3469
|
+
const handleEvent = (evt) => {
|
|
3470
|
+
evt.stopPropagation();
|
|
3471
|
+
const x = evt.clientX || evt.x || 0;
|
|
3472
|
+
const y = evt.clientY || evt.y || 0;
|
|
3473
|
+
onClick?.({ row, col, record, x, y });
|
|
3474
|
+
const rect2 = table.getCellRelativeRect(col, row);
|
|
3475
|
+
const tableEditor = getActiveEditorTable();
|
|
3476
|
+
if (!tableEditor) throw new Error("tableEditor \u4E0D\u5B58\u5728");
|
|
3477
|
+
const { recordId, columnId } = tableEditor.getInteractiveCell(row, col);
|
|
3478
|
+
setMenu({
|
|
3479
|
+
open: true,
|
|
3480
|
+
position: { x: rect2.left + width / 2 - 8, y: rect2.top + height / 2 - 8 },
|
|
3481
|
+
type: "more",
|
|
3482
|
+
cell: { col, row, recordId, columnId, rect: rect2 }
|
|
3483
|
+
});
|
|
3484
|
+
};
|
|
3485
|
+
const handleCancel = (evt) => {
|
|
3486
|
+
evt.stopPropagation();
|
|
3487
|
+
onCancel?.();
|
|
3488
|
+
setMenu(null);
|
|
3489
|
+
};
|
|
3490
|
+
group.addEventListener("pointerenter", handleEvent);
|
|
3491
|
+
group.addEventListener("pointermove", handleEvent);
|
|
3492
|
+
group.addEventListener("click", handleEvent);
|
|
3493
|
+
group.addEventListener("pointerleave", handleCancel);
|
|
3494
|
+
group.add(icon);
|
|
3495
|
+
return createGraphicsWithLoading(group, loading);
|
|
3496
|
+
};
|
|
3497
|
+
|
|
3498
|
+
const formatTagItem = (value, options, tableInstance) => {
|
|
3499
|
+
const {
|
|
3500
|
+
blankWidth = 16,
|
|
3501
|
+
fontWeight = 400,
|
|
3502
|
+
fontSize,
|
|
3503
|
+
fontColor = "black",
|
|
3504
|
+
fontFamily = "PingFang SC",
|
|
3505
|
+
basePadding = 16 * 2,
|
|
3506
|
+
tagMinWidth = 48,
|
|
3507
|
+
cellWidth
|
|
3508
|
+
} = options;
|
|
3509
|
+
const tagMaxWidth = Math.max(cellWidth - basePadding, tagMinWidth);
|
|
3510
|
+
const item = {
|
|
3511
|
+
label: value.label,
|
|
3512
|
+
value: value.value
|
|
3513
|
+
};
|
|
3514
|
+
const label = (item.label || "").replace(/[\u200B\u2060]/g, "");
|
|
3515
|
+
const { width } = tableInstance.measureText(label, {
|
|
3516
|
+
fontSize,
|
|
3517
|
+
fontWeight,
|
|
3518
|
+
fontFamily
|
|
3519
|
+
});
|
|
3520
|
+
const textLength = Math.ceil(width) + blankWidth;
|
|
3521
|
+
const tagWidth = Math.min(Math.max(textLength, tagMinWidth), tagMaxWidth);
|
|
3522
|
+
if (!item.tagProps) {
|
|
3523
|
+
item.tagProps = {
|
|
3524
|
+
fontColor,
|
|
3525
|
+
backgroundColor: value.color,
|
|
3526
|
+
width: 0
|
|
3527
|
+
};
|
|
3528
|
+
}
|
|
3529
|
+
item.tagProps.width = tagWidth;
|
|
3530
|
+
return {
|
|
3531
|
+
textLength,
|
|
3532
|
+
tagWidth,
|
|
3533
|
+
tagMaxWidth,
|
|
3534
|
+
tagMinWidth,
|
|
3535
|
+
item
|
|
3536
|
+
};
|
|
3537
|
+
};
|
|
3538
|
+
|
|
3539
|
+
const TAG_HEIGHT$2 = 18;
|
|
3540
|
+
const TAG_GAP = 8;
|
|
3541
|
+
const NUMBER_WIDTH = 25;
|
|
3542
|
+
const TAG_MIN_WIDTH$2 = TAG_GAP + NUMBER_WIDTH;
|
|
3543
|
+
const getTagsRowMap = (tags, options, tableInstance) => {
|
|
3544
|
+
const res = calcCellTags(
|
|
3545
|
+
tags,
|
|
3546
|
+
{
|
|
3547
|
+
cellWidth: options.cellWidth,
|
|
3548
|
+
fontSize: options.fontSize,
|
|
3549
|
+
blankWidth: options.blankWidth,
|
|
3550
|
+
tagMinWidth: TAG_MIN_WIDTH$2
|
|
3551
|
+
},
|
|
3552
|
+
tableInstance
|
|
3553
|
+
);
|
|
3554
|
+
return res.filterTagsRowMap;
|
|
3555
|
+
};
|
|
3556
|
+
const calcCellTags = (tags = [], options, tableInstance) => {
|
|
3557
|
+
if (!tags.length) return { filterTags: [], filterTagsRowMap: {} };
|
|
3558
|
+
const data = lodash.cloneDeep(tags);
|
|
3559
|
+
const filterTags = [];
|
|
3560
|
+
const filterTagsRowMap = {};
|
|
3561
|
+
const numberTagWidth = TAG_GAP + NUMBER_WIDTH;
|
|
3562
|
+
const len = data.length;
|
|
3563
|
+
let totalWidth = 0;
|
|
3564
|
+
const currentRow = 1;
|
|
3565
|
+
const addTags = (item) => {
|
|
3566
|
+
filterTags.push(item);
|
|
3567
|
+
if (!filterTagsRowMap[currentRow]) {
|
|
3568
|
+
filterTagsRowMap[currentRow] = [];
|
|
3569
|
+
}
|
|
3570
|
+
filterTagsRowMap[currentRow].push(item);
|
|
3571
|
+
};
|
|
3572
|
+
if (len === 1) {
|
|
3573
|
+
const { item } = formatTagItem(data[0], options, tableInstance);
|
|
3574
|
+
addTags(item);
|
|
3575
|
+
} else if (len > 1) {
|
|
3576
|
+
for (let i = 0; i < len; i += 1) {
|
|
3577
|
+
const { item, tagMaxWidth, tagMinWidth, tagWidth } = formatTagItem(data[i], options, tableInstance);
|
|
3578
|
+
const handlePushItem = (item2) => {
|
|
3579
|
+
const calcWidth = totalWidth + tagMinWidth + (i === len - 1 ? 0 : numberTagWidth);
|
|
3580
|
+
if (tagMaxWidth >= calcWidth) {
|
|
3581
|
+
const realTextWidth = Math.min(tagWidth, tagMaxWidth - totalWidth - (i === len - 1 ? 0 : numberTagWidth));
|
|
3582
|
+
item2.tagProps.width = realTextWidth;
|
|
3583
|
+
totalWidth = totalWidth + realTextWidth + TAG_GAP;
|
|
3584
|
+
addTags(item2);
|
|
3585
|
+
return false;
|
|
3586
|
+
} else if (tagMaxWidth < calcWidth) {
|
|
3587
|
+
if (tagMaxWidth < totalWidth + tagMinWidth + numberTagWidth) {
|
|
3588
|
+
addTags({
|
|
3589
|
+
label: "+" + (len - filterTags.length),
|
|
3590
|
+
value: -1,
|
|
3591
|
+
tagProps: {
|
|
3592
|
+
fontColor: "#404A59",
|
|
3593
|
+
backgroundColor: "#eff0f1",
|
|
3594
|
+
width: TAG_MIN_WIDTH$2
|
|
3595
|
+
}
|
|
3596
|
+
});
|
|
3597
|
+
return true;
|
|
3598
|
+
}
|
|
3599
|
+
if (i === len - 1) {
|
|
3600
|
+
item2.tagProps.width = Math.min(tagWidth, tagMaxWidth - totalWidth);
|
|
3601
|
+
addTags(item2);
|
|
3602
|
+
} else {
|
|
3603
|
+
item2.tagProps.width = Math.min(tagWidth, tagMaxWidth - totalWidth - numberTagWidth);
|
|
3604
|
+
addTags(item2);
|
|
3605
|
+
addTags({
|
|
3606
|
+
label: "+" + (len - filterTags.length),
|
|
3607
|
+
value: -1,
|
|
3608
|
+
tagProps: {
|
|
3609
|
+
fontColor: "#404A59",
|
|
3610
|
+
backgroundColor: "#eff0f1",
|
|
3611
|
+
width: NUMBER_WIDTH
|
|
3612
|
+
}
|
|
3613
|
+
});
|
|
3614
|
+
}
|
|
3615
|
+
return true;
|
|
3616
|
+
}
|
|
3617
|
+
};
|
|
3618
|
+
if (handlePushItem(item)) break;
|
|
3619
|
+
}
|
|
3620
|
+
}
|
|
3621
|
+
return { filterTags, filterTagsRowMap };
|
|
3622
|
+
};
|
|
3623
|
+
const createMultiSelectGraphic = (props) => {
|
|
3624
|
+
const { width, height, table, col, row } = props;
|
|
3625
|
+
const value = props.value?.value ?? [];
|
|
3626
|
+
const loading = !!props.value?.loading;
|
|
3627
|
+
const styles = table._getCellStyle(col, row);
|
|
3628
|
+
const options = table.getBodyColumnDefine(col, 0).options || [];
|
|
3629
|
+
const newValue = value.map((item) => {
|
|
3630
|
+
return options.find((option) => option.value === item.value);
|
|
3631
|
+
}).filter(Boolean);
|
|
3632
|
+
const fontSize = getProp("fontSize", styles, col, row, table);
|
|
3633
|
+
const tagsMap = getTagsRowMap(newValue, { cellWidth: width, blankWidth: 16, fontSize }, table) || {};
|
|
3634
|
+
const container = /* @__PURE__ */ React.createElement(
|
|
3635
|
+
vrender.VGroup,
|
|
3636
|
+
{
|
|
3637
|
+
attribute: {
|
|
3638
|
+
width: width - 32,
|
|
3639
|
+
height,
|
|
3640
|
+
display: "flex",
|
|
3641
|
+
alignItems: "center",
|
|
3642
|
+
alignContent: "center",
|
|
3643
|
+
dx: 16
|
|
3644
|
+
}
|
|
3645
|
+
},
|
|
3646
|
+
Object.keys(tagsMap).map((key) => {
|
|
3647
|
+
const tag = tagsMap[Number(key)];
|
|
3648
|
+
return /* @__PURE__ */ React.createElement(
|
|
3649
|
+
vrender.VGroup,
|
|
3650
|
+
{
|
|
3651
|
+
key,
|
|
3652
|
+
attribute: {
|
|
3653
|
+
width: width - 32,
|
|
3654
|
+
height: TAG_HEIGHT$2,
|
|
3655
|
+
display: "flex",
|
|
3656
|
+
alignItems: "center",
|
|
3657
|
+
flexWrap: "nowrap",
|
|
3658
|
+
overflow: "hidden",
|
|
3659
|
+
boundsPadding: [4, 0, 4, 0]
|
|
3660
|
+
}
|
|
3661
|
+
},
|
|
3662
|
+
tag.map((item, subIndex) => {
|
|
3663
|
+
return /* @__PURE__ */ React.createElement(
|
|
3664
|
+
vrender.VGroup,
|
|
3665
|
+
{
|
|
3666
|
+
key: item.value,
|
|
3667
|
+
attribute: {
|
|
3668
|
+
width: item.tagProps.width,
|
|
3669
|
+
height: TAG_HEIGHT$2,
|
|
3670
|
+
display: "flex",
|
|
3671
|
+
alignItems: "center",
|
|
3672
|
+
justifyContent: "center",
|
|
3673
|
+
overflow: "hidden",
|
|
3674
|
+
cornerRadius: TAG_HEIGHT$2 / 2,
|
|
3675
|
+
fill: item.tagProps.backgroundColor,
|
|
3676
|
+
boundsPadding: subIndex > 0 ? [0, 0, 0, 8] : 0
|
|
3677
|
+
}
|
|
3678
|
+
},
|
|
3679
|
+
/* @__PURE__ */ React.createElement(
|
|
3680
|
+
vrender.VText,
|
|
3681
|
+
{
|
|
3682
|
+
attribute: {
|
|
3683
|
+
text: item.label,
|
|
3684
|
+
fontSize,
|
|
3685
|
+
fill: color.getTextColorForBackground(item.tagProps.backgroundColor || "#000000"),
|
|
3686
|
+
textAlign: "left",
|
|
3687
|
+
textBaseline: "top",
|
|
3688
|
+
maxLineWidth: item.tagProps.width - 16
|
|
3689
|
+
}
|
|
3690
|
+
}
|
|
3691
|
+
)
|
|
3692
|
+
);
|
|
3693
|
+
})
|
|
3694
|
+
);
|
|
3695
|
+
})
|
|
3696
|
+
);
|
|
3697
|
+
return createGraphicsWithLoading(container, loading);
|
|
3698
|
+
};
|
|
3699
|
+
|
|
3700
|
+
const createNumberGraphics = (props) => {
|
|
3701
|
+
const { row, col, table, rect, textAlign = "right" } = props;
|
|
3702
|
+
const columnDefine = table.getBodyColumnDefine(col, row);
|
|
3703
|
+
const fmt = columnDefine.fmt ?? "integer";
|
|
3704
|
+
const value = props.value?.value;
|
|
3705
|
+
const loading = !!props.value?.loading;
|
|
3706
|
+
const cellStyle = table._getCellStyle(col, row);
|
|
3707
|
+
const fontSize = getProp("fontSize", cellStyle, col, row, table);
|
|
3708
|
+
const functionalColor = getProp("color", cellStyle, col, row, table);
|
|
3709
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
3710
|
+
const textValue = core.formatValue(value, fmt);
|
|
3711
|
+
const padding = 10;
|
|
3712
|
+
const group = vrender.createGroup({
|
|
3713
|
+
width,
|
|
3714
|
+
height
|
|
3715
|
+
});
|
|
3716
|
+
const text = vrender.createText({
|
|
3717
|
+
text: textValue,
|
|
3718
|
+
fill: functionalColor,
|
|
3719
|
+
fontFamily: "sans-serif",
|
|
3720
|
+
fontSize,
|
|
3721
|
+
textBaseline: "middle",
|
|
3722
|
+
y: height / 2,
|
|
3723
|
+
maxLineWidth: width - padding * 2
|
|
3724
|
+
});
|
|
3725
|
+
if (textAlign === "left") {
|
|
3726
|
+
text.setAttribute("x", padding);
|
|
3727
|
+
text.setAttribute("textAlign", "left");
|
|
3728
|
+
} else if (textAlign === "center") {
|
|
3729
|
+
text.setAttribute("x", width / 2);
|
|
3730
|
+
text.setAttribute("textAlign", "center");
|
|
3731
|
+
} else {
|
|
3732
|
+
text.setAttribute("x", width - padding);
|
|
3733
|
+
text.setAttribute("textAlign", "right");
|
|
3734
|
+
}
|
|
3735
|
+
group.add(text);
|
|
3736
|
+
return createGraphicsWithLoading(group, loading);
|
|
3737
|
+
};
|
|
3738
|
+
|
|
3739
|
+
const getTextWidth = (text, fontSize) => {
|
|
3740
|
+
const textElement = vrender.createText({
|
|
3741
|
+
text,
|
|
3742
|
+
fontSize
|
|
3743
|
+
});
|
|
3744
|
+
const bounds = textElement.AABBBounds;
|
|
3745
|
+
return bounds.width();
|
|
3746
|
+
};
|
|
3747
|
+
|
|
3748
|
+
const AVATAR_SIZE = 20;
|
|
3749
|
+
const GAP = 4;
|
|
3750
|
+
const ITEM_GAP = 8;
|
|
3751
|
+
const ELLIPSIS = "...";
|
|
3752
|
+
const ELLIPSIS_WIDTH = 8;
|
|
3753
|
+
const PADDING_LEFT = 15;
|
|
3754
|
+
const getName = (id, value) => {
|
|
3755
|
+
if (id == -1) {
|
|
3756
|
+
return "\u7CFB\u7EDF";
|
|
3757
|
+
} else if (id == -2) {
|
|
3758
|
+
return "\u65E0";
|
|
3759
|
+
}
|
|
3760
|
+
return value;
|
|
3761
|
+
};
|
|
3762
|
+
const createPeopleGraphics = (props) => {
|
|
3763
|
+
const { row, col, rect, table } = props;
|
|
3764
|
+
const cellStyle = table?._getCellStyle(col, row);
|
|
3765
|
+
const functionalFontSize = getProp("fontSize", cellStyle, col, row, table);
|
|
3766
|
+
const functionalColor = getProp("color", cellStyle, col, row, table);
|
|
3767
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
3768
|
+
const group = vrender.createGroup({ width, height, x: 15, y: 0 });
|
|
3769
|
+
const value = props.value?.value ?? [];
|
|
3770
|
+
const loading = props.value?.loading ?? false;
|
|
3771
|
+
const items = [];
|
|
3772
|
+
let cursor = 0;
|
|
3773
|
+
for (let i = 0; i < value.length; i++) {
|
|
3774
|
+
const person = value[i];
|
|
3775
|
+
const nameWidth = getTextWidth(getName(person.id, person.name), functionalFontSize);
|
|
3776
|
+
const fullWidth = AVATAR_SIZE + GAP + nameWidth;
|
|
3777
|
+
const remaining = width - cursor - PADDING_LEFT;
|
|
3778
|
+
if (fullWidth <= remaining) {
|
|
3779
|
+
items.push({ person, mode: "full" });
|
|
3780
|
+
cursor += fullWidth + ITEM_GAP;
|
|
3781
|
+
continue;
|
|
3782
|
+
}
|
|
3783
|
+
const minWidth = AVATAR_SIZE + GAP + ELLIPSIS_WIDTH;
|
|
3784
|
+
if (remaining >= minWidth) {
|
|
3785
|
+
const availableNameWidth = remaining - AVATAR_SIZE - GAP;
|
|
3786
|
+
items.push({
|
|
3787
|
+
person,
|
|
3788
|
+
mode: "truncate",
|
|
3789
|
+
availableNameWidth
|
|
3790
|
+
});
|
|
3791
|
+
}
|
|
3792
|
+
break;
|
|
3793
|
+
}
|
|
3794
|
+
const hasMore = items.length < value.length;
|
|
3795
|
+
let x = 0;
|
|
3796
|
+
items.forEach((item) => {
|
|
3797
|
+
const personGroup = renderPersonItem(item, x, height, functionalFontSize, functionalColor, table, {
|
|
3798
|
+
row,
|
|
3799
|
+
col,
|
|
3800
|
+
width,
|
|
3801
|
+
height
|
|
3802
|
+
});
|
|
3803
|
+
group.add(personGroup);
|
|
3804
|
+
const nameW = item.mode === "full" ? getTextWidth(getName(item.person.id, item.person?.name ?? ""), functionalFontSize) : item.availableNameWidth ?? 0;
|
|
3805
|
+
x += AVATAR_SIZE + GAP + nameW + ITEM_GAP;
|
|
3806
|
+
});
|
|
3807
|
+
if (hasMore) {
|
|
3808
|
+
group.add(
|
|
3809
|
+
vrender.createText({
|
|
3810
|
+
x,
|
|
3811
|
+
y: height / 2,
|
|
3812
|
+
text: ELLIPSIS,
|
|
3813
|
+
textBaseline: "middle",
|
|
3814
|
+
fill: functionalColor || "#666",
|
|
3815
|
+
fontSize: functionalFontSize
|
|
3816
|
+
})
|
|
3817
|
+
);
|
|
3818
|
+
}
|
|
3819
|
+
return createGraphicsWithLoading(group, loading);
|
|
3820
|
+
};
|
|
3821
|
+
function renderPersonItem(item, x, containerHeight, functionalFontSize, functionalColor, table, cell) {
|
|
3822
|
+
const { person, mode, availableNameWidth } = item;
|
|
3823
|
+
const y = (containerHeight - AVATAR_SIZE) / 2;
|
|
3824
|
+
const g = vrender.createGroup({ x, y, height: AVATAR_SIZE });
|
|
3825
|
+
if (person.id == -1 || person.id == -2) {
|
|
3826
|
+
const avatarBg = vrender.createRect({
|
|
3827
|
+
width: AVATAR_SIZE,
|
|
3828
|
+
height: AVATAR_SIZE,
|
|
3829
|
+
cornerRadius: AVATAR_SIZE / 2,
|
|
3830
|
+
fill: person.id == -1 ? "#52c41a" : "#999"
|
|
3831
|
+
});
|
|
3832
|
+
g.add(avatarBg);
|
|
3833
|
+
const avatarText = vrender.createText({
|
|
3834
|
+
x: AVATAR_SIZE / 2,
|
|
3835
|
+
y: AVATAR_SIZE / 2,
|
|
3836
|
+
text: person.id == -1 ? "\u7CFB\u7EDF" : "\u65E0",
|
|
3837
|
+
textBaseline: "middle",
|
|
3838
|
+
textAlign: "center",
|
|
3839
|
+
fill: "#fff",
|
|
3840
|
+
fontSize: 8
|
|
3841
|
+
});
|
|
3842
|
+
g.add(avatarText);
|
|
3843
|
+
} else if (person.avatar) {
|
|
3844
|
+
const imageGraphics = vrender.createImage({
|
|
3845
|
+
width: AVATAR_SIZE,
|
|
3846
|
+
height: AVATAR_SIZE,
|
|
3847
|
+
image: person.avatar,
|
|
3848
|
+
cornerRadius: AVATAR_SIZE / 2
|
|
3849
|
+
});
|
|
3850
|
+
g.add(imageGraphics);
|
|
3851
|
+
} else {
|
|
3852
|
+
const avatarBg = vrender.createRect({
|
|
3853
|
+
width: AVATAR_SIZE,
|
|
3854
|
+
height: AVATAR_SIZE,
|
|
3855
|
+
cornerRadius: AVATAR_SIZE / 2,
|
|
3856
|
+
fill: core.getColorByStr(person.name?.slice(-2))
|
|
3857
|
+
});
|
|
3858
|
+
g.add(avatarBg);
|
|
3859
|
+
const avatarText = vrender.createText({
|
|
3860
|
+
x: AVATAR_SIZE / 2,
|
|
3861
|
+
y: AVATAR_SIZE / 2,
|
|
3862
|
+
text: (person.name?.length ?? 0) >= 2 ? person.name?.slice(-2) : person.name?.[0] ?? "?",
|
|
3863
|
+
textBaseline: "middle",
|
|
3864
|
+
textAlign: "center",
|
|
3865
|
+
fill: "#fff",
|
|
3866
|
+
fontSize: 8
|
|
3867
|
+
});
|
|
3868
|
+
g.add(avatarText);
|
|
3869
|
+
}
|
|
3870
|
+
if (table && cell && person.id !== -1 && person.id !== -2) {
|
|
3871
|
+
g.on("mouseenter", () => {
|
|
3872
|
+
const cellRect = table.getCellRelativeRect(cell.col, cell.row);
|
|
3873
|
+
const avatarCenterX = cellRect.left + PADDING_LEFT + x + AVATAR_SIZE / 2;
|
|
3874
|
+
const avatarCenterY = cellRect.top + y + AVATAR_SIZE / 2;
|
|
3875
|
+
initUserShowTool({
|
|
3876
|
+
cell: {
|
|
3877
|
+
row: cell.row,
|
|
3878
|
+
col: cell.col,
|
|
3879
|
+
position: { x: avatarCenterX, y: avatarCenterY },
|
|
3880
|
+
width: cell.width,
|
|
3881
|
+
height: cell.height
|
|
3882
|
+
},
|
|
3883
|
+
table,
|
|
3884
|
+
endEdit: () => {
|
|
3885
|
+
},
|
|
3886
|
+
id: person.id
|
|
3887
|
+
});
|
|
3888
|
+
});
|
|
3889
|
+
g.on("mouseleave", () => {
|
|
3890
|
+
clearUserShowTool();
|
|
3891
|
+
});
|
|
3892
|
+
}
|
|
3893
|
+
let text = getName(person.id, person.name ?? "");
|
|
3894
|
+
if (mode === "truncate" && availableNameWidth !== void 0 && person.id !== -1 && person.id !== -2) {
|
|
3895
|
+
let left = 0;
|
|
3896
|
+
let right = person.name?.length || 0;
|
|
3897
|
+
let bestLength = 0;
|
|
3898
|
+
while (left <= right) {
|
|
3899
|
+
const mid = Math.floor((left + right) / 2);
|
|
3900
|
+
const testText = person.name?.slice(0, mid) + ELLIPSIS;
|
|
3901
|
+
const testWidth = getTextWidth(testText, functionalFontSize);
|
|
3902
|
+
if (testWidth <= availableNameWidth) {
|
|
3903
|
+
bestLength = mid;
|
|
3904
|
+
left = mid + 1;
|
|
3905
|
+
} else {
|
|
3906
|
+
right = mid - 1;
|
|
3907
|
+
}
|
|
3908
|
+
}
|
|
3909
|
+
text = bestLength > 0 ? person.name?.slice(0, bestLength) + ELLIPSIS : ELLIPSIS;
|
|
3910
|
+
}
|
|
3911
|
+
g.add(
|
|
3912
|
+
vrender.createText({
|
|
3913
|
+
x: AVATAR_SIZE + GAP,
|
|
3914
|
+
y: AVATAR_SIZE / 2,
|
|
3915
|
+
text,
|
|
3916
|
+
textBaseline: "middle",
|
|
3917
|
+
fill: functionalColor,
|
|
3918
|
+
fontSize: functionalFontSize
|
|
3919
|
+
})
|
|
3920
|
+
);
|
|
3921
|
+
return g;
|
|
3922
|
+
}
|
|
3923
|
+
|
|
3924
|
+
const TAG_HEIGHT$1 = 18;
|
|
3925
|
+
const CELL_PADDING$1 = 16;
|
|
3926
|
+
const TAG_PADDING$1 = 8;
|
|
3927
|
+
const TAG_MIN_WIDTH$1 = 35;
|
|
3928
|
+
const createSingleSelectGraphic = (props) => {
|
|
3929
|
+
const { table, col, row, rect } = props;
|
|
3930
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
3931
|
+
const value = props.value?.value ?? [];
|
|
3932
|
+
const loading = !!props.value?.loading;
|
|
3933
|
+
const options = table.getBodyColumnDefine(col, 0).options || [];
|
|
3934
|
+
const valueItem = options.find((option) => option.value === value[0]?.value);
|
|
3935
|
+
if (!valueItem) {
|
|
3936
|
+
return null;
|
|
3937
|
+
}
|
|
3938
|
+
const styles = table._getCellStyle(col, row);
|
|
3939
|
+
const fontSize = getProp("fontSize", styles, col, row, table);
|
|
3940
|
+
const { item } = formatTagItem(
|
|
3941
|
+
valueItem,
|
|
3942
|
+
{
|
|
3943
|
+
cellWidth: width,
|
|
3944
|
+
blankWidth: 16,
|
|
3945
|
+
basePadding: CELL_PADDING$1 * 2,
|
|
3946
|
+
tagMinWidth: TAG_MIN_WIDTH$1,
|
|
3947
|
+
fontSize
|
|
3948
|
+
},
|
|
3949
|
+
table
|
|
3950
|
+
);
|
|
3951
|
+
const container = /* @__PURE__ */ React.createElement(
|
|
3952
|
+
vrender.VGroup,
|
|
3953
|
+
{
|
|
3954
|
+
attribute: {
|
|
3955
|
+
width: width - 32,
|
|
3956
|
+
height,
|
|
3957
|
+
display: "flex",
|
|
3958
|
+
alignItems: "center",
|
|
3959
|
+
alignContent: "center",
|
|
3960
|
+
dx: 16
|
|
3961
|
+
}
|
|
3962
|
+
},
|
|
3963
|
+
/* @__PURE__ */ React.createElement(
|
|
3964
|
+
vrender.VGroup,
|
|
3965
|
+
{
|
|
3966
|
+
key: item.value,
|
|
3967
|
+
attribute: {
|
|
3968
|
+
width: item.tagProps.width,
|
|
3969
|
+
height: TAG_HEIGHT$1,
|
|
3970
|
+
display: "flex",
|
|
3971
|
+
alignItems: "center",
|
|
3972
|
+
justifyContent: "center",
|
|
3973
|
+
overflow: "hidden",
|
|
3974
|
+
cornerRadius: TAG_HEIGHT$1 / 2 - 1,
|
|
3975
|
+
fill: item.tagProps.backgroundColor
|
|
3976
|
+
}
|
|
3977
|
+
},
|
|
3978
|
+
/* @__PURE__ */ React.createElement(
|
|
3979
|
+
vrender.VText,
|
|
3980
|
+
{
|
|
3981
|
+
attribute: {
|
|
3982
|
+
text: item.label,
|
|
3983
|
+
fontSize,
|
|
3984
|
+
fill: color.getTextColorForBackground(item.tagProps.backgroundColor || "#000000"),
|
|
3985
|
+
textAlign: "left",
|
|
3986
|
+
textBaseline: "top",
|
|
3987
|
+
maxLineWidth: item.tagProps.width - TAG_PADDING$1 * 2
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
)
|
|
3991
|
+
)
|
|
3992
|
+
);
|
|
3993
|
+
return createGraphicsWithLoading(container, loading);
|
|
3994
|
+
};
|
|
3995
|
+
|
|
3996
|
+
const TAG_HEIGHT = 18;
|
|
3997
|
+
const CELL_PADDING = 16;
|
|
3998
|
+
const TAG_PADDING = 8;
|
|
3999
|
+
const TAG_MIN_WIDTH = 40;
|
|
4000
|
+
const TAG_BACKGROUND_COLOR = "#FAFAFA";
|
|
4001
|
+
const createTagGraphic = (props) => {
|
|
4002
|
+
const { table, row, col, rect } = props;
|
|
4003
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
4004
|
+
const value = props.value?.value ?? "";
|
|
4005
|
+
const loading = !!props.value?.loading;
|
|
4006
|
+
const styles = table._getCellStyle(col, row);
|
|
4007
|
+
const fontSize = getProp("fontSize", styles, col, row, table);
|
|
4008
|
+
const { item } = formatTagItem(
|
|
4009
|
+
{ label: value, value, color: TAG_BACKGROUND_COLOR },
|
|
4010
|
+
{
|
|
4011
|
+
cellWidth: width,
|
|
4012
|
+
blankWidth: 16,
|
|
4013
|
+
basePadding: CELL_PADDING * 2,
|
|
4014
|
+
tagMinWidth: TAG_MIN_WIDTH,
|
|
4015
|
+
fontSize
|
|
4016
|
+
},
|
|
4017
|
+
table
|
|
4018
|
+
);
|
|
4019
|
+
const container = /* @__PURE__ */ React.createElement(
|
|
4020
|
+
vrender.VGroup,
|
|
4021
|
+
{
|
|
4022
|
+
attribute: {
|
|
4023
|
+
width: width - 32,
|
|
4024
|
+
height,
|
|
4025
|
+
display: "flex",
|
|
4026
|
+
alignItems: "center",
|
|
4027
|
+
alignContent: "center",
|
|
4028
|
+
dx: 16
|
|
4029
|
+
}
|
|
4030
|
+
},
|
|
4031
|
+
!lodash.isNil(props.value?.value) && /* @__PURE__ */ React.createElement(
|
|
4032
|
+
vrender.VGroup,
|
|
4033
|
+
{
|
|
4034
|
+
key: item.value,
|
|
4035
|
+
attribute: {
|
|
4036
|
+
width: item.tagProps.width,
|
|
4037
|
+
height: TAG_HEIGHT,
|
|
4038
|
+
display: "flex",
|
|
4039
|
+
alignItems: "center",
|
|
4040
|
+
justifyContent: "center",
|
|
4041
|
+
overflow: "hidden",
|
|
4042
|
+
cornerRadius: 4,
|
|
4043
|
+
stroke: "#D9D9D9",
|
|
4044
|
+
fill: item.tagProps.backgroundColor
|
|
4045
|
+
}
|
|
4046
|
+
},
|
|
4047
|
+
/* @__PURE__ */ React.createElement(
|
|
4048
|
+
vrender.VText,
|
|
4049
|
+
{
|
|
4050
|
+
attribute: {
|
|
4051
|
+
text: item.label,
|
|
4052
|
+
fontSize,
|
|
4053
|
+
zIndex: 1e3,
|
|
4054
|
+
textAlign: "left",
|
|
4055
|
+
textBaseline: "top",
|
|
4056
|
+
fill: item.tagProps.fontColor,
|
|
4057
|
+
maxLineWidth: item.tagProps.width - TAG_PADDING * 2
|
|
4058
|
+
}
|
|
4059
|
+
}
|
|
4060
|
+
)
|
|
4061
|
+
)
|
|
4062
|
+
);
|
|
4063
|
+
return createGraphicsWithLoading(container, loading);
|
|
4064
|
+
};
|
|
4065
|
+
|
|
4066
|
+
const createTimeLenGraphics = (props) => {
|
|
4067
|
+
const { table, row, col, rect } = props;
|
|
4068
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
4069
|
+
const padding = [5, 10];
|
|
4070
|
+
const loading = props.value?.loading;
|
|
4071
|
+
const value = props.value?.value;
|
|
4072
|
+
const cellStyle = table._getCellStyle(col, row);
|
|
4073
|
+
const functionalFontSize = getProp("fontSize", cellStyle, col, row, table);
|
|
4074
|
+
const functionalColor = getProp("color", cellStyle, col, row, table);
|
|
4075
|
+
const time = !lodash.isNil(value) ? core.formatDuration(value) : "";
|
|
4076
|
+
const group = vrender.createGroup({
|
|
4077
|
+
width,
|
|
4078
|
+
height,
|
|
4079
|
+
display: "flex",
|
|
4080
|
+
flexWrap: "nowrap",
|
|
4081
|
+
justifyContent: "space-around",
|
|
4082
|
+
alignContent: "center",
|
|
4083
|
+
alignItems: "center"
|
|
4084
|
+
// 垂直居中
|
|
4085
|
+
});
|
|
4086
|
+
const text = vrender.createText({
|
|
4087
|
+
fontSize: functionalFontSize,
|
|
4088
|
+
fontFamily: "sans-serif",
|
|
4089
|
+
text: time,
|
|
4090
|
+
maxLineWidth: width - padding[1] * 2,
|
|
4091
|
+
boundsPadding: [5, 12, 5, 10],
|
|
4092
|
+
fill: functionalColor
|
|
4093
|
+
});
|
|
4094
|
+
group.add(text);
|
|
4095
|
+
return createGraphicsWithLoading(group, !!loading);
|
|
4096
|
+
};
|
|
4097
|
+
|
|
4098
|
+
const suffixToIconName = {
|
|
4099
|
+
// 图片类型
|
|
4100
|
+
png: "image-file",
|
|
4101
|
+
jpg: "image-file",
|
|
4102
|
+
jpeg: "image-file",
|
|
4103
|
+
bmp: "image-file",
|
|
4104
|
+
tif: "image-file",
|
|
4105
|
+
tiff: "image-file",
|
|
4106
|
+
heic: "image-file",
|
|
4107
|
+
pdf: "pdf",
|
|
4108
|
+
doc: "doc",
|
|
4109
|
+
docs: "docs",
|
|
4110
|
+
// 若枚举中没有 "docs",改为 "doc"
|
|
4111
|
+
ppt: "ppt",
|
|
4112
|
+
mp4: "video-file",
|
|
4113
|
+
mp3: "mp3",
|
|
4114
|
+
csv: "csv"
|
|
4115
|
+
};
|
|
4116
|
+
const createUploadDocumentGraphics = (props) => {
|
|
4117
|
+
const { table, row, col, rect } = props;
|
|
4118
|
+
const { height, width } = rect ?? table.getCellRect(col, row);
|
|
4119
|
+
const cellStyle = table._getCellStyle(col, row);
|
|
4120
|
+
const functionalFontSize = getProp("fontSize", cellStyle, col, row, table);
|
|
4121
|
+
const functionalColor = getProp("color", cellStyle, col, row, table);
|
|
4122
|
+
const headerIconSize = getIconSizeFromFont(functionalFontSize);
|
|
4123
|
+
const padding = [5, 10, 20];
|
|
4124
|
+
const value = props.value?.value ?? [];
|
|
4125
|
+
const loading = !!props.value?.loading;
|
|
4126
|
+
const getFileIconName = () => {
|
|
4127
|
+
if (value.length < 1) {
|
|
4128
|
+
return "text";
|
|
4129
|
+
}
|
|
4130
|
+
const fileNameOnly = value[0]?.name.split("/").pop() || "";
|
|
4131
|
+
const suffix = fileNameOnly.split(".").pop()?.toLowerCase() || "";
|
|
4132
|
+
return suffixToIconName[suffix] || "text";
|
|
4133
|
+
};
|
|
4134
|
+
const group = vrender.createGroup({
|
|
4135
|
+
width,
|
|
4136
|
+
height,
|
|
4137
|
+
display: "flex",
|
|
4138
|
+
flexWrap: "nowrap",
|
|
4139
|
+
justifyContent: "center",
|
|
4140
|
+
alignContent: "center",
|
|
4141
|
+
alignItems: "center"
|
|
4142
|
+
// 垂直居中
|
|
4143
|
+
// x: 15,
|
|
4144
|
+
});
|
|
4145
|
+
const uploadIcon = createIconGraphics("upload", { x: 0, y: 0, size: 14, color: functionalColor });
|
|
4146
|
+
const text = vrender.createText({
|
|
4147
|
+
fontSize: headerIconSize,
|
|
4148
|
+
fontFamily: "sans-serif",
|
|
4149
|
+
text: "\u70B9\u51FB\u4E0A\u4F20",
|
|
4150
|
+
fill: functionalColor,
|
|
4151
|
+
cursor: "pointer",
|
|
4152
|
+
// TODO padding maxLineWidth 计算优化
|
|
4153
|
+
maxLineWidth: width - padding[2] * 2 - uploadIcon.AABBBounds.width() - 12 - 5,
|
|
4154
|
+
boundsPadding: [4, 12, 5, 5],
|
|
4155
|
+
overflow: "hidden",
|
|
4156
|
+
textBaseline: "middle"
|
|
4157
|
+
});
|
|
4158
|
+
const borderGroup = vrender.createGroup({
|
|
4159
|
+
width: width - 30,
|
|
4160
|
+
height: height - 8,
|
|
4161
|
+
display: "flex",
|
|
4162
|
+
alignItems: "center",
|
|
4163
|
+
justifyContent: "center",
|
|
4164
|
+
stroke: "#D9D9D9",
|
|
4165
|
+
cursor: "pointer"
|
|
4166
|
+
});
|
|
4167
|
+
borderGroup.add(uploadIcon);
|
|
4168
|
+
borderGroup.add(text);
|
|
4169
|
+
borderGroup.addEventListener("click", () => {
|
|
4170
|
+
const columnDefine = table.getBodyColumnDefine(col, row);
|
|
4171
|
+
const lock = columnDefine.lock;
|
|
4172
|
+
const editor = getActiveEditorTable();
|
|
4173
|
+
if (lock || editor?.lock) return;
|
|
4174
|
+
const fileInput = document.createElement("input");
|
|
4175
|
+
fileInput.type = "file";
|
|
4176
|
+
fileInput.style.display = "none";
|
|
4177
|
+
fileInput.addEventListener("change", (e) => {
|
|
4178
|
+
const target = e.target;
|
|
4179
|
+
const files = target.files;
|
|
4180
|
+
if (files && files.length > 0) {
|
|
4181
|
+
const selectedFile = files[0];
|
|
4182
|
+
console.log("\u7528\u6237\u9009\u62E9\u7684\u6587\u4EF6\uFF1A", selectedFile);
|
|
4183
|
+
uploadFileToServer(selectedFile, col, row, props.value);
|
|
4184
|
+
}
|
|
4185
|
+
fileInput.value = "";
|
|
4186
|
+
});
|
|
4187
|
+
document.body.appendChild(fileInput);
|
|
4188
|
+
fileInput.click();
|
|
4189
|
+
setTimeout(() => {
|
|
4190
|
+
document.body.removeChild(fileInput);
|
|
4191
|
+
}, 100);
|
|
4192
|
+
});
|
|
4193
|
+
group.add(borderGroup);
|
|
4194
|
+
const groupname = vrender.createGroup({
|
|
4195
|
+
width,
|
|
4196
|
+
height,
|
|
4197
|
+
display: "flex",
|
|
4198
|
+
flexWrap: "nowrap",
|
|
4199
|
+
justifyContent: "flex-start",
|
|
4200
|
+
// alignContent: 'center',
|
|
4201
|
+
alignItems: "center",
|
|
4202
|
+
// 垂直居中
|
|
4203
|
+
x: 15
|
|
4204
|
+
});
|
|
4205
|
+
const uploadIconName = createIconGraphics(getFileIconName(), { x: 0, y: 0, size: 14, color: functionalColor });
|
|
4206
|
+
const textname = vrender.createText({
|
|
4207
|
+
fontSize: headerIconSize,
|
|
4208
|
+
fontFamily: "sans-serif",
|
|
4209
|
+
text: value.length > 0 ? value[0].name : "",
|
|
4210
|
+
fill: functionalColor,
|
|
4211
|
+
cursor: "pointer",
|
|
4212
|
+
maxLineWidth: width - padding[2] * 2,
|
|
4213
|
+
// marginLeft: 5,
|
|
4214
|
+
boundsPadding: [4, 12, 5, 5]
|
|
4215
|
+
});
|
|
4216
|
+
groupname.add(uploadIconName);
|
|
4217
|
+
groupname.add(textname);
|
|
4218
|
+
groupname.addEventListener("click", () => {
|
|
4219
|
+
const editor = getActiveEditorTable();
|
|
4220
|
+
if (!editor) throw new Error("\u672A\u83B7\u53D6\u5230\u8868\u683C\u7F16\u8F91\u5668\u5B9E\u4F8B");
|
|
4221
|
+
editor.dispatch("cell::attachment::preview", {
|
|
4222
|
+
editor,
|
|
4223
|
+
cellValue: props.value
|
|
4224
|
+
});
|
|
4225
|
+
});
|
|
4226
|
+
if (value.length > 0) {
|
|
4227
|
+
return createGraphicsWithLoading(groupname, loading);
|
|
4228
|
+
} else {
|
|
4229
|
+
return createGraphicsWithLoading(group, loading);
|
|
4230
|
+
}
|
|
4231
|
+
};
|
|
4232
|
+
const uploadFileToServer = async (file, col, row, originValue) => {
|
|
4233
|
+
const name = file.name;
|
|
4234
|
+
const suffix = name.split(".").pop();
|
|
4235
|
+
const column = getActiveEditorTable()?.getColumnDefine(col);
|
|
4236
|
+
let getField;
|
|
4237
|
+
if (column.field) {
|
|
4238
|
+
getField = column.field;
|
|
4239
|
+
}
|
|
4240
|
+
try {
|
|
4241
|
+
const editor = getActiveEditorTable();
|
|
4242
|
+
if (!editor) {
|
|
4243
|
+
throw new Error("\u672A\u83B7\u53D6\u5230\u8868\u683C\u7F16\u8F91\u5668\u5B9E\u4F8B");
|
|
4244
|
+
}
|
|
4245
|
+
const path = `dataset/base/table/upload/${getField}/${id.getUUID()}.${suffix}`;
|
|
4246
|
+
editor.updateCellData(col, row, {
|
|
4247
|
+
loading: true
|
|
4248
|
+
});
|
|
4249
|
+
editor.uploadFile(
|
|
4250
|
+
{
|
|
4251
|
+
file,
|
|
4252
|
+
// 注意:需确保 formData 是后端/编辑器要求的文件类型(如 Blob、File、FormData 等)
|
|
4253
|
+
type: file.type
|
|
4254
|
+
// 类型标识,根据业务传如 'image'/'video'/'file' 等
|
|
4255
|
+
},
|
|
4256
|
+
path
|
|
4257
|
+
).then(() => {
|
|
4258
|
+
console.log("\u4E0A\u4F20\u6210\u529F\uFF01\uFF01");
|
|
4259
|
+
const tableEditor = getActiveEditorTable();
|
|
4260
|
+
if (!tableEditor) throw new Error("[createUploadFileGraphics::onEnd] tableEditor is Nil");
|
|
4261
|
+
const run = () => {
|
|
4262
|
+
const oldData = { ...originValue, loading: false };
|
|
4263
|
+
const { columnId, recordId } = tableEditor.getInteractiveCell(col, row);
|
|
4264
|
+
const data = {
|
|
4265
|
+
...oldData,
|
|
4266
|
+
loading: false,
|
|
4267
|
+
value: [{ name, path }]
|
|
4268
|
+
};
|
|
4269
|
+
tableEditor.updateCellData(col, row, data);
|
|
4270
|
+
tableEditor.dispatch("cells::update", {
|
|
4271
|
+
editor: tableEditor,
|
|
4272
|
+
data: [
|
|
4273
|
+
{
|
|
4274
|
+
current: data,
|
|
4275
|
+
previous: oldData,
|
|
4276
|
+
recordId,
|
|
4277
|
+
columnId
|
|
4278
|
+
}
|
|
4279
|
+
]
|
|
4280
|
+
});
|
|
4281
|
+
return {
|
|
4282
|
+
restore: () => {
|
|
4283
|
+
tableEditor.updateCellData(col, row, oldData);
|
|
4284
|
+
tableEditor.dispatch("cells::update", {
|
|
4285
|
+
editor: tableEditor,
|
|
4286
|
+
data: [
|
|
4287
|
+
{
|
|
4288
|
+
current: oldData,
|
|
4289
|
+
previous: data,
|
|
4290
|
+
recordId,
|
|
4291
|
+
columnId
|
|
4292
|
+
}
|
|
4293
|
+
]
|
|
4294
|
+
});
|
|
4295
|
+
}
|
|
4296
|
+
};
|
|
4297
|
+
};
|
|
4298
|
+
const command = new EditTableCellDataFunctionalCommand(tableEditor, run);
|
|
4299
|
+
tableEditor.commandManager.execute(command);
|
|
4300
|
+
}).catch((e) => {
|
|
4301
|
+
console.log(e);
|
|
4302
|
+
});
|
|
4303
|
+
} catch (error) {
|
|
4304
|
+
console.error("\u6587\u4EF6\u4E0A\u4F20\u5931\u8D25\uFF1A", error);
|
|
4305
|
+
}
|
|
4306
|
+
};
|
|
4307
|
+
|
|
4308
|
+
exports.BaseTableInteractive = BaseTableInteractive;
|
|
4309
|
+
exports.CellContextMenu = CellContextMenu;
|
|
4310
|
+
exports.DateSelect = DateSelect;
|
|
4311
|
+
exports.DateSelectEditorTool = DateSelectEditorTool;
|
|
4312
|
+
exports.EditTableCellDataCommand = EditTableCellDataCommand;
|
|
4313
|
+
exports.EditTableCellDataFunctionalCommand = EditTableCellDataFunctionalCommand;
|
|
4314
|
+
exports.HeaderContextMenu = HeaderContextMenu;
|
|
4315
|
+
exports.INNER_TABLE_COLUMN_KEY_CHECKBOX = INNER_TABLE_COLUMN_KEY_CHECKBOX;
|
|
4316
|
+
exports.INNER_TABLE_COLUMN_KEY_LIST = INNER_TABLE_COLUMN_KEY_LIST;
|
|
4317
|
+
exports.INNER_TABLE_COLUMN_KEY_PLUS = INNER_TABLE_COLUMN_KEY_PLUS;
|
|
4318
|
+
exports.INNER_TABLE_RECORD_ID_KEY = INNER_TABLE_RECORD_ID_KEY;
|
|
4319
|
+
exports.JsonEditorTool = JsonEditorTool;
|
|
4320
|
+
exports.LinkEditor = LinkEditor;
|
|
4321
|
+
exports.LinkEditorTool = LinkEditorTool;
|
|
4322
|
+
exports.MenuItemInputLabel = MenuItemInputLabel;
|
|
4323
|
+
exports.MoreContextMenu = MoreContextMenu;
|
|
4324
|
+
exports.MultiSelectEditorTool = MultiSelectEditorTool;
|
|
4325
|
+
exports.NumEditor = NumEditor;
|
|
4326
|
+
exports.NumEditorTool = NumEditorTool;
|
|
4327
|
+
exports.RecordsManager = RecordsManager;
|
|
4328
|
+
exports.SelectEditor = SelectEditor;
|
|
4329
|
+
exports.SingleSelectEditorTool = SingleSelectEditorTool;
|
|
4330
|
+
exports.Table = Table;
|
|
4331
|
+
exports.TableChangeEvent = TableChangeEvent;
|
|
4332
|
+
exports.TableEditor = TableEditor;
|
|
4333
|
+
exports.TableEditorEvent = TableEditorEvent;
|
|
4334
|
+
exports.TableJsonEditor = TableJsonEditor;
|
|
4335
|
+
exports.TableLayout = TableLayout;
|
|
4336
|
+
exports.TableSelectEditor = TableSelectEditor;
|
|
4337
|
+
exports.TableView = TableView;
|
|
4338
|
+
exports.TextEditor = TextEditor;
|
|
4339
|
+
exports.TextEditorTool = TextEditorTool;
|
|
4340
|
+
exports.UserShow = UserShow;
|
|
4341
|
+
exports.VTableEditorType = VTableEditorType;
|
|
4342
|
+
exports.activeTableIdAtom = activeTableIdAtom;
|
|
4343
|
+
exports.adaptColumnStructure = adaptColumnStructure;
|
|
4344
|
+
exports.adaptRecordStructure = adaptRecordStructure;
|
|
4345
|
+
exports.adaptRecordsStructure = adaptRecordsStructure;
|
|
4346
|
+
exports.adaptedCellPosition = adaptedCellPosition;
|
|
4347
|
+
exports.attachmentColumnCreator = attachmentColumnCreator;
|
|
4348
|
+
exports.checkboxColumnCreator = checkboxColumnCreator;
|
|
4349
|
+
exports.clearDateEditorTool = clearDateEditorTool;
|
|
4350
|
+
exports.clearEditorTool = clearEditorTool;
|
|
4351
|
+
exports.clearJsonEditorTool = clearJsonEditorTool;
|
|
4352
|
+
exports.clearLinkEditorTool = clearLinkEditorTool;
|
|
4353
|
+
exports.clearNumEditorTool = clearNumEditorTool;
|
|
4354
|
+
exports.clearSelectEditorTool = clearSelectEditorTool;
|
|
4355
|
+
exports.clearTextEditorTool = clearTextEditorTool;
|
|
4356
|
+
exports.clearUserShowTool = clearUserShowTool;
|
|
4357
|
+
exports.createBaseTableEditor = createBaseTableEditor;
|
|
4358
|
+
exports.createColumns = createColumns;
|
|
4359
|
+
exports.createDateGraphics = createDateGraphics;
|
|
4360
|
+
exports.createDefaultColumnConfig = createDefaultColumnConfig;
|
|
4361
|
+
exports.createGraphicsWithLoading = createGraphicsWithLoading;
|
|
4362
|
+
exports.createHeaderGraphics = createHeaderGraphics;
|
|
4363
|
+
exports.createIconGraphics = createIconGraphics;
|
|
4364
|
+
exports.createJsonGraphics = createJsonGraphics;
|
|
4365
|
+
exports.createLinkGraphics = createLinkGraphics;
|
|
4366
|
+
exports.createMainColumnCellGraphics = createMainColumnCellGraphics;
|
|
4367
|
+
exports.createMoreGraphics = createMoreGraphics;
|
|
4368
|
+
exports.createMultiSelectGraphic = createMultiSelectGraphic;
|
|
4369
|
+
exports.createNumberGraphics = createNumberGraphics;
|
|
4370
|
+
exports.createPeopleGraphics = createPeopleGraphics;
|
|
4371
|
+
exports.createPlusHeaderGraphics = createPlusHeaderGraphics;
|
|
4372
|
+
exports.createSingleSelectGraphic = createSingleSelectGraphic;
|
|
4373
|
+
exports.createTagGraphic = createTagGraphic;
|
|
4374
|
+
exports.createTextGraphics = createTextGraphics;
|
|
4375
|
+
exports.createTimeLenGraphics = createTimeLenGraphics;
|
|
4376
|
+
exports.createUploadDocumentGraphics = createUploadDocumentGraphics;
|
|
4377
|
+
exports.dateColumnCreator = dateColumnCreator;
|
|
4378
|
+
exports.dateProcess = dateProcess;
|
|
4379
|
+
exports.dropdownColumnCreator = dropdownColumnCreator;
|
|
4380
|
+
exports.editorRegistry = editorRegistry;
|
|
4381
|
+
exports.editorTableStoreAtom = editorTableStoreAtom;
|
|
4382
|
+
exports.getActiveEditorTable = getActiveEditorTable;
|
|
4383
|
+
exports.getActiveTableId = getActiveTableId;
|
|
4384
|
+
exports.getColFromColIndex = getColFromColIndex;
|
|
4385
|
+
exports.getDateEditorData = getDateEditorData;
|
|
4386
|
+
exports.getDateEditorValue = getDateEditorValue;
|
|
4387
|
+
exports.getEditorByToolType = getEditorByToolType;
|
|
4388
|
+
exports.getEditorTableStore = getEditorTableStore;
|
|
4389
|
+
exports.getFunctionalProp = getFunctionalProp;
|
|
4390
|
+
exports.getIconSizeFromFont = getIconSizeFromFont;
|
|
4391
|
+
exports.getJsonEditorData = getJsonEditorData;
|
|
4392
|
+
exports.getJsonEditorValue = getJsonEditorValue;
|
|
4393
|
+
exports.getLinkEditorData = getLinkEditorData;
|
|
4394
|
+
exports.getLinkEditorValue = getLinkEditorValue;
|
|
4395
|
+
exports.getMenu = getMenu;
|
|
4396
|
+
exports.getNumEditorData = getNumEditorData;
|
|
4397
|
+
exports.getNumEditorValue = getNumEditorValue;
|
|
4398
|
+
exports.getProp = getProp;
|
|
4399
|
+
exports.getRowFromRowIndex = getRowFromRowIndex;
|
|
4400
|
+
exports.getSelectEditorData = getSelectEditorData;
|
|
4401
|
+
exports.getSelectEditorValue = getSelectEditorValue;
|
|
4402
|
+
exports.getTextEditorData = getTextEditorData;
|
|
4403
|
+
exports.getTextEditorValue = getTextEditorValue;
|
|
4404
|
+
exports.getTextWidth = getTextWidth;
|
|
4405
|
+
exports.getUserShowData = getUserShowData;
|
|
4406
|
+
exports.getUserShowId = getUserShowId;
|
|
4407
|
+
exports.highlightMerge = highlightMerge;
|
|
4408
|
+
exports.initDateEditorTool = initDateEditorTool;
|
|
4409
|
+
exports.initEditorTool = initEditorTool;
|
|
4410
|
+
exports.initJsonEditorTool = initJsonEditorTool;
|
|
4411
|
+
exports.initLinkEditorTool = initLinkEditorTool;
|
|
4412
|
+
exports.initNumEditorTool = initNumEditorTool;
|
|
4413
|
+
exports.initSelectEditorTool = initSelectEditorTool;
|
|
4414
|
+
exports.initTextEditorTool = initTextEditorTool;
|
|
4415
|
+
exports.initUserShowTool = initUserShowTool;
|
|
4416
|
+
exports.isColumnEditable = isColumnEditable;
|
|
4417
|
+
exports.jsonColumnCreator = jsonColumnCreator;
|
|
4418
|
+
exports.linkColumnCreator = linkColumnCreator;
|
|
4419
|
+
exports.moreColumnCreator = moreColumnCreator;
|
|
4420
|
+
exports.multiSelectColumnCreator = multiSelectColumnCreator;
|
|
4421
|
+
exports.numberColumnCreator = numberColumnCreator;
|
|
4422
|
+
exports.plusColumnCreator = plusColumnCreator;
|
|
4423
|
+
exports.revertRecordStructure = revertRecordStructure;
|
|
4424
|
+
exports.setActiveEditorTable = setActiveEditorTable;
|
|
4425
|
+
exports.setActiveTableId = setActiveTableId;
|
|
4426
|
+
exports.setDateEditorData = setDateEditorData;
|
|
4427
|
+
exports.setDateEditorValue = setDateEditorValue;
|
|
4428
|
+
exports.setEditorTableStore = setEditorTableStore;
|
|
4429
|
+
exports.setJsonEditorData = setJsonEditorData;
|
|
4430
|
+
exports.setJsonEditorValue = setJsonEditorValue;
|
|
4431
|
+
exports.setLinkEditorData = setLinkEditorData;
|
|
4432
|
+
exports.setLinkEditorValue = setLinkEditorValue;
|
|
4433
|
+
exports.setMenu = setMenu;
|
|
4434
|
+
exports.setNumEditorData = setNumEditorData;
|
|
4435
|
+
exports.setNumEditorValue = setNumEditorValue;
|
|
4436
|
+
exports.setSelectEditorData = setSelectEditorData;
|
|
4437
|
+
exports.setSelectEditorValue = setSelectEditorValue;
|
|
4438
|
+
exports.setTextEditorData = setTextEditorData;
|
|
4439
|
+
exports.setTextEditorValue = setTextEditorValue;
|
|
4440
|
+
exports.setUserShowData = setUserShowData;
|
|
4441
|
+
exports.setUserShowId = setUserShowId;
|
|
4442
|
+
exports.tagColumnCreator = tagColumnCreator;
|
|
4443
|
+
exports.theme = theme;
|
|
4444
|
+
exports.timeLenColumnCreator = timeLenColumnCreator;
|
|
4445
|
+
exports.updateSelectEditorCell = updateSelectEditorCell;
|
|
4446
|
+
exports.useActiveEditorTable = useActiveEditorTable;
|
|
4447
|
+
exports.useActiveTableId = useActiveTableId;
|
|
4448
|
+
exports.useComponentVTable = useComponentVTable;
|
|
4449
|
+
exports.useDateEditorData = useDateEditorData;
|
|
4450
|
+
exports.useDateEditorValue = useDateEditorValue;
|
|
4451
|
+
exports.useEditorTableStore = useEditorTableStore;
|
|
4452
|
+
exports.useJsonEditorData = useJsonEditorData;
|
|
4453
|
+
exports.useJsonEditorValue = useJsonEditorValue;
|
|
4454
|
+
exports.useLinkEditorData = useLinkEditorData;
|
|
4455
|
+
exports.useLinkEditorValue = useLinkEditorValue;
|
|
4456
|
+
exports.useMenu = useMenu;
|
|
4457
|
+
exports.useNumEditorData = useNumEditorData;
|
|
4458
|
+
exports.useNumEditorValue = useNumEditorValue;
|
|
4459
|
+
exports.useSelectEditorData = useSelectEditorData;
|
|
4460
|
+
exports.useSelectEditorValue = useSelectEditorValue;
|
|
4461
|
+
exports.useTextEditorData = useTextEditorData;
|
|
4462
|
+
exports.useTextEditorValue = useTextEditorValue;
|
|
4463
|
+
exports.useUserShowData = useUserShowData;
|
|
4464
|
+
exports.useUserShowId = useUserShowId;
|
|
4465
|
+
exports.userColumnCreator = userColumnCreator;
|