cloud-web-corejs 1.1.0-dev.21 → 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/excelExport/conditionExportConfig.js +112 -0
- package/src/components/excelExport/exportType.js +8 -0
- package/src/components/excelExport/index.vue +7 -1
- package/src/components/excelExport/mixins.js +410 -259
- 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/form-widget/field-widget/select-export-item-button-widget.vue +2 -1
- package/src/components/xform/form-designer/form-widget/field-widget/table-export-button-widget.vue +2 -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/setting-panel/property-editor/field-table-export-button/empty-number-input.vue +51 -0
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/select-export-item-button-editor.vue +27 -2
- package/src/components/xform/form-designer/setting-panel/property-editor/field-table-export-button/table-export-button-editor.vue +33 -3
- package/src/components/xform/form-designer/widget-panel/widgetsConfig.js +54 -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 +587 -25
- 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:{
|
|
@@ -2798,7 +3249,9 @@ modules = {
|
|
|
2798
3249
|
if (
|
|
2799
3250
|
customParam?.exportParam?.type !== EXPORT_TYPE.ITEM_SELECTED
|
|
2800
3251
|
) {
|
|
2801
|
-
formData =
|
|
3252
|
+
formData = customParam?.exportParam?.exportQuerySnapshot !== undefined
|
|
3253
|
+
? this.$baseLodash.cloneDeep(customParam.exportParam.exportQuerySnapshot)
|
|
3254
|
+
: tableOption.param ? tableOption.param() || {} : {};
|
|
2802
3255
|
}
|
|
2803
3256
|
const queryParams = Object.assign({}, formData);
|
|
2804
3257
|
|
|
@@ -2818,7 +3271,7 @@ modules = {
|
|
|
2818
3271
|
});
|
|
2819
3272
|
}
|
|
2820
3273
|
|
|
2821
|
-
if (page.pageSize !== undefined) {
|
|
3274
|
+
if (page && page.pageSize !== undefined) {
|
|
2822
3275
|
queryParams["size"] = page.pageSize;
|
|
2823
3276
|
queryParams["current"] = page.currentPage;
|
|
2824
3277
|
}
|
|
@@ -3678,8 +4131,10 @@ modules = {
|
|
|
3678
4131
|
async deleteRow(row, rowIndex) {
|
|
3679
4132
|
let isTreeTable = this.widget.options.isTreeTable;
|
|
3680
4133
|
if (isTreeTable) {
|
|
3681
|
-
this.removeTreeRow({ row });
|
|
3682
|
-
|
|
4134
|
+
return this.removeTreeRow({ row, rowIndex });
|
|
4135
|
+
}
|
|
4136
|
+
if (!this.canDeleteTableRow({ row, rowIndex })) {
|
|
4137
|
+
return false;
|
|
3683
4138
|
}
|
|
3684
4139
|
delete this.fieldSchemaMap[row._X_ROW_KEY];
|
|
3685
4140
|
let $grid = this.getGridTable();
|
|
@@ -4480,15 +4935,18 @@ modules = {
|
|
|
4480
4935
|
/**
|
|
4481
4936
|
* 保存当前编辑行。持久化行原位合并;新身份以回查结果重建树关系。
|
|
4482
4937
|
* @param {Object} obj VXE 插槽参数,必须包含 row 和 $table。
|
|
4938
|
+
* @param {Object} options 保存选项;skipConfirm 用于粘贴后的自动保存。
|
|
4483
4939
|
*/
|
|
4484
|
-
async saveEditRow(obj) {
|
|
4940
|
+
async saveEditRow(obj, options = {}) {
|
|
4485
4941
|
let formRef = this.getFormRef();
|
|
4486
4942
|
let formConfig = this.formConfig;
|
|
4487
4943
|
let entity = formConfig.entity;
|
|
4488
4944
|
if (!entity) return;
|
|
4489
4945
|
let reportTemplate = formRef?.reportTemplate;
|
|
4490
4946
|
let formCode = reportTemplate?.formCode;
|
|
4491
|
-
let scriptCode =
|
|
4947
|
+
let scriptCode = this.widget.options.rowSaveScriptCode
|
|
4948
|
+
|| formConfig.saveScriptCode
|
|
4949
|
+
|| "saveUpdate";
|
|
4492
4950
|
|
|
4493
4951
|
let $grid = obj.$table.$xegrid;
|
|
4494
4952
|
if (typeof this.treeSingleSaveReconcileTask === "function") {
|
|
@@ -4541,6 +4999,12 @@ modules = {
|
|
|
4541
4999
|
const rowValid = controlled ? await this.validateEditRowAsync(obj.row) : this.validateEditRow(obj.row);
|
|
4542
5000
|
if (!rowValid) return false;
|
|
4543
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;
|
|
4544
5008
|
|
|
4545
5009
|
let requestRow = obj.row;
|
|
4546
5010
|
if (treeContext) {
|
|
@@ -4610,10 +5074,12 @@ modules = {
|
|
|
4610
5074
|
);
|
|
4611
5075
|
}
|
|
4612
5076
|
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4616
|
-
|
|
5077
|
+
if (!options.skipConfirm) {
|
|
5078
|
+
try {
|
|
5079
|
+
await this.$baseConfirm("您确定要保存吗?");
|
|
5080
|
+
} catch (error) {
|
|
5081
|
+
return false;
|
|
5082
|
+
}
|
|
4617
5083
|
}
|
|
4618
5084
|
|
|
4619
5085
|
await $grid.clearActived();
|
|
@@ -4636,8 +5102,8 @@ modules = {
|
|
|
4636
5102
|
let urlValueProps = this.getUrlValueAttachmentProps();
|
|
4637
5103
|
Object.keys(mainData).forEach((key) => {
|
|
4638
5104
|
if (
|
|
4639
|
-
key.startsWith("attachments_")
|
|
4640
|
-
urlValueProps.indexOf(key) === -1
|
|
5105
|
+
key.startsWith("attachments_")
|
|
5106
|
+
&& urlValueProps.indexOf(key) === -1
|
|
4641
5107
|
) {
|
|
4642
5108
|
formData[key] = mainData[key];
|
|
4643
5109
|
}
|
|
@@ -4846,6 +5312,11 @@ modules = {
|
|
|
4846
5312
|
await $grid.updateData();
|
|
4847
5313
|
}
|
|
4848
5314
|
delete obj.$table.editCloneRow;
|
|
5315
|
+
this.handleCustomEvent(
|
|
5316
|
+
this.widget.options.afterRowSave,
|
|
5317
|
+
["rowData", "res"],
|
|
5318
|
+
[obj.row, rowResponse]
|
|
5319
|
+
);
|
|
4849
5320
|
return true;
|
|
4850
5321
|
};
|
|
4851
5322
|
let runRowReconcile = async () =>
|
|
@@ -4853,6 +5324,7 @@ modules = {
|
|
|
4853
5324
|
try {
|
|
4854
5325
|
return await runRowReconcile();
|
|
4855
5326
|
} catch (error) {
|
|
5327
|
+
this.handleRowSaveError(error, obj.row);
|
|
4856
5328
|
keepSaveLocked = true;
|
|
4857
5329
|
let retryPromise = null;
|
|
4858
5330
|
this.treeSingleSaveReconcileTask = () => {
|
|
@@ -4882,6 +5354,7 @@ modules = {
|
|
|
4882
5354
|
return false;
|
|
4883
5355
|
}
|
|
4884
5356
|
} catch (error) {
|
|
5357
|
+
this.handleRowSaveError(error, obj.row);
|
|
4885
5358
|
if (error?.treeReloadFailed) {
|
|
4886
5359
|
keepSaveLocked = true;
|
|
4887
5360
|
installReloadRetry();
|
|
@@ -4902,6 +5375,18 @@ modules = {
|
|
|
4902
5375
|
}
|
|
4903
5376
|
}
|
|
4904
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
|
+
},
|
|
4905
5390
|
/** @param {*} dataId 行数据 id。@param {Function} callback 查询成功回调。加载保存后的完整行。 */
|
|
4906
5391
|
getRowData(dataId, callback, fail, error) {
|
|
4907
5392
|
let reportTemplate = this.getFormRef()?.reportTemplate;
|
|
@@ -5233,6 +5718,9 @@ modules = {
|
|
|
5233
5718
|
* @param {Object} obj VXE 行参数。
|
|
5234
5719
|
*/
|
|
5235
5720
|
removeTreeRow(obj) {
|
|
5721
|
+
if (!this.canDeleteTableRow(obj)) {
|
|
5722
|
+
return false;
|
|
5723
|
+
}
|
|
5236
5724
|
let row = obj.row;
|
|
5237
5725
|
let tableRows = this.getValue() || [];
|
|
5238
5726
|
let delKeys = this.collectDescendantKeys(row, tableRows);
|
|
@@ -5246,6 +5734,9 @@ modules = {
|
|
|
5246
5734
|
* @param {Object} obj VXE 行参数。
|
|
5247
5735
|
*/
|
|
5248
5736
|
removeChildTreeRows(obj) {
|
|
5737
|
+
if (!this.canDeleteTableRow(obj)) {
|
|
5738
|
+
return false;
|
|
5739
|
+
}
|
|
5249
5740
|
let row = obj.row;
|
|
5250
5741
|
let tableRows = this.getValue() || [];
|
|
5251
5742
|
let delKeys = this.collectDescendantKeys(row, tableRows);
|
|
@@ -5279,8 +5770,17 @@ modules = {
|
|
|
5279
5770
|
},
|
|
5280
5771
|
/** @param {Object} obj VXE 单元格参数。@returns {Object} 行新增/编辑按钮配置。 */
|
|
5281
5772
|
getEditTreeButtonGroupConfig(obj) {
|
|
5282
|
-
let columnConfig = obj?.column?.params?.columnConfig || {};
|
|
5283
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
|
+
}
|
|
5284
5784
|
return {
|
|
5285
5785
|
rowAddAuthName: columnConfig.rowAddAuthName,
|
|
5286
5786
|
rowEditAuthName: columnConfig.rowEditAuthName,
|
|
@@ -5312,11 +5812,30 @@ modules = {
|
|
|
5312
5812
|
let result = this.handleCustomEvent(script, ["tableParam"], [obj]);
|
|
5313
5813
|
return result !== false;
|
|
5314
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
|
+
},
|
|
5315
5830
|
/** @param {Object} obj VXE 行参数。@returns {Boolean} 是否显示行新增按钮。 */
|
|
5316
5831
|
canShowRowAdd(obj) {
|
|
5317
5832
|
return (
|
|
5318
|
-
this.hasTableRowPermission(this.getRowAddAuthName(obj))
|
|
5319
|
-
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
|
+
)
|
|
5320
5839
|
);
|
|
5321
5840
|
},
|
|
5322
5841
|
/** @param {Object} obj VXE 行参数。@returns {Boolean} 是否显示行编辑按钮。 */
|
|
@@ -5324,10 +5843,50 @@ modules = {
|
|
|
5324
5843
|
let isAddRow = !this.hasSaveRow(obj?.row);
|
|
5325
5844
|
if (isAddRow) return true;
|
|
5326
5845
|
return (
|
|
5327
|
-
this.hasTableRowPermission(this.getRowEditAuthName(obj))
|
|
5328
|
-
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
|
+
)
|
|
5329
5852
|
);
|
|
5330
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
|
+
},
|
|
5331
5890
|
/** @param {Object} obj VXE 行参数。保存编辑前快照并激活该行。 */
|
|
5332
5891
|
editRowEvent(obj) {
|
|
5333
5892
|
if (!this.canShowRowEdit(obj)) {
|
|
@@ -5576,6 +6135,9 @@ modules = {
|
|
|
5576
6135
|
* @param {Object} obj VXE 行参数。
|
|
5577
6136
|
*/
|
|
5578
6137
|
async removeEditRow(obj) {
|
|
6138
|
+
if (!this.canDeleteTableRow(obj)) {
|
|
6139
|
+
return false;
|
|
6140
|
+
}
|
|
5579
6141
|
let row = obj.row;
|
|
5580
6142
|
let $grid = this.getGridTable();
|
|
5581
6143
|
await $grid.remove(row);
|