cloud-web-corejs 1.1.0-dev.22 → 1.1.0-dev.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/components/bizTab/BizTabListPage.vue +66 -33
- package/src/components/bizTab/README.md +3 -1
- package/src/components/mobile/wf/content.vue +27 -3
- package/src/components/table/index.js +5 -2
- package/src/components/table/plugins/cell-area/index.js +10 -3
- package/src/components/wf/wfStartDialog.vue +1 -0
- package/src/components/wf/wfUtil.js +47 -29
- package/src/components/wf/wfVisibility.js +6 -0
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-mixin.js +7 -0
- package/src/components/xform/form-designer/form-widget/container-widget/data-table-widget.vue +3 -1
- package/src/components/xform/form-designer/form-widget/field-widget/fieldMixin.js +25 -1
- package/src/components/xform/form-designer/setting-panel/form-setting.vue +14 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/data-table-editor.vue +318 -12
- package/src/components/xform/form-designer/setting-panel/property-editor/container-data-table/table-column-dialog.vue +23 -7
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +48 -0
- package/src/components/xform/form-render/container-item/data-table-item.vue +8 -6
- package/src/components/xform/form-render/container-item/data-table-mixin.js +584 -24
- package/src/components/xform/form-render/container-item/detail-h5-item.vue +26 -16
- package/src/components/xform/form-render/container-item/detail-item.vue +350 -446
- package/src/components/xform/form-render/fieldControlMixin.js +2 -0
- package/src/components/xform/form-render/indexMixin.js +25 -15
- package/src/components/xform/mixins/businessLock.js +59 -0
- package/src/components/xform/mixins/wfStart.js +103 -0
- package/src/components/xform/mixins/wfVisibility.js +33 -0
- package/src/components/xform/styles/h5.scss +6 -1
- package/src/components/xform/utils/util.js +2 -0
- package/src/views/user/home/index.vue +1 -1
- package/src/views/user/home/net/distributor.vue +1015 -0
- package/src/views/user/home/net/index.vue +61 -0
|
@@ -29,7 +29,11 @@ import {
|
|
|
29
29
|
} from "../../../../components/xform/utils/tableColumnHelper";
|
|
30
30
|
import { mergeQueryParam } from "../../../../components/xform/utils/queryParamUtil";
|
|
31
31
|
import { isFixedQueryWidget } from "../../../../components/xform/utils/fixedQueryUtil";
|
|
32
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
isUrlValueColumn,
|
|
34
|
+
normalizeAttachmentValue,
|
|
35
|
+
toModelValue,
|
|
36
|
+
} from "../../../../components/xform/utils/attachmentValueUtil";
|
|
33
37
|
import {
|
|
34
38
|
EXPORT_TYPE,
|
|
35
39
|
isItemExport,
|
|
@@ -204,6 +208,8 @@ modules = {
|
|
|
204
208
|
treeKnownFormalKeyRegistry: new Set(),
|
|
205
209
|
treeSingleSavePending: false,
|
|
206
210
|
treeSingleSaveReconcileTask: null,
|
|
211
|
+
editAutoSaveTimers: {},
|
|
212
|
+
editAutoSaveQueue: null,
|
|
207
213
|
// 列/网格未就绪时 setValue 只缓存数据,置此标志延后行 schema 构建
|
|
208
214
|
pendingSchemaInit: false,
|
|
209
215
|
};
|
|
@@ -234,6 +240,13 @@ modules = {
|
|
|
234
240
|
customClass: function () {
|
|
235
241
|
return this.widget.options.customClass || "";
|
|
236
242
|
},
|
|
243
|
+
dataTableStyle: function () {
|
|
244
|
+
let width = this.widget.options.tableWidth;
|
|
245
|
+
if (width === null || width === undefined || width === "") return {};
|
|
246
|
+
width = String(width).trim();
|
|
247
|
+
if (/^\d+(?:\.\d+)?$/.test(width)) width += "px";
|
|
248
|
+
return { width };
|
|
249
|
+
},
|
|
237
250
|
singleRowSelectFlag: function () {
|
|
238
251
|
return !this.widget.options.showCheckBox;
|
|
239
252
|
},
|
|
@@ -284,6 +297,10 @@ modules = {
|
|
|
284
297
|
});
|
|
285
298
|
},
|
|
286
299
|
beforeDestroy: function () {
|
|
300
|
+
Object.values(this.editAutoSaveTimers || {}).forEach((timer) => {
|
|
301
|
+
clearTimeout(timer);
|
|
302
|
+
});
|
|
303
|
+
this.editAutoSaveTimers = {};
|
|
287
304
|
this.unregisterFromRefList();
|
|
288
305
|
},
|
|
289
306
|
methods: {
|
|
@@ -942,6 +959,430 @@ modules = {
|
|
|
942
959
|
let o = widget.options.name;
|
|
943
960
|
return (widget.options.keyNameEnabled && widget.options.keyName) || o;
|
|
944
961
|
},
|
|
962
|
+
/** @param {Object} obj VXE 单元格参数。@returns {Object|null} 当前单元格实际使用的编辑组件 schema。 */
|
|
963
|
+
getClipboardCellWidget(obj) {
|
|
964
|
+
const params = obj?.column?.params || {};
|
|
965
|
+
const template = params.editWidget || params.widget;
|
|
966
|
+
if (!template) return null;
|
|
967
|
+
const rowSchema = this.getRowFieldSchema(obj.row);
|
|
968
|
+
return rowSchema?.[template.id] || template;
|
|
969
|
+
},
|
|
970
|
+
/** @param {Object} obj VXE 单元格参数。@returns {Boolean} 粘贴是否可以修改该单元格。 */
|
|
971
|
+
canPasteTableCell(obj) {
|
|
972
|
+
const column = obj?.column;
|
|
973
|
+
if (!column?.editRender || column.editRender.enabled === false) {
|
|
974
|
+
return false;
|
|
975
|
+
}
|
|
976
|
+
const widget = this.getClipboardCellWidget(obj);
|
|
977
|
+
if (widget?.options?.disabled || widget?.options?.readonly) {
|
|
978
|
+
return false;
|
|
979
|
+
}
|
|
980
|
+
if (!this.isTableCellEditable(obj)) {
|
|
981
|
+
return false;
|
|
982
|
+
}
|
|
983
|
+
const editOpts = obj?.$table?.editOpts || {};
|
|
984
|
+
const beforeEditMethod = editOpts.beforeEditMethod || editOpts.activeMethod;
|
|
985
|
+
return !beforeEditMethod || beforeEditMethod(obj) !== false;
|
|
986
|
+
},
|
|
987
|
+
/**
|
|
988
|
+
* 把剪贴板里的展示文本转换成字段真实值。选项列按 label 反查 value,避免从表格
|
|
989
|
+
* 复制出的中文标签直接写进 code 字段。
|
|
990
|
+
* @param {Object} widget 字段组件 schema。
|
|
991
|
+
* @param {*} cellValue 剪贴板文本。
|
|
992
|
+
* @returns {{accepted: Boolean, value: *}}
|
|
993
|
+
*/
|
|
994
|
+
resolveTablePasteValue(widget, cellValue) {
|
|
995
|
+
const type = widget?.type;
|
|
996
|
+
const options = widget?.options || {};
|
|
997
|
+
const text = cellValue == null ? "" : String(cellValue).trim();
|
|
998
|
+
if (type === "number") {
|
|
999
|
+
if (!text) return { accepted: true, value: null };
|
|
1000
|
+
return isNaN(text)
|
|
1001
|
+
? { accepted: false, value: null }
|
|
1002
|
+
: { accepted: true, value: Number(text) };
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
const isMultiple = type === "checkbox"
|
|
1006
|
+
|| (type === "select" && options.multiple);
|
|
1007
|
+
const isOptionWidget = ["select", "radio", "checkbox", "status"]
|
|
1008
|
+
.includes(type);
|
|
1009
|
+
if (!isOptionWidget) {
|
|
1010
|
+
return { accepted: true, value: cellValue };
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
const items = type === "status"
|
|
1014
|
+
? options.statusParam || []
|
|
1015
|
+
: options.optionItems || [];
|
|
1016
|
+
const labelKey = this.getOptionItemLabelKey(widget);
|
|
1017
|
+
const valueKey = this.getOptionItemValueKey(widget);
|
|
1018
|
+
if (!text) {
|
|
1019
|
+
return { accepted: true, value: isMultiple ? [] : null };
|
|
1020
|
+
}
|
|
1021
|
+
const parts = isMultiple ? text.split(/[,,;;\n\r]+/) : [text];
|
|
1022
|
+
const values = [];
|
|
1023
|
+
for (let index = 0; index < parts.length; index++) {
|
|
1024
|
+
const part = parts[index].trim();
|
|
1025
|
+
const matched = items.find(
|
|
1026
|
+
(item) =>
|
|
1027
|
+
String(this.$t1(item[labelKey])) === part
|
|
1028
|
+
|| String(item[valueKey]) === part
|
|
1029
|
+
);
|
|
1030
|
+
if (!matched) return { accepted: false, value: null };
|
|
1031
|
+
values.push(matched[valueKey]);
|
|
1032
|
+
}
|
|
1033
|
+
return {
|
|
1034
|
+
accepted: true,
|
|
1035
|
+
value: isMultiple ? values : values[0],
|
|
1036
|
+
};
|
|
1037
|
+
},
|
|
1038
|
+
/** @param {Object} obj VXE 单元格参数。@returns {Boolean} 是否为附件编辑列。 */
|
|
1039
|
+
isClipboardAttachmentCell(obj) {
|
|
1040
|
+
const widget = this.getClipboardCellWidget(obj);
|
|
1041
|
+
return !!widget && isAttachmentWidgetType(widget.type);
|
|
1042
|
+
},
|
|
1043
|
+
/**
|
|
1044
|
+
* @param {Object} obj VXE 单元格参数。
|
|
1045
|
+
* @param {File[]} files 剪贴板文件。
|
|
1046
|
+
* @returns {Promise<Boolean>} 至少一个附件上传成功时为 true。
|
|
1047
|
+
*/
|
|
1048
|
+
pasteTableAttachments(obj, files) {
|
|
1049
|
+
if (!files.length || !this.$baseUpload?.upload) {
|
|
1050
|
+
return Promise.resolve(false);
|
|
1051
|
+
}
|
|
1052
|
+
const widget = this.getClipboardCellWidget(obj);
|
|
1053
|
+
const options = widget?.options || {};
|
|
1054
|
+
const field = obj.column.field;
|
|
1055
|
+
const currentRows = normalizeAttachmentValue(obj.row[field]);
|
|
1056
|
+
const limit = Number(options.limit) || 0;
|
|
1057
|
+
const remaining = limit
|
|
1058
|
+
? Math.max(limit - currentRows.length, 0)
|
|
1059
|
+
: files.length;
|
|
1060
|
+
const acceptedFiles = files.slice(0, remaining);
|
|
1061
|
+
if (!acceptedFiles.length) {
|
|
1062
|
+
this.$message.warning(this.$t1("附件数量已达到上限"));
|
|
1063
|
+
return Promise.resolve(false);
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
const tasks = acceptedFiles.map((file) => new Promise((resolve) => {
|
|
1067
|
+
let settled = false;
|
|
1068
|
+
const finish = (result) => {
|
|
1069
|
+
if (settled) return;
|
|
1070
|
+
settled = true;
|
|
1071
|
+
resolve(result);
|
|
1072
|
+
};
|
|
1073
|
+
try {
|
|
1074
|
+
const requestTask = this.$baseUpload.upload({
|
|
1075
|
+
file,
|
|
1076
|
+
isLoading: true,
|
|
1077
|
+
callback: (res) => {
|
|
1078
|
+
if (!res || res.type !== "success") {
|
|
1079
|
+
this.$message.error(
|
|
1080
|
+
res?.content
|
|
1081
|
+
|| this.$t1("[{name}]上传失败", { name: file.name })
|
|
1082
|
+
);
|
|
1083
|
+
finish(false);
|
|
1084
|
+
return;
|
|
1085
|
+
}
|
|
1086
|
+
const attachment = res.objx || {};
|
|
1087
|
+
attachment.name = attachment.name || file.name;
|
|
1088
|
+
const rows = normalizeAttachmentValue(obj.row[field]).slice();
|
|
1089
|
+
if (limit && rows.length >= limit) {
|
|
1090
|
+
finish(false);
|
|
1091
|
+
return;
|
|
1092
|
+
}
|
|
1093
|
+
rows.push(attachment);
|
|
1094
|
+
this.$set(obj.row, field, toModelValue(rows, options));
|
|
1095
|
+
this.$nextTick(() => obj.$table?.updateFooter());
|
|
1096
|
+
finish(true);
|
|
1097
|
+
},
|
|
1098
|
+
});
|
|
1099
|
+
if (requestTask && typeof requestTask.catch === "function") {
|
|
1100
|
+
requestTask.catch((error) => {
|
|
1101
|
+
this.$message.error(
|
|
1102
|
+
error?.message
|
|
1103
|
+
|| this.$t1("[{name}]上传失败", { name: file.name })
|
|
1104
|
+
);
|
|
1105
|
+
finish(false);
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
} catch (error) {
|
|
1109
|
+
this.$message.error(
|
|
1110
|
+
error?.message || this.$t1("[{name}]上传失败", { name: file.name })
|
|
1111
|
+
);
|
|
1112
|
+
finish(false);
|
|
1113
|
+
}
|
|
1114
|
+
}));
|
|
1115
|
+
return Promise.all(tasks).then((results) => results.some(Boolean));
|
|
1116
|
+
},
|
|
1117
|
+
/** @param {Object} obj VXE 单元格参数。@returns {Boolean|Promise<Boolean>} 是否修改了单元格。 */
|
|
1118
|
+
pasteTableCell(obj) {
|
|
1119
|
+
if (!this.canPasteTableCell(obj)) return false;
|
|
1120
|
+
if (this.isClipboardAttachmentCell(obj)) {
|
|
1121
|
+
if (!this.widget.options.clipboardAttachmentEnabled) return false;
|
|
1122
|
+
// 文件必须在原生 paste 事件的同步调用栈中读取,异步后浏览器会清掉该数据。
|
|
1123
|
+
const event = window.event;
|
|
1124
|
+
const clipboardData = obj.clipData?.clipboardData
|
|
1125
|
+
|| event?.clipboardData
|
|
1126
|
+
|| window.clipboardData;
|
|
1127
|
+
const files = clipboardData
|
|
1128
|
+
? Array.from(clipboardData.files || [])
|
|
1129
|
+
: [];
|
|
1130
|
+
return this.pasteTableAttachments(obj, files);
|
|
1131
|
+
}
|
|
1132
|
+
const widget = this.getClipboardCellWidget(obj);
|
|
1133
|
+
const resolved = this.resolveTablePasteValue(widget, obj.cellValue);
|
|
1134
|
+
if (resolved.accepted) {
|
|
1135
|
+
this.$set(obj.row, obj.column.field, resolved.value);
|
|
1136
|
+
return true;
|
|
1137
|
+
}
|
|
1138
|
+
if (this.widget.options.clipboardInvalidValueStrategy === "warn") {
|
|
1139
|
+
this.$message.warning(
|
|
1140
|
+
`字段 ${obj.column.title || obj.column.field} 的粘贴值无效,已跳过。`
|
|
1141
|
+
);
|
|
1142
|
+
}
|
|
1143
|
+
return false;
|
|
1144
|
+
},
|
|
1145
|
+
/**
|
|
1146
|
+
* @param {Object} $table VXE Table 实例。
|
|
1147
|
+
* @param {Array<Object>} rows 本次粘贴实际修改的行。
|
|
1148
|
+
* @description 按顺序复用单行保存,避免并发触发行保存锁。
|
|
1149
|
+
*/
|
|
1150
|
+
async autoSaveClipboardRows($table, rows) {
|
|
1151
|
+
const savedKeys = new Set();
|
|
1152
|
+
for (const sourceRow of rows || []) {
|
|
1153
|
+
const rowKey = sourceRow?._X_ROW_KEY;
|
|
1154
|
+
if (rowKey && savedKeys.has(rowKey)) continue;
|
|
1155
|
+
if (rowKey) savedKeys.add(rowKey);
|
|
1156
|
+
const formRows = this.formModel[this.fieldKeyName] || [];
|
|
1157
|
+
const row = rowKey
|
|
1158
|
+
? formRows.find((item) => item?._X_ROW_KEY === rowKey) || sourceRow
|
|
1159
|
+
: sourceRow;
|
|
1160
|
+
await this.saveEditRow(
|
|
1161
|
+
{ row, $table },
|
|
1162
|
+
{ skipConfirm: true }
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
/** @returns {Boolean} 是否开启编辑表格自动保存,兼容早期粘贴专用配置名。 */
|
|
1167
|
+
isTableAutoSaveEnabled() {
|
|
1168
|
+
const options = this.widget.options;
|
|
1169
|
+
return !!(
|
|
1170
|
+
options.autoSaveEnabled
|
|
1171
|
+
|| options.clipboardAutoSaveEnabled
|
|
1172
|
+
);
|
|
1173
|
+
},
|
|
1174
|
+
/** @param {String} trigger 触发来源。@returns {Boolean} 当前来源是否启用自动保存。 */
|
|
1175
|
+
isAutoSaveTriggerEnabled(trigger) {
|
|
1176
|
+
const triggers = this.widget.options.autoSaveTrigger;
|
|
1177
|
+
if (!Array.isArray(triggers)) {
|
|
1178
|
+
return true;
|
|
1179
|
+
}
|
|
1180
|
+
return triggers.includes(trigger);
|
|
1181
|
+
},
|
|
1182
|
+
/**
|
|
1183
|
+
* @param {Object} obj 行内字段携带的 VXE 单元格参数。
|
|
1184
|
+
* @returns {Boolean} 是否已安排自动保存。
|
|
1185
|
+
* @description 失焦后短延迟保存;同一行重复失焦会合并为一次请求。
|
|
1186
|
+
*/
|
|
1187
|
+
scheduleEditRowAutoSave(obj, trigger = "blur") {
|
|
1188
|
+
if (
|
|
1189
|
+
!this.widget.options.isEditTable
|
|
1190
|
+
|| !this.isTableAutoSaveEnabled()
|
|
1191
|
+
|| !this.isAutoSaveTriggerEnabled(trigger)
|
|
1192
|
+
|| !obj?.row
|
|
1193
|
+
|| !obj?.$table
|
|
1194
|
+
|| !this.isTableCellEditable(obj, true)
|
|
1195
|
+
) {
|
|
1196
|
+
return false;
|
|
1197
|
+
}
|
|
1198
|
+
const editSnapshot = obj.$table.editCloneRow;
|
|
1199
|
+
if (
|
|
1200
|
+
editSnapshot
|
|
1201
|
+
&& this.$baseLodash.isEqual(editSnapshot, obj.row)
|
|
1202
|
+
) {
|
|
1203
|
+
return false;
|
|
1204
|
+
}
|
|
1205
|
+
const rowKey = obj.row._X_ROW_KEY || "current";
|
|
1206
|
+
const configuredDelay = Number(this.widget.options.autoSaveDelay);
|
|
1207
|
+
const autoSaveDelay = Number.isFinite(configuredDelay)
|
|
1208
|
+
? Math.max(configuredDelay, 0)
|
|
1209
|
+
: 200;
|
|
1210
|
+
clearTimeout(this.editAutoSaveTimers[rowKey]);
|
|
1211
|
+
this.editAutoSaveTimers[rowKey] = setTimeout(() => {
|
|
1212
|
+
delete this.editAutoSaveTimers[rowKey];
|
|
1213
|
+
const runSave = async () => {
|
|
1214
|
+
const rows = this.formModel[this.fieldKeyName] || [];
|
|
1215
|
+
const currentRow = obj.row._X_ROW_KEY
|
|
1216
|
+
? rows.find((row) => row?._X_ROW_KEY === obj.row._X_ROW_KEY)
|
|
1217
|
+
|| obj.row
|
|
1218
|
+
: obj.row;
|
|
1219
|
+
return this.saveEditRow(
|
|
1220
|
+
{ ...obj, row: currentRow },
|
|
1221
|
+
{ skipConfirm: true }
|
|
1222
|
+
);
|
|
1223
|
+
};
|
|
1224
|
+
this.editAutoSaveQueue = Promise.resolve(this.editAutoSaveQueue)
|
|
1225
|
+
.catch(() => false)
|
|
1226
|
+
.then(runSave)
|
|
1227
|
+
.catch((error) => {
|
|
1228
|
+
this.$message.error(error?.message || "失焦自动保存失败。");
|
|
1229
|
+
return false;
|
|
1230
|
+
});
|
|
1231
|
+
}, autoSaveDelay);
|
|
1232
|
+
return true;
|
|
1233
|
+
},
|
|
1234
|
+
/**
|
|
1235
|
+
* @param {Object} $table VXE 表实例。
|
|
1236
|
+
* @param {Array<String>} insertedRowKeys 本次粘贴自动补出的稳定行键。
|
|
1237
|
+
* @description 把自动补出的行同步回 xform 表单模型。树表的 fullData 只有根节点,
|
|
1238
|
+
* 因此只能合并本次新增节点,不能用它覆盖规范扁平数据。
|
|
1239
|
+
*/
|
|
1240
|
+
syncClipboardTableRows($table, insertedRowKeys = []) {
|
|
1241
|
+
if (this.widget.options.isTreeTable) {
|
|
1242
|
+
if (!insertedRowKeys.length) return;
|
|
1243
|
+
const visibleRows = $table?.afterFullData || [];
|
|
1244
|
+
const keySet = new Set(insertedRowKeys);
|
|
1245
|
+
const insertedRows = visibleRows.filter(
|
|
1246
|
+
(row) => row?._X_ROW_KEY && keySet.has(row._X_ROW_KEY)
|
|
1247
|
+
);
|
|
1248
|
+
const formRows = Array.isArray(this.formModel[this.fieldKeyName])
|
|
1249
|
+
? this.formModel[this.fieldKeyName]
|
|
1250
|
+
: [];
|
|
1251
|
+
const existingKeys = new Set(formRows.map((row) => row?._X_ROW_KEY));
|
|
1252
|
+
const nextRows = formRows.concat(
|
|
1253
|
+
insertedRows.filter((row) => !existingKeys.has(row._X_ROW_KEY))
|
|
1254
|
+
);
|
|
1255
|
+
this.$set(this.formModel, this.fieldKeyName, nextRows);
|
|
1256
|
+
this.initRowIdData();
|
|
1257
|
+
this.initFieldSchemaData();
|
|
1258
|
+
return;
|
|
1259
|
+
}
|
|
1260
|
+
const rows = $table?.getTableData()?.fullData || [];
|
|
1261
|
+
let formRows = this.formModel[this.fieldKeyName];
|
|
1262
|
+
if (!Array.isArray(formRows)) {
|
|
1263
|
+
this.$set(this.formModel, this.fieldKeyName, rows);
|
|
1264
|
+
this.fieldModel = rows;
|
|
1265
|
+
return;
|
|
1266
|
+
}
|
|
1267
|
+
if (formRows !== rows) {
|
|
1268
|
+
formRows.splice(0, formRows.length);
|
|
1269
|
+
formRows.push(...rows);
|
|
1270
|
+
}
|
|
1271
|
+
this.fieldModel = formRows;
|
|
1272
|
+
this.initRowIdData();
|
|
1273
|
+
this.initFieldSchemaData();
|
|
1274
|
+
},
|
|
1275
|
+
/** @returns {Object} xform 编辑表的区域复制粘贴配置。 */
|
|
1276
|
+
buildTableClipboardConfig() {
|
|
1277
|
+
const options = this.widget.options;
|
|
1278
|
+
if (!options.isEditTable || !options.clipboardEnabled) {
|
|
1279
|
+
return {};
|
|
1280
|
+
}
|
|
1281
|
+
let insertedRowKeys = [];
|
|
1282
|
+
let pasteBatch = null;
|
|
1283
|
+
const excludeFields = Array.from(new Set([
|
|
1284
|
+
"operate",
|
|
1285
|
+
...(Array.isArray(options.clipboardExcludeFields)
|
|
1286
|
+
? options.clipboardExcludeFields
|
|
1287
|
+
: []),
|
|
1288
|
+
]));
|
|
1289
|
+
return {
|
|
1290
|
+
mouseConfig: { area: true },
|
|
1291
|
+
areaConfig: {
|
|
1292
|
+
multiple: false,
|
|
1293
|
+
excludeFields,
|
|
1294
|
+
selectCellByHeader: false,
|
|
1295
|
+
},
|
|
1296
|
+
keyboardConfig: {
|
|
1297
|
+
isClip: true,
|
|
1298
|
+
isEdit: true,
|
|
1299
|
+
isDel: false,
|
|
1300
|
+
isEsc: true,
|
|
1301
|
+
},
|
|
1302
|
+
clipConfig: {
|
|
1303
|
+
isCopy: true,
|
|
1304
|
+
isPaste: true,
|
|
1305
|
+
isCut: false,
|
|
1306
|
+
excludeFields,
|
|
1307
|
+
isRowIncrement: !!options.clipboardRowIncrementEnabled,
|
|
1308
|
+
beforePasteMethod: () => {
|
|
1309
|
+
pasteBatch = {
|
|
1310
|
+
rows: new Map(),
|
|
1311
|
+
tasks: [],
|
|
1312
|
+
};
|
|
1313
|
+
},
|
|
1314
|
+
createRowsMethod: ({ insertRows, targetRow }) => {
|
|
1315
|
+
insertedRowKeys = [];
|
|
1316
|
+
const treeContext = options.isTreeTable
|
|
1317
|
+
? this.getTreeContext()
|
|
1318
|
+
: null;
|
|
1319
|
+
const rows = insertRows.map(() => {
|
|
1320
|
+
const row = {
|
|
1321
|
+
...this.createNewTableData(true),
|
|
1322
|
+
_X_ROW_KEY: "row_" + generateId(),
|
|
1323
|
+
};
|
|
1324
|
+
if (treeContext) {
|
|
1325
|
+
row[treeContext.identityConfig.physicalIdField] = null;
|
|
1326
|
+
this.ensureNewTreeRowKey(row, treeContext);
|
|
1327
|
+
const insertMode = options.treePasteInsertMode || "root";
|
|
1328
|
+
const siblingParent = targetRow
|
|
1329
|
+
? targetRow[treeContext.fields.parentField]
|
|
1330
|
+
: treeContext.identityConfig.rootParentValue;
|
|
1331
|
+
row[treeContext.fields.parentField]
|
|
1332
|
+
= insertMode === "sibling"
|
|
1333
|
+
? siblingParent
|
|
1334
|
+
: treeContext.identityConfig.rootParentValue;
|
|
1335
|
+
}
|
|
1336
|
+
insertedRowKeys.push(row._X_ROW_KEY);
|
|
1337
|
+
return row;
|
|
1338
|
+
});
|
|
1339
|
+
if (treeContext) {
|
|
1340
|
+
this.validateNewTreeRows(rows, treeContext);
|
|
1341
|
+
}
|
|
1342
|
+
return rows;
|
|
1343
|
+
},
|
|
1344
|
+
pasteMethod: (obj) => {
|
|
1345
|
+
const batch = pasteBatch;
|
|
1346
|
+
const rememberRow = () => {
|
|
1347
|
+
if (!batch) return;
|
|
1348
|
+
const key = obj.row?._X_ROW_KEY || obj.row;
|
|
1349
|
+
batch.rows.set(key, obj.row);
|
|
1350
|
+
};
|
|
1351
|
+
const result = this.pasteTableCell(obj);
|
|
1352
|
+
if (result && typeof result.then === "function") {
|
|
1353
|
+
batch?.tasks.push(
|
|
1354
|
+
Promise.resolve(result).then((changed) => {
|
|
1355
|
+
if (changed) rememberRow();
|
|
1356
|
+
})
|
|
1357
|
+
);
|
|
1358
|
+
} else if (result) {
|
|
1359
|
+
rememberRow();
|
|
1360
|
+
}
|
|
1361
|
+
},
|
|
1362
|
+
afterPasteMethod: ({ $table }) => {
|
|
1363
|
+
$table.clearActived();
|
|
1364
|
+
this.syncClipboardTableRows($table, insertedRowKeys);
|
|
1365
|
+
insertedRowKeys = [];
|
|
1366
|
+
const batch = pasteBatch;
|
|
1367
|
+
pasteBatch = null;
|
|
1368
|
+
if (
|
|
1369
|
+
this.isTableAutoSaveEnabled()
|
|
1370
|
+
&& this.isAutoSaveTriggerEnabled("paste")
|
|
1371
|
+
&& batch
|
|
1372
|
+
) {
|
|
1373
|
+
Promise.all(batch.tasks)
|
|
1374
|
+
.then(() => this.autoSaveClipboardRows(
|
|
1375
|
+
$table,
|
|
1376
|
+
Array.from(batch.rows.values())
|
|
1377
|
+
))
|
|
1378
|
+
.catch((error) => {
|
|
1379
|
+
this.$message.error(error?.message || "粘贴后自动保存失败。");
|
|
1380
|
+
});
|
|
1381
|
+
}
|
|
1382
|
+
},
|
|
1383
|
+
},
|
|
1384
|
+
};
|
|
1385
|
+
},
|
|
945
1386
|
/** @returns {String} 数据集必填校验提示。 */
|
|
946
1387
|
getDatasetRequiredHint() {
|
|
947
1388
|
if (this.widget.options.requiredHint) {
|
|
@@ -2418,13 +2859,13 @@ modules = {
|
|
|
2418
2859
|
let pagerConfig = {};
|
|
2419
2860
|
let editDefaultRow, treeNodeParam, treeConfig;
|
|
2420
2861
|
let isTreeTable = this.widget.options.isTreeTable;
|
|
2862
|
+
if (this.widget.options.editDefaultRow) {
|
|
2863
|
+
editDefaultRow = this.handleCustomEvent(
|
|
2864
|
+
this.widget.options.editDefaultRow
|
|
2865
|
+
);
|
|
2866
|
+
}
|
|
2421
2867
|
if (isTreeTable) {
|
|
2422
|
-
|
|
2423
|
-
if (this.widget.options.editDefaultRow) {
|
|
2424
|
-
editDefaultRow = this.handleCustomEvent(
|
|
2425
|
-
this.widget.options.editDefaultRow
|
|
2426
|
-
);
|
|
2427
|
-
}
|
|
2868
|
+
const configuredTree = this.widget.options.treeConfig || {};
|
|
2428
2869
|
treeConfig = {
|
|
2429
2870
|
lazy: false,
|
|
2430
2871
|
// 树表主键列显式声明为唯一事实源:vxe transform 建树(toArrayTree)
|
|
@@ -2441,6 +2882,8 @@ modules = {
|
|
|
2441
2882
|
// 所有行,vxe 按引用匹配的展开记录会全部失效。reserve 按 _X_ROW_KEY
|
|
2442
2883
|
// 恢复展开状态(克隆保留该键),查询重载会重新生成键,互不干扰。
|
|
2443
2884
|
reserve: true,
|
|
2885
|
+
...configuredTree,
|
|
2886
|
+
transform: true,
|
|
2444
2887
|
loadMethod: ({ $table, row }) => {
|
|
2445
2888
|
// 模拟后台接口
|
|
2446
2889
|
let $grid = that.getGridTable();
|
|
@@ -2610,6 +3053,7 @@ modules = {
|
|
|
2610
3053
|
// editRules
|
|
2611
3054
|
};
|
|
2612
3055
|
}
|
|
3056
|
+
const clipboardOpts = this.buildTableClipboardConfig();
|
|
2613
3057
|
let showFooter = this.widget.options.showGridFooter || false;
|
|
2614
3058
|
let otherConfig = {};
|
|
2615
3059
|
if (this.widget.options.hideGridCheckBox) {
|
|
@@ -2682,14 +3126,17 @@ modules = {
|
|
|
2682
3126
|
};
|
|
2683
3127
|
}
|
|
2684
3128
|
let hostTreeIdentityConfig = {
|
|
3129
|
+
...(this.widget.options.treeIdentityConfig || {}),
|
|
2685
3130
|
...(dataTableConfig.otherConfig?.treeIdentityConfig || {}),
|
|
2686
3131
|
...(dataTableConfig.treeIdentityConfig || {}),
|
|
2687
3132
|
};
|
|
2688
3133
|
let hostTreeCopyConfig = {
|
|
3134
|
+
...(this.widget.options.treeCopyConfig || {}),
|
|
2689
3135
|
...(dataTableConfig.otherConfig?.treeCopyConfig || {}),
|
|
2690
3136
|
...(dataTableConfig.treeCopyConfig || {}),
|
|
2691
3137
|
};
|
|
2692
3138
|
let hostTreeSubmitConfig = {
|
|
3139
|
+
...(this.widget.options.treeSubmitConfig || {}),
|
|
2693
3140
|
...(dataTableConfig.otherConfig?.treeSubmitConfig || {}),
|
|
2694
3141
|
...(dataTableConfig.treeSubmitConfig || {}),
|
|
2695
3142
|
};
|
|
@@ -2702,6 +3149,7 @@ modules = {
|
|
|
2702
3149
|
columns: columns,
|
|
2703
3150
|
searchColumns: searchColumns,
|
|
2704
3151
|
isQueryAllPage,
|
|
3152
|
+
readQueryAllPage: !this.widget.options.isNotReadQueryAllPage,
|
|
2705
3153
|
exportItemConfig,
|
|
2706
3154
|
vform: true,
|
|
2707
3155
|
...(this.getDynamicColumnSourceType() !== "none"
|
|
@@ -2718,11 +3166,14 @@ modules = {
|
|
|
2718
3166
|
config: {
|
|
2719
3167
|
height: height,
|
|
2720
3168
|
showFooter,
|
|
2721
|
-
pagerConfig
|
|
3169
|
+
pagerConfig: this.widget.options.showPagination
|
|
3170
|
+
? pagerConfig
|
|
3171
|
+
: false,
|
|
2722
3172
|
treeConfig,
|
|
2723
3173
|
rowConfig,
|
|
2724
3174
|
headerCellStyle,
|
|
2725
3175
|
...editOpts,
|
|
3176
|
+
...clipboardOpts,
|
|
2726
3177
|
...hostTableConfig,
|
|
2727
3178
|
|
|
2728
3179
|
/*rowConfig:{
|
|
@@ -2820,7 +3271,7 @@ modules = {
|
|
|
2820
3271
|
});
|
|
2821
3272
|
}
|
|
2822
3273
|
|
|
2823
|
-
if (page.pageSize !== undefined) {
|
|
3274
|
+
if (page && page.pageSize !== undefined) {
|
|
2824
3275
|
queryParams["size"] = page.pageSize;
|
|
2825
3276
|
queryParams["current"] = page.currentPage;
|
|
2826
3277
|
}
|
|
@@ -3680,8 +4131,10 @@ modules = {
|
|
|
3680
4131
|
async deleteRow(row, rowIndex) {
|
|
3681
4132
|
let isTreeTable = this.widget.options.isTreeTable;
|
|
3682
4133
|
if (isTreeTable) {
|
|
3683
|
-
this.removeTreeRow({ row });
|
|
3684
|
-
|
|
4134
|
+
return this.removeTreeRow({ row, rowIndex });
|
|
4135
|
+
}
|
|
4136
|
+
if (!this.canDeleteTableRow({ row, rowIndex })) {
|
|
4137
|
+
return false;
|
|
3685
4138
|
}
|
|
3686
4139
|
delete this.fieldSchemaMap[row._X_ROW_KEY];
|
|
3687
4140
|
let $grid = this.getGridTable();
|
|
@@ -4482,15 +4935,18 @@ modules = {
|
|
|
4482
4935
|
/**
|
|
4483
4936
|
* 保存当前编辑行。持久化行原位合并;新身份以回查结果重建树关系。
|
|
4484
4937
|
* @param {Object} obj VXE 插槽参数,必须包含 row 和 $table。
|
|
4938
|
+
* @param {Object} options 保存选项;skipConfirm 用于粘贴后的自动保存。
|
|
4485
4939
|
*/
|
|
4486
|
-
async saveEditRow(obj) {
|
|
4940
|
+
async saveEditRow(obj, options = {}) {
|
|
4487
4941
|
let formRef = this.getFormRef();
|
|
4488
4942
|
let formConfig = this.formConfig;
|
|
4489
4943
|
let entity = formConfig.entity;
|
|
4490
4944
|
if (!entity) return;
|
|
4491
4945
|
let reportTemplate = formRef?.reportTemplate;
|
|
4492
4946
|
let formCode = reportTemplate?.formCode;
|
|
4493
|
-
let scriptCode =
|
|
4947
|
+
let scriptCode = this.widget.options.rowSaveScriptCode
|
|
4948
|
+
|| formConfig.saveScriptCode
|
|
4949
|
+
|| "saveUpdate";
|
|
4494
4950
|
|
|
4495
4951
|
let $grid = obj.$table.$xegrid;
|
|
4496
4952
|
if (typeof this.treeSingleSaveReconcileTask === "function") {
|
|
@@ -4543,6 +4999,12 @@ modules = {
|
|
|
4543
4999
|
const rowValid = controlled ? await this.validateEditRowAsync(obj.row) : this.validateEditRow(obj.row);
|
|
4544
5000
|
if (!rowValid) return false;
|
|
4545
5001
|
const fieldControlSnapshot = controlled ? formRef.captureFieldControlSubmission() : null;
|
|
5002
|
+
const beforeSaveResult = this.handleCustomEvent(
|
|
5003
|
+
this.widget.options.beforeRowSave,
|
|
5004
|
+
["rowData", "tableParam"],
|
|
5005
|
+
[obj.row, obj]
|
|
5006
|
+
);
|
|
5007
|
+
if (beforeSaveResult === false) return false;
|
|
4546
5008
|
|
|
4547
5009
|
let requestRow = obj.row;
|
|
4548
5010
|
if (treeContext) {
|
|
@@ -4612,10 +5074,12 @@ modules = {
|
|
|
4612
5074
|
);
|
|
4613
5075
|
}
|
|
4614
5076
|
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
5077
|
+
if (!options.skipConfirm) {
|
|
5078
|
+
try {
|
|
5079
|
+
await this.$baseConfirm("您确定要保存吗?");
|
|
5080
|
+
} catch (error) {
|
|
5081
|
+
return false;
|
|
5082
|
+
}
|
|
4619
5083
|
}
|
|
4620
5084
|
|
|
4621
5085
|
await $grid.clearActived();
|
|
@@ -4638,8 +5102,8 @@ modules = {
|
|
|
4638
5102
|
let urlValueProps = this.getUrlValueAttachmentProps();
|
|
4639
5103
|
Object.keys(mainData).forEach((key) => {
|
|
4640
5104
|
if (
|
|
4641
|
-
key.startsWith("attachments_")
|
|
4642
|
-
urlValueProps.indexOf(key) === -1
|
|
5105
|
+
key.startsWith("attachments_")
|
|
5106
|
+
&& urlValueProps.indexOf(key) === -1
|
|
4643
5107
|
) {
|
|
4644
5108
|
formData[key] = mainData[key];
|
|
4645
5109
|
}
|
|
@@ -4848,6 +5312,11 @@ modules = {
|
|
|
4848
5312
|
await $grid.updateData();
|
|
4849
5313
|
}
|
|
4850
5314
|
delete obj.$table.editCloneRow;
|
|
5315
|
+
this.handleCustomEvent(
|
|
5316
|
+
this.widget.options.afterRowSave,
|
|
5317
|
+
["rowData", "res"],
|
|
5318
|
+
[obj.row, rowResponse]
|
|
5319
|
+
);
|
|
4851
5320
|
return true;
|
|
4852
5321
|
};
|
|
4853
5322
|
let runRowReconcile = async () =>
|
|
@@ -4855,6 +5324,7 @@ modules = {
|
|
|
4855
5324
|
try {
|
|
4856
5325
|
return await runRowReconcile();
|
|
4857
5326
|
} catch (error) {
|
|
5327
|
+
this.handleRowSaveError(error, obj.row);
|
|
4858
5328
|
keepSaveLocked = true;
|
|
4859
5329
|
let retryPromise = null;
|
|
4860
5330
|
this.treeSingleSaveReconcileTask = () => {
|
|
@@ -4884,6 +5354,7 @@ modules = {
|
|
|
4884
5354
|
return false;
|
|
4885
5355
|
}
|
|
4886
5356
|
} catch (error) {
|
|
5357
|
+
this.handleRowSaveError(error, obj.row);
|
|
4887
5358
|
if (error?.treeReloadFailed) {
|
|
4888
5359
|
keepSaveLocked = true;
|
|
4889
5360
|
installReloadRetry();
|
|
@@ -4904,6 +5375,18 @@ modules = {
|
|
|
4904
5375
|
}
|
|
4905
5376
|
}
|
|
4906
5377
|
},
|
|
5378
|
+
/** @param {Error} error 保存异常。@param {Object} rowData 当前行。执行保存失败脚本。 */
|
|
5379
|
+
handleRowSaveError(error, rowData) {
|
|
5380
|
+
try {
|
|
5381
|
+
this.handleCustomEvent(
|
|
5382
|
+
this.widget.options.onRowSaveError,
|
|
5383
|
+
["error", "rowData"],
|
|
5384
|
+
[error, rowData]
|
|
5385
|
+
);
|
|
5386
|
+
} catch (hookError) {
|
|
5387
|
+
// 自定义失败脚本自身报错时保留原保存异常,由统一错误提示负责展示。
|
|
5388
|
+
}
|
|
5389
|
+
},
|
|
4907
5390
|
/** @param {*} dataId 行数据 id。@param {Function} callback 查询成功回调。加载保存后的完整行。 */
|
|
4908
5391
|
getRowData(dataId, callback, fail, error) {
|
|
4909
5392
|
let reportTemplate = this.getFormRef()?.reportTemplate;
|
|
@@ -5235,6 +5718,9 @@ modules = {
|
|
|
5235
5718
|
* @param {Object} obj VXE 行参数。
|
|
5236
5719
|
*/
|
|
5237
5720
|
removeTreeRow(obj) {
|
|
5721
|
+
if (!this.canDeleteTableRow(obj)) {
|
|
5722
|
+
return false;
|
|
5723
|
+
}
|
|
5238
5724
|
let row = obj.row;
|
|
5239
5725
|
let tableRows = this.getValue() || [];
|
|
5240
5726
|
let delKeys = this.collectDescendantKeys(row, tableRows);
|
|
@@ -5248,6 +5734,9 @@ modules = {
|
|
|
5248
5734
|
* @param {Object} obj VXE 行参数。
|
|
5249
5735
|
*/
|
|
5250
5736
|
removeChildTreeRows(obj) {
|
|
5737
|
+
if (!this.canDeleteTableRow(obj)) {
|
|
5738
|
+
return false;
|
|
5739
|
+
}
|
|
5251
5740
|
let row = obj.row;
|
|
5252
5741
|
let tableRows = this.getValue() || [];
|
|
5253
5742
|
let delKeys = this.collectDescendantKeys(row, tableRows);
|
|
@@ -5281,8 +5770,17 @@ modules = {
|
|
|
5281
5770
|
},
|
|
5282
5771
|
/** @param {Object} obj VXE 单元格参数。@returns {Object} 行新增/编辑按钮配置。 */
|
|
5283
5772
|
getEditTreeButtonGroupConfig(obj) {
|
|
5284
|
-
let columnConfig = obj?.column?.params?.columnConfig || {};
|
|
5285
5773
|
let tableOptions = this.widget.options || {};
|
|
5774
|
+
let columnConfig = obj?.column?.params?.columnConfig || {};
|
|
5775
|
+
if (columnConfig.formatS !== "editTreeButtonGroup") {
|
|
5776
|
+
let actionColumn = null;
|
|
5777
|
+
this.loodHandleColumns(tableOptions.tableColumns || [], (column) => {
|
|
5778
|
+
if (!actionColumn && column?.formatS === "editTreeButtonGroup") {
|
|
5779
|
+
actionColumn = column;
|
|
5780
|
+
}
|
|
5781
|
+
});
|
|
5782
|
+
columnConfig = actionColumn || columnConfig;
|
|
5783
|
+
}
|
|
5286
5784
|
return {
|
|
5287
5785
|
rowAddAuthName: columnConfig.rowAddAuthName,
|
|
5288
5786
|
rowEditAuthName: columnConfig.rowEditAuthName,
|
|
@@ -5314,11 +5812,30 @@ modules = {
|
|
|
5314
5812
|
let result = this.handleCustomEvent(script, ["tableParam"], [obj]);
|
|
5315
5813
|
return result !== false;
|
|
5316
5814
|
},
|
|
5815
|
+
/** @param {String|Function} script 行级条件脚本。@param {Object} obj VXE 行参数。@returns {Boolean} */
|
|
5816
|
+
isTableRowConditionAllowed(script, obj) {
|
|
5817
|
+
if (!script) {
|
|
5818
|
+
return true;
|
|
5819
|
+
}
|
|
5820
|
+
try {
|
|
5821
|
+
return this.handleCustomEvent(
|
|
5822
|
+
script,
|
|
5823
|
+
["tableParam"],
|
|
5824
|
+
[obj]
|
|
5825
|
+
) !== false;
|
|
5826
|
+
} catch (error) {
|
|
5827
|
+
return false;
|
|
5828
|
+
}
|
|
5829
|
+
},
|
|
5317
5830
|
/** @param {Object} obj VXE 行参数。@returns {Boolean} 是否显示行新增按钮。 */
|
|
5318
5831
|
canShowRowAdd(obj) {
|
|
5319
5832
|
return (
|
|
5320
|
-
this.hasTableRowPermission(this.getRowAddAuthName(obj))
|
|
5321
|
-
this.isRowButtonShow(this.getRowAddShow(obj), obj)
|
|
5833
|
+
this.hasTableRowPermission(this.getRowAddAuthName(obj))
|
|
5834
|
+
&& this.isRowButtonShow(this.getRowAddShow(obj), obj)
|
|
5835
|
+
&& this.isTableRowConditionAllowed(
|
|
5836
|
+
this.widget.options.rowAddableScript,
|
|
5837
|
+
obj
|
|
5838
|
+
)
|
|
5322
5839
|
);
|
|
5323
5840
|
},
|
|
5324
5841
|
/** @param {Object} obj VXE 行参数。@returns {Boolean} 是否显示行编辑按钮。 */
|
|
@@ -5326,10 +5843,50 @@ modules = {
|
|
|
5326
5843
|
let isAddRow = !this.hasSaveRow(obj?.row);
|
|
5327
5844
|
if (isAddRow) return true;
|
|
5328
5845
|
return (
|
|
5329
|
-
this.hasTableRowPermission(this.getRowEditAuthName(obj))
|
|
5330
|
-
this.isRowButtonShow(this.getRowEditShow(obj), obj)
|
|
5846
|
+
this.hasTableRowPermission(this.getRowEditAuthName(obj))
|
|
5847
|
+
&& this.isRowButtonShow(this.getRowEditShow(obj), obj)
|
|
5848
|
+
&& this.isTableRowConditionAllowed(
|
|
5849
|
+
this.widget.options.rowEditableScript,
|
|
5850
|
+
obj
|
|
5851
|
+
)
|
|
5331
5852
|
);
|
|
5332
5853
|
},
|
|
5854
|
+
/** @param {Object} obj VXE 行参数。@returns {Boolean} 当前行是否允许删除。 */
|
|
5855
|
+
canDeleteTableRow(obj) {
|
|
5856
|
+
return this.isTableRowConditionAllowed(
|
|
5857
|
+
this.widget.options.rowDeletableScript,
|
|
5858
|
+
obj
|
|
5859
|
+
);
|
|
5860
|
+
},
|
|
5861
|
+
/**
|
|
5862
|
+
* @param {Object} obj VXE 单元格参数。
|
|
5863
|
+
* @param {Boolean} useEditSnapshot true 时按进入编辑时的原始状态判断。
|
|
5864
|
+
* @returns {Boolean} 当前行、当前字段是否允许修改。
|
|
5865
|
+
*/
|
|
5866
|
+
isTableCellEditable(obj, useEditSnapshot = false) {
|
|
5867
|
+
const rowParams = useEditSnapshot && obj?.$table?.editCloneRow
|
|
5868
|
+
? { ...obj, row: obj.$table.editCloneRow }
|
|
5869
|
+
: obj;
|
|
5870
|
+
if (!this.canShowRowEdit(rowParams)) {
|
|
5871
|
+
return false;
|
|
5872
|
+
}
|
|
5873
|
+
const columnConfig = obj?.column?.params?.columnConfig || {};
|
|
5874
|
+
const script = columnConfig.cellEditable;
|
|
5875
|
+
if (!script) {
|
|
5876
|
+
return true;
|
|
5877
|
+
}
|
|
5878
|
+
try {
|
|
5879
|
+
const result = this.handleCustomEvent(
|
|
5880
|
+
script,
|
|
5881
|
+
["tableParam", "columnConfig"],
|
|
5882
|
+
[rowParams, columnConfig]
|
|
5883
|
+
);
|
|
5884
|
+
return result !== false;
|
|
5885
|
+
} catch (error) {
|
|
5886
|
+
// 条件脚本异常时按不可编辑处理,避免渲染阶段放开字段修改。
|
|
5887
|
+
return false;
|
|
5888
|
+
}
|
|
5889
|
+
},
|
|
5333
5890
|
/** @param {Object} obj VXE 行参数。保存编辑前快照并激活该行。 */
|
|
5334
5891
|
editRowEvent(obj) {
|
|
5335
5892
|
if (!this.canShowRowEdit(obj)) {
|
|
@@ -5578,6 +6135,9 @@ modules = {
|
|
|
5578
6135
|
* @param {Object} obj VXE 行参数。
|
|
5579
6136
|
*/
|
|
5580
6137
|
async removeEditRow(obj) {
|
|
6138
|
+
if (!this.canDeleteTableRow(obj)) {
|
|
6139
|
+
return false;
|
|
6140
|
+
}
|
|
5581
6141
|
let row = obj.row;
|
|
5582
6142
|
let $grid = this.getGridTable();
|
|
5583
6143
|
await $grid.remove(row);
|