umy-ui-table 1.2.4 → 1.2.6
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/lib/button.js +1 -1
- package/lib/icon.js +1 -1
- package/lib/index.js +1 -1
- package/lib/locale/format.js +1 -1
- package/lib/locale/index.js +1 -72
- package/lib/mixins/locale.js +1 -1
- package/lib/theme-chalk/button.css +1 -1
- package/lib/theme-chalk/icon.css +1 -1
- package/lib/theme-chalk/iconfont.1785242763644.ttf +0 -0
- package/lib/theme-chalk/iconfont.1785242763644.woff +0 -0
- package/lib/theme-chalk/iconfont.1785242763644.woff2 +0 -0
- package/lib/theme-chalk/index.css +1 -1
- package/lib/theme-chalk/u-table.css +1 -1
- package/lib/theme-chalk/ux-grid.css +1 -1
- package/lib/u-table-column.js +1 -1
- package/lib/u-table.js +1 -1
- package/lib/umy-ui.common.js +1 -1
- package/lib/utils/util.js +1 -1
- package/lib/ux-grid.js +1 -1
- package/lib/ux-table-column.js +1 -1
- package/package.json +4 -3
- package/packages/.DS_Store +0 -0
- package/packages/input/.DS_Store +0 -0
- package/packages/pagination/.DS_Store +0 -0
- package/packages/scrollbar/.DS_Store +0 -0
- package/packages/select/.DS_Store +0 -0
- package/packages/table/.DS_Store +0 -0
- package/packages/tag/.DS_Store +0 -0
- package/packages/tools/.DS_Store +0 -0
- package/packages/tools/locale/index.js +2 -48
- package/packages/tools/utils/.DS_Store +0 -0
- package/packages/tooltip/.DS_Store +0 -0
- package/packages/u-table/.DS_Store +0 -0
- package/packages/ux-grid/.DS_Store +0 -0
- package/packages/ux-grid/mixins/index.js +133 -25
- package/packages/ux-grid/src/dialog-draft.js +75 -0
- package/packages/ux-grid/src/element-renderer.js +809 -0
- package/packages/ux-grid/src/grid-height.js +75 -0
- package/packages/ux-grid/src/grid-kernel.js +14 -0
- package/packages/ux-grid/src/setup.js +42 -0
- package/packages/ux-grid/src/ux-grid.vue +215 -57
- package/packages/ux-grid/test/browser-acceptance.cjs +192 -0
- package/packages/ux-grid/test/browser-baseline-loader.cjs +10 -0
- package/packages/ux-grid/test/browser-entry.js +242 -0
- package/packages/ux-grid/test/browser-layout-contracts.cjs +105 -0
- package/packages/ux-grid/test/browser-layout-entry.js +66 -0
- package/packages/ux-grid/test/browser-renderer-contracts.cjs +262 -0
- package/packages/ux-grid/test/browser-renderer-entry.js +129 -0
- package/packages/ux-grid/test/browser-resize-contracts.cjs +150 -0
- package/packages/ux-grid/test/compatibility.cjs +176 -0
- package/packages/ux-grid/test/contracts.cjs +281 -0
- package/packages/ux-grid/test/delivery-umd.cjs +48 -0
- package/packages/ux-grid/test/delivery.cjs +103 -0
- package/packages/ux-grid/test/integration.cjs +132 -0
- package/packages/ux-grid/test/real-kernel-contracts.cjs +335 -0
- package/packages/ux-grid/test/real-kernel-events.cjs +233 -0
- package/packages/ux-grid/test/renderer-async.cjs +140 -0
- package/packages/ux-grid/test/renderer-boundaries.cjs +196 -0
- package/packages/ux-grid/test/ui-components.cjs +103 -0
- package/tools/locale/format.js +1 -1
- package/tools/locale/index.js +1 -7
- package/tools/mixins/locale.js +1 -1
- package/tools/utils/util.js +1 -1
package/lib/ux-table-column.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
module.exports=function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=
|
|
1
|
+
module.exports=function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="/dist/",n(n.s=39)}({35:function(e,t){e.exports=require("vxe-table/lib/column")},39:function(e,t,n){"use strict";n.r(t);var r=n(35),o=n.n(r),u=Object.assign({},o.a,{name:"UxTableColumn"});u.install=function(e){e.component(u.name,u)},t.default=u}});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "umy-ui-table",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.6",
|
|
4
4
|
"description": "一个基于 vue 的 PC 端表格UI库,解决万级数据渲染卡顿问题,过万数据点击全选卡顿,等等问题",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "foriacus"
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"lint": "eslint --fix --ext .js,.vue examples",
|
|
10
10
|
"clean": "rimraf lib && rimraf packages/*/lib",
|
|
11
11
|
"lib:file": "node build/build-entry.js",
|
|
12
|
-
"lib:utils": "cross-env BABEL_ENV=utils babel tools --out-dir lib",
|
|
12
|
+
"lib:utils": "cross-env BABEL_ENV=utils babel tools --out-dir lib && webpack --config build/webpack.locale.js",
|
|
13
13
|
"lib:umd": "node build/build-locale.js",
|
|
14
14
|
"lib:theme": "gulp build",
|
|
15
15
|
"lib": "npm run clean && npm run lib:file && webpack --config build/webpack.conf.js && webpack --config build/webpack.common.js && webpack --config build/webpack.component.js && npm run lib:utils && npm run lib:umd && npm run lib:theme"
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"url": "git+https://github.com/popo-fishes/umy-ui.git"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
+
"babel-helper-vue-jsx-merge-props": "^2.0.0",
|
|
37
38
|
"async-validator": "~1.8.1",
|
|
38
39
|
"deepmerge": "^1.2.0",
|
|
39
40
|
"normalize-wheel": "^1.0.1",
|
|
@@ -41,6 +42,7 @@
|
|
|
41
42
|
"throttle-debounce": "^1.0.1",
|
|
42
43
|
"vuedraggable": "^2.23.2",
|
|
43
44
|
"vxe-table": "^3.22.9",
|
|
45
|
+
"vxe-pc-ui": "3.16.23",
|
|
44
46
|
"@vxe-ui/core": "^3.4.19",
|
|
45
47
|
"xe-utils": ">= 3"
|
|
46
48
|
},
|
|
@@ -54,7 +56,6 @@
|
|
|
54
56
|
"animejs": "^3.1.0",
|
|
55
57
|
"babel-cli": "^6.26.0",
|
|
56
58
|
"babel-core": "^6.26.3",
|
|
57
|
-
"babel-helper-vue-jsx-merge-props": "^2.0.0",
|
|
58
59
|
"babel-loader": "^7.1.5",
|
|
59
60
|
"babel-plugin-add-module-exports": "^0.2.1",
|
|
60
61
|
"babel-plugin-istanbul": "^4.1.1",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,48 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import deepmerge from 'deepmerge';
|
|
4
|
-
import Format from './format';
|
|
5
|
-
|
|
6
|
-
const format = Format(Vue);
|
|
7
|
-
let lang = defaultLang;
|
|
8
|
-
let merged = false;
|
|
9
|
-
let i18nHandler = function() {
|
|
10
|
-
const vuei18n = Object.getPrototypeOf(this || Vue).$t;
|
|
11
|
-
if (typeof vuei18n === 'function' && !!Vue.locale) {
|
|
12
|
-
if (!merged) {
|
|
13
|
-
merged = true;
|
|
14
|
-
Vue.locale(
|
|
15
|
-
Vue.config.lang,
|
|
16
|
-
deepmerge(lang, Vue.locale(Vue.config.lang) || {}, { clone: true })
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
return vuei18n.apply(this, arguments);
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export const t = function(path, options) {
|
|
24
|
-
let value = i18nHandler.apply(this, arguments);
|
|
25
|
-
if (value !== null && value !== undefined) return value;
|
|
26
|
-
const array = path.split('.');
|
|
27
|
-
let current = lang;
|
|
28
|
-
for (let i = 0, j = array.length; i < j; i++) {
|
|
29
|
-
const property = array[i];
|
|
30
|
-
value = current[property];
|
|
31
|
-
if (i === j - 1) {
|
|
32
|
-
return format(value, options)
|
|
33
|
-
}
|
|
34
|
-
if (!value) return '';
|
|
35
|
-
current = value;
|
|
36
|
-
}
|
|
37
|
-
return '';
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
export const use = function(l) {
|
|
41
|
-
lang = l || lang;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
export const i18n = function(fn) {
|
|
45
|
-
i18nHandler = fn || i18nHandler;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
export default { use, t, i18n };
|
|
1
|
+
// Table, pagination and the public locale entry share one language store.
|
|
2
|
+
export { default, use, t, i18n } from "../../../tools/locale";
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
import { isArrayFn } from "../../utils/common";
|
|
2
|
+
import { createDialogDraft, mergeDialogDraft } from "../src/dialog-draft";
|
|
3
|
+
// Vue 2 instance listeners ($on/$once) are not included in $listeners.
|
|
4
|
+
function hasGridListener(vm, name) {
|
|
5
|
+
const events = vm._events && vm._events[name];
|
|
6
|
+
return !!((vm.$listeners && vm.$listeners[name]) || (events && events.length));
|
|
7
|
+
}
|
|
8
|
+
function bridgeStoppedClick(vm, params, header) {
|
|
9
|
+
if (vm._isDestroyed || vm._isBeingDestroyed) return;
|
|
10
|
+
const event = params && params.$event;
|
|
11
|
+
if (!event || event.type !== "click" || !event.target || !event.target.closest) return;
|
|
12
|
+
// Only VXE's built-in controls stop propagation. Row/cell-triggered actions
|
|
13
|
+
// must reach the native cell/header handler so current-change stays ordered.
|
|
14
|
+
if (!event.target.closest(".vxe-cell--checkbox,.vxe-cell--radio,.vxe-table--expand-btn,.vxe-cell--tree-btn,.vxe-sort--asc-btn,.vxe-sort--desc-btn")) return;
|
|
15
|
+
if (!hasGridListener(vm, header ? "header-click" : "cell-click") &&
|
|
16
|
+
(header || !hasGridListener(vm, "row-click"))) return;
|
|
17
|
+
const cell = event.target.closest(header ? "th" : "td");
|
|
18
|
+
const table = vm.$refs.singleTable;
|
|
19
|
+
const columnNode = cell && table && table.getColumnNode ? table.getColumnNode(cell) : null;
|
|
20
|
+
const column = params.column || (columnNode && columnNode.item);
|
|
21
|
+
if (!cell || !column) return;
|
|
22
|
+
const payload = Object.assign({}, params, { column, cell });
|
|
23
|
+
if (header) vm.headerClick(payload);
|
|
24
|
+
else vm.cellClick(payload);
|
|
25
|
+
}
|
|
26
|
+
function repeatedClick(vm, key, event) {
|
|
27
|
+
if (!event) return false;
|
|
28
|
+
const seen = vm[key] || (vm[key] = new WeakSet());
|
|
29
|
+
if (seen.has(event)) return true;
|
|
30
|
+
seen.add(event);
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
2
33
|
export default {
|
|
34
|
+
beforeDestroy() {
|
|
35
|
+
this.stopDialogSync();
|
|
36
|
+
clearTimeout(this._times);
|
|
37
|
+
this.clearNode();
|
|
38
|
+
},
|
|
3
39
|
props: {
|
|
4
40
|
beautifyTable: { default: false, type: Boolean }, // 美化表格,修改了样式
|
|
5
41
|
showDialogIcon: { default: true, type: Boolean }, // 是否显示操作字段的上下移动按钮(侧滑框)
|
|
@@ -95,9 +131,10 @@ export default {
|
|
|
95
131
|
},
|
|
96
132
|
// 打开自定义字段框
|
|
97
133
|
plDialogOpens() {
|
|
98
|
-
this.
|
|
99
|
-
|
|
100
|
-
this.newDialogData =
|
|
134
|
+
if (this._dialogUnwatch) return;
|
|
135
|
+
this._dialogDraft = createDialogDraft(this.dialogData);
|
|
136
|
+
this.newDialogData = this._dialogDraft.draft.slice();
|
|
137
|
+
this._dialogUnwatch = this.$watch("dialogData", () => this.syncDialogDraft(), { deep: true });
|
|
101
138
|
this.$refs.plDialog.style.width = 300 + "px";
|
|
102
139
|
this._times = setTimeout(() => {
|
|
103
140
|
this.plDialogFals = true;
|
|
@@ -113,31 +150,43 @@ export default {
|
|
|
113
150
|
},
|
|
114
151
|
// 关闭自定义字段框(取消选择)
|
|
115
152
|
closeModal() {
|
|
153
|
+
this.stopDialogSync();
|
|
116
154
|
this.plDialogFals = false;
|
|
117
155
|
clearTimeout(this._times);
|
|
118
156
|
this.$refs.plDialog.style.width = 0 + "px";
|
|
119
|
-
this.aBox.style.display = "none";
|
|
120
157
|
this.clearNode();
|
|
121
158
|
this.newDialogData = JSON.parse(JSON.stringify(this.dialogData));
|
|
122
159
|
},
|
|
123
160
|
// 确认按钮
|
|
124
161
|
confirmField() {
|
|
162
|
+
this.syncDialogDraft();
|
|
163
|
+
this.stopDialogSync();
|
|
125
164
|
this.$emit("show-field", this.newDialogData);
|
|
126
165
|
this.plDialogFals = false;
|
|
127
166
|
clearTimeout(this._times);
|
|
128
167
|
this.$refs.plDialog.style.width = 0 + "px";
|
|
129
|
-
this.aBox.style.display = "none";
|
|
130
168
|
this.clearNode();
|
|
131
169
|
},
|
|
132
170
|
// 重置按钮
|
|
133
171
|
reset() {
|
|
172
|
+
this.syncDialogDraft();
|
|
173
|
+
this.stopDialogSync();
|
|
134
174
|
this.$emit("reset", this.newDialogData);
|
|
135
175
|
this.plDialogFals = false;
|
|
136
176
|
clearTimeout(this._times);
|
|
137
177
|
this.$refs.plDialog.style.width = 0 + "px";
|
|
138
|
-
this.aBox.style.display = "none";
|
|
139
178
|
this.clearNode();
|
|
140
179
|
},
|
|
180
|
+
syncDialogDraft() {
|
|
181
|
+
if (!this._dialogDraft) return;
|
|
182
|
+
this._dialogDraft = mergeDialogDraft(this._dialogDraft, this.dialogData, this.newDialogData);
|
|
183
|
+
this.newDialogData = this._dialogDraft.value;
|
|
184
|
+
},
|
|
185
|
+
stopDialogSync() {
|
|
186
|
+
if (this._dialogUnwatch) this._dialogUnwatch();
|
|
187
|
+
this._dialogUnwatch = null;
|
|
188
|
+
this._dialogDraft = null;
|
|
189
|
+
},
|
|
141
190
|
// 修改字段名按钮事件
|
|
142
191
|
amendField(item, index) {
|
|
143
192
|
this.$emit("amend-field", item, index);
|
|
@@ -147,10 +196,6 @@ export default {
|
|
|
147
196
|
// 删除节点
|
|
148
197
|
let parent = this.aBox ? this.aBox.parentNode : "";
|
|
149
198
|
parent && parent.removeChild(this.aBox);
|
|
150
|
-
let doms = document.getElementsByClassName("modal-backdrop");
|
|
151
|
-
if (doms.length > 0) {
|
|
152
|
-
document.body.removeChild(doms[0]);
|
|
153
|
-
}
|
|
154
199
|
this.aBox = null;
|
|
155
200
|
},
|
|
156
201
|
|
|
@@ -202,7 +247,7 @@ export default {
|
|
|
202
247
|
}
|
|
203
248
|
});
|
|
204
249
|
// 当选择项发生变化时会触发该事件(仅在有监听者时取值,避免无监听时全表扫描)
|
|
205
|
-
if (this
|
|
250
|
+
if (hasGridListener(this, "selection-change")) {
|
|
206
251
|
const data = this.$refs.singleTable.getCheckboxRecords();
|
|
207
252
|
this.$emit("selection-change", data);
|
|
208
253
|
}
|
|
@@ -213,7 +258,7 @@ export default {
|
|
|
213
258
|
if (this.$refs.singleTable) {
|
|
214
259
|
this.$refs.singleTable.setAllCheckboxRow(checked);
|
|
215
260
|
// 当选择项发生变化时会触发该事件(仅在有监听者时取值)
|
|
216
|
-
if (this
|
|
261
|
+
if (hasGridListener(this, "selection-change")) {
|
|
217
262
|
const data = this.$refs.singleTable.getCheckboxRecords();
|
|
218
263
|
this.$emit("selection-change", data);
|
|
219
264
|
}
|
|
@@ -226,7 +271,7 @@ export default {
|
|
|
226
271
|
if (this.$refs.singleTable) {
|
|
227
272
|
this.$refs.singleTable.clearCheckboxRow();
|
|
228
273
|
// 当选择项发生变化时会触发该事件(仅在有监听者时取值)
|
|
229
|
-
if (this
|
|
274
|
+
if (hasGridListener(this, "selection-change")) {
|
|
230
275
|
const data = this.$refs.singleTable.getCheckboxRecords();
|
|
231
276
|
this.$emit("selection-change", data);
|
|
232
277
|
}
|
|
@@ -252,7 +297,8 @@ export default {
|
|
|
252
297
|
},
|
|
253
298
|
// 对 Table 进行重新布局。当 Table 或其祖先元素由隐藏切换为显示时,可能需要调用此方法
|
|
254
299
|
doLayout() {
|
|
255
|
-
this
|
|
300
|
+
const revision = this._selectedRevision || 0;
|
|
301
|
+
this.refreshSelectedAfter(this.$refs.singleTable.recalculate(), revision);
|
|
256
302
|
},
|
|
257
303
|
// 让表格滚动条回到顶部,和左侧
|
|
258
304
|
pagingScrollTopLeft(top = 0, left = 0) {
|
|
@@ -277,7 +323,8 @@ export default {
|
|
|
277
323
|
return this.$refs.singleTable.loadColumn(data);
|
|
278
324
|
},
|
|
279
325
|
refreshColumn() {
|
|
280
|
-
this
|
|
326
|
+
const revision = this._selectedRevision || 0;
|
|
327
|
+
this.refreshSelectedAfter(this.$refs.singleTable.refreshColumn(), revision);
|
|
281
328
|
},
|
|
282
329
|
// 激活编辑状态
|
|
283
330
|
setActiveRow(row) {
|
|
@@ -453,31 +500,34 @@ export default {
|
|
|
453
500
|
selectAll(params) {
|
|
454
501
|
// vxe 事件参数里的 records 是惰性 getter,仅在有监听者时才取值,避免每次全选都全表扫描
|
|
455
502
|
if (
|
|
456
|
-
this
|
|
457
|
-
this
|
|
503
|
+
hasGridListener(this, "select-all") ||
|
|
504
|
+
hasGridListener(this, "selection-change")
|
|
458
505
|
) {
|
|
459
506
|
const data =
|
|
460
507
|
params && typeof params.records === "function"
|
|
461
508
|
? params.records()
|
|
462
|
-
:
|
|
509
|
+
: params && Array.isArray(params.records)
|
|
510
|
+
? params.records : this.$refs.singleTable.getCheckboxRecords();
|
|
463
511
|
this.$emit("select-all", data);
|
|
464
512
|
// 当选择项发生变化时会触发该事件
|
|
465
513
|
this.$emit("selection-change", data);
|
|
466
514
|
}
|
|
515
|
+
bridgeStoppedClick(this, params, true);
|
|
467
516
|
},
|
|
468
517
|
// 当用户手动勾选数据行的 Checkbox 时触发的事件
|
|
469
518
|
plSelect(params) {
|
|
470
519
|
const { row, records } = params || {};
|
|
471
520
|
// vxe 事件参数里的 records 是惰性 getter,仅在有监听者时才取值,避免每次勾选都全表扫描
|
|
472
|
-
if (this
|
|
521
|
+
if (hasGridListener(this, "select") || hasGridListener(this, "selection-change")) {
|
|
473
522
|
const data =
|
|
474
523
|
typeof records === "function"
|
|
475
524
|
? records()
|
|
476
|
-
: this.$refs.singleTable.getCheckboxRecords();
|
|
525
|
+
: Array.isArray(records) ? records : this.$refs.singleTable.getCheckboxRecords();
|
|
477
526
|
this.$emit("select", data, row);
|
|
478
527
|
// 当选择项发生变化时会触发该事件
|
|
479
528
|
this.$emit("selection-change", data);
|
|
480
529
|
}
|
|
530
|
+
bridgeStoppedClick(this, params, false);
|
|
481
531
|
},
|
|
482
532
|
// 只对 type=radio 有效,当手动勾选并且值发生改变时触发的事件
|
|
483
533
|
radioChange({
|
|
@@ -488,13 +538,16 @@ export default {
|
|
|
488
538
|
columnIndex,
|
|
489
539
|
$columnIndex,
|
|
490
540
|
cell,
|
|
541
|
+
$event,
|
|
491
542
|
}) {
|
|
492
543
|
this.$emit("radio-change", row, column);
|
|
544
|
+
bridgeStoppedClick(this, { row, column, cell, $event }, false);
|
|
493
545
|
},
|
|
494
546
|
// 当表格的排序条件发生变化的时候会触发该事件
|
|
495
|
-
sortChange({ column, property, order }) {
|
|
496
|
-
let objs = { column, prop: property, order };
|
|
547
|
+
sortChange({ column, property, field, order, $event }) {
|
|
548
|
+
let objs = { column, prop: property === undefined ? field : property, order };
|
|
497
549
|
this.$emit("sort-change", objs);
|
|
550
|
+
bridgeStoppedClick(this, { column, $event }, true);
|
|
498
551
|
},
|
|
499
552
|
// 当表格的当前行发生变化的时候会触发该事件
|
|
500
553
|
currentChange({ row }) {
|
|
@@ -521,15 +574,32 @@ export default {
|
|
|
521
574
|
$columnIndex,
|
|
522
575
|
$event,
|
|
523
576
|
});
|
|
577
|
+
bridgeStoppedClick(this, { row, column, $event }, false);
|
|
524
578
|
},
|
|
525
579
|
// 当表格的筛选条件发生变化的时候会触发该事件
|
|
526
|
-
filterChange({ column, property, values, datas, filters, $event }) {
|
|
580
|
+
filterChange({ column, property, field, values, datas, filters, $event }) {
|
|
581
|
+
const supplied = typeof filters === "function" ? filters() : filters;
|
|
582
|
+
const table = this.$refs.singleTable;
|
|
583
|
+
const columns = table && table.getTableColumn ? table.getTableColumn().visibleColumn : null;
|
|
584
|
+
// The legacy wrapper reports every visible filterable column, including
|
|
585
|
+
// those with no selection. Keep the new kernel's checked-only API intact.
|
|
586
|
+
const compatibleFilters = columns ? columns.filter(item => item.filters && item.filters.length).map(item => {
|
|
587
|
+
const checked = item.filters.filter(option => option.checked);
|
|
588
|
+
const existing = (supplied || []).find(entry => entry.column === item);
|
|
589
|
+
return Object.assign({}, existing, {
|
|
590
|
+
column: item,
|
|
591
|
+
field: item.field || item.property,
|
|
592
|
+
property: item.property || item.field,
|
|
593
|
+
values: checked.map(option => option.value),
|
|
594
|
+
datas: checked.map(option => option.data),
|
|
595
|
+
});
|
|
596
|
+
}) : supplied;
|
|
527
597
|
this.$emit("filter-change", {
|
|
528
598
|
column,
|
|
529
|
-
property,
|
|
599
|
+
property: property === undefined ? field : property,
|
|
530
600
|
values,
|
|
531
601
|
datas,
|
|
532
|
-
filters,
|
|
602
|
+
filters: compatibleFilters,
|
|
533
603
|
$event,
|
|
534
604
|
});
|
|
535
605
|
},
|
|
@@ -544,6 +614,10 @@ export default {
|
|
|
544
614
|
cell,
|
|
545
615
|
$event,
|
|
546
616
|
}) {
|
|
617
|
+
// VXE dispatches this from mouseover, which also bubbles when moving
|
|
618
|
+
// between descendants. The legacy wrapper exposes mouseenter semantics.
|
|
619
|
+
const relatedTarget = $event && $event.relatedTarget;
|
|
620
|
+
if (cell && relatedTarget && relatedTarget.nodeType && cell.contains(relatedTarget)) return;
|
|
547
621
|
this.$emit("cell-mouse-enter", row, column, cell, $event);
|
|
548
622
|
},
|
|
549
623
|
// 当单元格 hover 退出时会触发该事件
|
|
@@ -570,6 +644,7 @@ export default {
|
|
|
570
644
|
cell,
|
|
571
645
|
$event,
|
|
572
646
|
}) {
|
|
647
|
+
if (repeatedClick(this, "_cellClickEvents", $event)) return;
|
|
573
648
|
this.$emit("cell-click", row, column, cell, $event);
|
|
574
649
|
// row-click 当某一行被点击时会触发该事件 row, event, column
|
|
575
650
|
// 只有当点击的单元格不是复选框才触发行事件!
|
|
@@ -606,6 +681,7 @@ export default {
|
|
|
606
681
|
columnIndex,
|
|
607
682
|
$event,
|
|
608
683
|
}) {
|
|
684
|
+
if (repeatedClick(this, "_headerClickEvents", $event)) return;
|
|
609
685
|
this.$emit("header-click", column, $event);
|
|
610
686
|
},
|
|
611
687
|
// 当某一列的表头被鼠标右键点击时触发该事件 column, $event
|
|
@@ -686,9 +762,39 @@ export default {
|
|
|
686
762
|
$columnIndex,
|
|
687
763
|
});
|
|
688
764
|
},
|
|
765
|
+
// elx-grid 扩展事件:鼠标或键盘切换当前选中单元格时触发
|
|
766
|
+
editCurrentlyActive({ row, column, cell }) {
|
|
767
|
+
this._selectedRevision = (this._selectedRevision || 0) + 1;
|
|
768
|
+
const table = this.$refs.singleTable;
|
|
769
|
+
const targetCell =
|
|
770
|
+
cell ||
|
|
771
|
+
(table && table.getCellElement
|
|
772
|
+
? table.getCellElement(row, column)
|
|
773
|
+
: null);
|
|
774
|
+
this.$emit("edit-currently-active", {
|
|
775
|
+
row,
|
|
776
|
+
column,
|
|
777
|
+
cell: targetCell,
|
|
778
|
+
});
|
|
779
|
+
},
|
|
780
|
+
// Only public wrapper refreshes participate; no global VXE hooks or
|
|
781
|
+
// private editStore access. Preserve the legacy undefined method return.
|
|
782
|
+
refreshSelectedAfter(completion, revision = this._selectedRevision || 0) {
|
|
783
|
+
Promise.resolve(completion).then(() => this.$nextTick()).then(() => {
|
|
784
|
+
if (this._isDestroyed || this._isBeingDestroyed ||
|
|
785
|
+
revision !== (this._selectedRevision || 0) ||
|
|
786
|
+
!hasGridListener(this, "edit-currently-active")) return;
|
|
787
|
+
const table = this.$refs.singleTable;
|
|
788
|
+
const selected = table && table.getSelectedCell ? table.getSelectedCell() : null;
|
|
789
|
+
if (!selected) return;
|
|
790
|
+
const cell = table.getCellElement(selected.row, selected.column);
|
|
791
|
+
if (cell) this.editCurrentlyActive(Object.assign({}, selected, { cell }));
|
|
792
|
+
}).catch(error => console.error("[UxGrid] Selected cell refresh failed", error));
|
|
793
|
+
},
|
|
689
794
|
// 当树节点展开或收起时会触发该事件
|
|
690
795
|
toggleTreeExpandEv(row) {
|
|
691
796
|
this.$emit("toggle-tree-expand", row);
|
|
797
|
+
bridgeStoppedClick(this, row, false);
|
|
692
798
|
},
|
|
693
799
|
// 键盘按下事件
|
|
694
800
|
keydown({ $event }) {
|
|
@@ -700,7 +806,9 @@ export default {
|
|
|
700
806
|
},
|
|
701
807
|
// vxe 后续重新加载/刷新数据并渲染完成后触发
|
|
702
808
|
dataRendered(params) {
|
|
809
|
+
const revision = this._selectedRevision || 0;
|
|
703
810
|
this.$emit("data-rendered", params);
|
|
811
|
+
this.refreshSelectedAfter(undefined, revision);
|
|
704
812
|
},
|
|
705
813
|
},
|
|
706
814
|
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import XEUtils from "xe-utils";
|
|
2
|
+
|
|
3
|
+
// Keep the source snapshot separate from the editable draft. Only an open
|
|
4
|
+
// dialog owns this state; closed grids do not traverse dialogData.
|
|
5
|
+
export function createDialogDraft(source) {
|
|
6
|
+
return { source: source.slice(), baseline: XEUtils.clone(source, true), draft: XEUtils.clone(source, true) };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function mergeDialogDraft(previous, source, draft) {
|
|
10
|
+
const keyOf = item => {
|
|
11
|
+
for (const field of ["id", "field", "prop", "key"]) {
|
|
12
|
+
if (item[field] !== undefined && item[field] !== null) return field + ":" + item[field];
|
|
13
|
+
}
|
|
14
|
+
return null;
|
|
15
|
+
};
|
|
16
|
+
const matchIndices = (items, originals) => {
|
|
17
|
+
const indices = items.map(() => -1);
|
|
18
|
+
const used = new Set();
|
|
19
|
+
const assign = (index, oldIndex) => {
|
|
20
|
+
if (oldIndex >= 0 && !used.has(oldIndex)) {
|
|
21
|
+
indices[index] = oldIndex;
|
|
22
|
+
used.add(oldIndex);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
// Reserve every surviving reference before considering positional fallback:
|
|
26
|
+
// a new item inserted at index 0 must not take the old index of a later A.
|
|
27
|
+
items.forEach((item, index) => {
|
|
28
|
+
assign(index, originals.findIndex((entry, oldIndex) => entry === item && !used.has(oldIndex)));
|
|
29
|
+
});
|
|
30
|
+
items.forEach((item, index) => {
|
|
31
|
+
const key = keyOf(item);
|
|
32
|
+
if (indices[index] < 0 && key !== null) {
|
|
33
|
+
assign(index, previous.baseline.findIndex((entry, oldIndex) => keyOf(entry) === key && !used.has(oldIndex)));
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
items.forEach((item, index) => {
|
|
37
|
+
if (indices[index] < 0 && keyOf(item) === null &&
|
|
38
|
+
index < previous.baseline.length && keyOf(previous.baseline[index]) === null) {
|
|
39
|
+
assign(index, index);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
return indices;
|
|
43
|
+
};
|
|
44
|
+
const draftIndices = matchIndices(draft, previous.draft);
|
|
45
|
+
const sourceIndices = matchIndices(source, previous.source);
|
|
46
|
+
const incoming = source.map((item, index) => {
|
|
47
|
+
const oldIndex = sourceIndices[index];
|
|
48
|
+
const draftIndex = draftIndices.indexOf(oldIndex);
|
|
49
|
+
const value = XEUtils.clone(item, true);
|
|
50
|
+
if (oldIndex >= 0 && draftIndex >= 0) {
|
|
51
|
+
const base = previous.baseline[oldIndex];
|
|
52
|
+
const edited = draft[draftIndex];
|
|
53
|
+
// A local field edit wins a simultaneous parent change to that field.
|
|
54
|
+
new Set(Object.keys(base).concat(Object.keys(edited))).forEach(field => {
|
|
55
|
+
if (!XEUtils.isEqual(base[field], edited[field])) {
|
|
56
|
+
if (Object.prototype.hasOwnProperty.call(edited, field)) value[field] = XEUtils.clone(edited[field], true);
|
|
57
|
+
else delete value[field];
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return { oldIndex, value };
|
|
62
|
+
});
|
|
63
|
+
const reordered = draftIndices.some((index, position) => index !== position);
|
|
64
|
+
let nextDraft = incoming.map(entry => entry.value);
|
|
65
|
+
if (reordered) {
|
|
66
|
+
const ordered = draftIndices.filter(index => index >= 0)
|
|
67
|
+
.map(index => incoming.find(entry => entry.oldIndex === index)).filter(Boolean);
|
|
68
|
+
const retained = new Set(ordered);
|
|
69
|
+
nextDraft = ordered.concat(incoming.filter(entry => !retained.has(entry))).map(entry => entry.value);
|
|
70
|
+
}
|
|
71
|
+
// Store draft references in source order so subsequent drag operations can
|
|
72
|
+
// still be matched even when the item does not declare a stable key.
|
|
73
|
+
return { source: source.slice(), baseline: XEUtils.clone(source, true),
|
|
74
|
+
draft: incoming.map(entry => entry.value), value: nextDraft };
|
|
75
|
+
}
|