@lx-frontend/wrap-element-ui 1.0.1-beta.3 → 1.0.1-beta.5
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/README.md +45 -45
- package/package.json +14 -14
- package/src/components/AddMembers/index.vue +157 -157
- package/src/components/AuditSteps/index.vue +140 -140
- package/src/components/DemoComponent/index.vue +20 -20
- package/src/components/EditableTable/README.md +147 -147
- package/src/components/EditableTable/index.less +724 -724
- package/src/components/EditableTable/index.vue +914 -914
- package/src/components/EditableTable/types.ts +116 -116
- package/src/components/EditableTable/useCellHover.ts +71 -71
- package/src/components/EditableTable/useColumnHeaderOperation.ts +325 -325
- package/src/components/EditableTable/useDefaultOperation.ts +95 -95
- package/src/components/EditableTable/useDragSort.ts +290 -290
- package/src/components/EditableTable/usePagination.ts +30 -30
- package/src/components/EditableTable/useRowBgColor.ts +50 -50
- package/src/components/EditableTable/useViewSetting.ts +119 -119
- package/src/components/Ellipsis/MultilineEllipsis.vue +141 -141
- package/src/components/Ellipsis/index.vue +119 -119
- package/src/components/LxTable/index.vue +296 -296
- package/src/components/PopoverForm/index.vue +66 -66
- package/src/components/SearchForm/index.vue +243 -243
- package/src/components/SearchSelect/index.vue +153 -153
- package/src/components/index.ts +24 -24
- package/src/components/singleMessage/index.ts +44 -44
|
@@ -1,291 +1,291 @@
|
|
|
1
|
-
import { onBeforeUnmount, onMounted, ref, Ref } from 'vue';
|
|
2
|
-
import { IColumnConfig, IDraggingData, IEmits, IProps } from "./types"
|
|
3
|
-
import throttle from "lodash/throttle"
|
|
4
|
-
|
|
5
|
-
interface IUseDragSortParams {
|
|
6
|
-
props: IProps
|
|
7
|
-
emit: IEmits
|
|
8
|
-
viewSettingDragSortOptions: Ref<IColumnConfig[]>
|
|
9
|
-
beforeDragStart: () => boolean
|
|
10
|
-
currScope: Ref<any>
|
|
11
|
-
pageSize: Ref<number>
|
|
12
|
-
tableDomRef: Ref<any>
|
|
13
|
-
}
|
|
14
|
-
export default function useDragSort({ props, emit, viewSettingDragSortOptions, pageSize, beforeDragStart, currScope, tableDomRef }: IUseDragSortParams) {
|
|
15
|
-
|
|
16
|
-
const draggingData = ref<IDraggingData>({}); // 拖拽相关数据
|
|
17
|
-
const isMouseDown = ref(false);
|
|
18
|
-
const dragType = ref<'row' | 'view-setting'>('row');
|
|
19
|
-
// 如果页面存在多个table实例,如果没有这个值来区分正在操作哪个表格,拖拽功能会有异常
|
|
20
|
-
const isOperating = ref(false);
|
|
21
|
-
|
|
22
|
-
onMounted(() => {
|
|
23
|
-
tableDomRef.value.$el.addEventListener('mousedown', () => { isOperating.value = true });
|
|
24
|
-
document.addEventListener('mousedown', handleDocumentMouseDown);
|
|
25
|
-
document.addEventListener('mousemove', handleDocumentMouseMove);
|
|
26
|
-
document.addEventListener('mouseup', handleDocumentMouseUp);
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
onBeforeUnmount(() => {
|
|
30
|
-
tableDomRef.value.$el.removeEventListener('mousedown', () => isOperating.value = true);
|
|
31
|
-
document.removeEventListener('mousedown', handleDocumentMouseDown);
|
|
32
|
-
document.removeEventListener('mousemove', handleDocumentMouseMove);
|
|
33
|
-
document.removeEventListener('mouseup', handleDocumentMouseUp);
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
const handleDocumentMouseDown = (e) => {
|
|
37
|
-
isMouseDown.value = true;
|
|
38
|
-
const target = e.target as HTMLElement
|
|
39
|
-
|
|
40
|
-
if (typeof target.dataset?.index === 'undefined') return
|
|
41
|
-
|
|
42
|
-
if ([...target.classList].includes('row-drag-target')) {
|
|
43
|
-
dragType.value = 'row';
|
|
44
|
-
if (!isOperating.value) return
|
|
45
|
-
// 处理列表行拖拽
|
|
46
|
-
handleDragMouseDown(e, +target.dataset.index);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if ([...target.classList].includes('view-setting-drag-target')) {
|
|
50
|
-
dragType.value = 'view-setting';
|
|
51
|
-
// 处理显示设置拖拽
|
|
52
|
-
handleViewSettingDragMouseDown(e, +target.dataset.index);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const handleDocumentMouseMove = (e) => {
|
|
57
|
-
if (!isMouseDown.value || typeof draggingData.value.draggingIndex === 'undefined') {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
throttledMoveHandler(e);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const handleDocumentMouseUp = (e) => {
|
|
65
|
-
isOperating.value = false;
|
|
66
|
-
isMouseDown.value = false;
|
|
67
|
-
if (typeof draggingData.value.draggingIndex === 'undefined') {
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
if (dragType.value === 'row') {
|
|
71
|
-
handleDragDrop(e, currScope.value);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (dragType.value === 'view-setting') {
|
|
75
|
-
handleViewSettingDragDrop();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const handleDragMouseDown = (event, draggingIndex) => {
|
|
80
|
-
if (!beforeDragStart()) return
|
|
81
|
-
const rows = [...document.getElementsByClassName(`custom-row-classname`)] as HTMLElement[];
|
|
82
|
-
const rowDoms: Record<number, HTMLElement[]> = [];
|
|
83
|
-
for (let i = 0; i < rows.length; i++) {
|
|
84
|
-
const row = rows[i];
|
|
85
|
-
const clsIndex = ([...row.classList].find(cls => cls.startsWith(`custom-row-classname-`)) ?? '').split('-').pop() ?? 'NaN';
|
|
86
|
-
if (typeof +clsIndex === 'number') {
|
|
87
|
-
rowDoms[+clsIndex] = rowDoms[+clsIndex] || [];
|
|
88
|
-
rowDoms[+clsIndex].push(row);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
draggingData.value.isDragging = true;
|
|
93
|
-
draggingData.value.rowDoms = rowDoms;
|
|
94
|
-
draggingData.value.draggingIndex = +draggingIndex;
|
|
95
|
-
draggingData.value.rowsRange = [];
|
|
96
|
-
|
|
97
|
-
draggingData.value.startPosition = {
|
|
98
|
-
x: event.clientX,
|
|
99
|
-
y: event.clientY
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
// 列表过大时拖拽有性能问题,所以拖拽范围限制在拖拽元素的上下15个元素内
|
|
103
|
-
const dragSemiRange = props.dragSemiRange ?? 15;
|
|
104
|
-
for (const i of Object.keys(rowDoms).map(Number)) {
|
|
105
|
-
if (i < draggingIndex - dragSemiRange || i > draggingIndex + dragSemiRange) {
|
|
106
|
-
draggingData.value.rowsRange[i] = undefined
|
|
107
|
-
continue
|
|
108
|
-
}
|
|
109
|
-
const rowdom = rowDoms[i];
|
|
110
|
-
// 在Chrom中,relative加z-index可以让拖拽更流畅,然而在Safari中无效
|
|
111
|
-
// 如果在Safari中relative有效,其实蒙层都没有必要了
|
|
112
|
-
rowdom.forEach(el => el.style.setProperty('position', 'relative'));
|
|
113
|
-
|
|
114
|
-
if (i !== draggingData.value.draggingIndex) {
|
|
115
|
-
rowdom.forEach(el => el.style.setProperty('transition', 'transform 0.25s ease'));
|
|
116
|
-
} else {
|
|
117
|
-
rowdom.forEach(el => el.style.setProperty('z-index', '100'));
|
|
118
|
-
// 当有固定列时,一行的内容并不是一个tr,而是两个或多个tr的叠加显示,其中有的列内容被隐藏
|
|
119
|
-
// 所以拖拽时,需要同时拖拽所有的tr,并显示所有内容,否则拖拽效果会显示异常
|
|
120
|
-
const tds = rowdom
|
|
121
|
-
.map(dom => dom.querySelectorAll('td'))
|
|
122
|
-
.reduce((pre, curr) => ([...pre, ...curr]), [] as HTMLElement[])
|
|
123
|
-
.filter(td => td.classList.contains('is-hidden'));
|
|
124
|
-
draggingData.value.hiddenTds = tds;
|
|
125
|
-
tds.forEach(td => td.classList.remove('is-hidden'));
|
|
126
|
-
|
|
127
|
-
// 生成一个蒙层,防止拖动时文字被选中
|
|
128
|
-
const fullScreenDiv = document.createElement('div');
|
|
129
|
-
fullScreenDiv.style.position = 'fixed';
|
|
130
|
-
fullScreenDiv.style.top = '0';
|
|
131
|
-
fullScreenDiv.style.left = '0';
|
|
132
|
-
fullScreenDiv.style.right = '0';
|
|
133
|
-
fullScreenDiv.style.bottom = '0';
|
|
134
|
-
fullScreenDiv.style.zIndex = '999';
|
|
135
|
-
fullScreenDiv.style.cursor = 'grabbing';
|
|
136
|
-
document.body.appendChild(fullScreenDiv);
|
|
137
|
-
draggingData.value.fullScreenDiv = fullScreenDiv;
|
|
138
|
-
}
|
|
139
|
-
// 计算每一行的高度范围
|
|
140
|
-
const rect = rowdom[0].getBoundingClientRect()
|
|
141
|
-
draggingData.value.rowsRange = draggingData.value.rowsRange || [];
|
|
142
|
-
draggingData.value.rowsRange[i] = ([
|
|
143
|
-
rect.top,
|
|
144
|
-
rect.bottom
|
|
145
|
-
]);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const calcPositionRowShouldBePlace = (rowsRange: ([number, number])[], draggingClientY: number) => {
|
|
150
|
-
if (!draggingData.value.rowsRange ||
|
|
151
|
-
typeof draggingData.value.draggingIndex === 'undefined' ||
|
|
152
|
-
typeof props.dragSemiRange === 'undefined'
|
|
153
|
-
) return;
|
|
154
|
-
const rangeLeft = draggingData.value.draggingIndex - props.dragSemiRange <= 0 ? 0 : draggingData.value.draggingIndex - props.dragSemiRange
|
|
155
|
-
const rangeRight = draggingData.value.draggingIndex + props.dragSemiRange >= draggingData.value.rowsRange.length ? draggingData.value.rowsRange.length - 1 : draggingData.value.draggingIndex + props.dragSemiRange
|
|
156
|
-
if (!rowsRange) return -1;
|
|
157
|
-
if (draggingClientY <= rowsRange[rangeLeft][0]) return rangeLeft;
|
|
158
|
-
if (draggingClientY >= rowsRange[rangeRight][1]) return rangeRight;
|
|
159
|
-
for (let i = rangeLeft; i <= rangeRight; i++) {
|
|
160
|
-
const [top, bottom] = rowsRange[i];
|
|
161
|
-
if (draggingClientY > top && draggingClientY < bottom) {
|
|
162
|
-
return i;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return -1;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const clearMovingData = () => {
|
|
169
|
-
const rowdoms = draggingData.value.rowDoms || [];
|
|
170
|
-
const draggingIndex = draggingData.value.draggingIndex ?? -1
|
|
171
|
-
const dragSemiRange = props.dragSemiRange ?? 15;
|
|
172
|
-
for (const i of Object.keys(rowdoms).map(Number)) {
|
|
173
|
-
if (i < draggingIndex - dragSemiRange || i > draggingIndex + dragSemiRange) continue
|
|
174
|
-
const doms = rowdoms[i];
|
|
175
|
-
doms.forEach(el => {
|
|
176
|
-
el.style.removeProperty('position');
|
|
177
|
-
el.style.removeProperty('transition');
|
|
178
|
-
el.style.removeProperty('transform');
|
|
179
|
-
el.style.removeProperty('z-index');
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
draggingData.value.fullScreenDiv?.parentNode?.removeChild(draggingData.value.fullScreenDiv);
|
|
183
|
-
draggingData.value.hiddenTds?.forEach(el => el.classList.add('is-hidden'));
|
|
184
|
-
draggingData.value = {};
|
|
185
|
-
currScope.value = null
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
const handleDragDrop = (event, scope) => {
|
|
189
|
-
if (!scope) return
|
|
190
|
-
const { draggingIndex = 0, dropIndex = draggingIndex } = draggingData.value;
|
|
191
|
-
const dataList = scope.store.states.data;
|
|
192
|
-
const movedRow = dataList[draggingIndex];
|
|
193
|
-
const newList = [
|
|
194
|
-
...dataList.slice(0, +draggingIndex),
|
|
195
|
-
...dataList.slice(draggingIndex + 1)
|
|
196
|
-
];
|
|
197
|
-
newList.splice(dropIndex, 0, movedRow);
|
|
198
|
-
scope.store.states.data = newList;
|
|
199
|
-
emit('row-drag-drop', {
|
|
200
|
-
row: movedRow,
|
|
201
|
-
fromIndex: draggingIndex,
|
|
202
|
-
toIndex: dropIndex,
|
|
203
|
-
page: props.currentPage,
|
|
204
|
-
size: pageSize.value
|
|
205
|
-
});
|
|
206
|
-
// 清理工作
|
|
207
|
-
clearMovingData();
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
const handleViewSettingDragMouseDown = (event, index) => {
|
|
211
|
-
const rowDoms = [...document.getElementsByClassName('view-setting-draggable-item')]
|
|
212
|
-
.reduce((pre, item, index) => ({ ...pre, [index]: [item] }), {});
|
|
213
|
-
draggingData.value.isDragging = true;
|
|
214
|
-
draggingData.value.rowDoms = rowDoms;
|
|
215
|
-
draggingData.value.draggingIndex = +index;
|
|
216
|
-
draggingData.value.startPosition = {
|
|
217
|
-
x: event.clientX,
|
|
218
|
-
y: event.clientY
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
for (const i of Object.keys(rowDoms).map(Number)) {
|
|
222
|
-
const rowdoms = rowDoms[i];
|
|
223
|
-
rowdoms.forEach((el) => {
|
|
224
|
-
el.style.setProperty('position', 'relative');
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
if (i !== draggingData.value.draggingIndex) {
|
|
228
|
-
rowdoms.forEach(el => el.style.setProperty('transition', 'transform 0.25s ease'));
|
|
229
|
-
}
|
|
230
|
-
const rect = rowdoms[0].getBoundingClientRect();
|
|
231
|
-
draggingData.value.rowsRange = draggingData.value.rowsRange || [];
|
|
232
|
-
draggingData.value.rowsRange.push([
|
|
233
|
-
rect.top,
|
|
234
|
-
rect.bottom
|
|
235
|
-
]);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const handleMove = (event) => {
|
|
240
|
-
if (!draggingData.value.isDragging) return;
|
|
241
|
-
const { y = 0 } = draggingData.value.startPosition || {};
|
|
242
|
-
const { draggingIndex = -1, rowDoms = {} } = draggingData.value;
|
|
243
|
-
const draggingRow = rowDoms?.[draggingIndex ?? 0];
|
|
244
|
-
for (let i = 0; i < draggingRow.length; i++) {
|
|
245
|
-
const dom = draggingRow[i];
|
|
246
|
-
dom?.style.setProperty('transform', `translateY(${event.clientY - y}px)`);
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// 判断应该落在第几行
|
|
250
|
-
const idx = calcPositionRowShouldBePlace(draggingData.value.rowsRange as [number, number][], event.clientY);
|
|
251
|
-
if (typeof idx !== 'number') return;
|
|
252
|
-
const [top, bottom] = draggingData.value.rowsRange![draggingIndex] as [number, number];
|
|
253
|
-
draggingData.value.dropIndex = idx;
|
|
254
|
-
const rowHeight = bottom - top;
|
|
255
|
-
const dragSemiRange = props.dragSemiRange ?? 15;
|
|
256
|
-
for (const i of Object.keys(rowDoms).map(Number)) {
|
|
257
|
-
if (i < draggingIndex - dragSemiRange || i > draggingIndex + dragSemiRange || draggingIndex === i) continue
|
|
258
|
-
const doms = rowDoms[i];
|
|
259
|
-
if (idx < draggingIndex) {
|
|
260
|
-
if (i >= idx && i < draggingIndex) {
|
|
261
|
-
doms.forEach(el => el.style.setProperty('transform', `translateY(${rowHeight}px)`));
|
|
262
|
-
} else {
|
|
263
|
-
doms.forEach(el => el.style.removeProperty('transform'));
|
|
264
|
-
}
|
|
265
|
-
} else if (idx > draggingIndex) {
|
|
266
|
-
if (i <= idx && i > draggingIndex) {
|
|
267
|
-
doms.forEach(el => el.style.setProperty('transform', `translateY(${-rowHeight}px)`));
|
|
268
|
-
} else {
|
|
269
|
-
doms.forEach(el => el.style.removeProperty('transform'));
|
|
270
|
-
}
|
|
271
|
-
} else {
|
|
272
|
-
doms.forEach(el => el.style.removeProperty('transform'));
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
|
|
277
|
-
const handleViewSettingDragDrop = () => {
|
|
278
|
-
const { draggingIndex = 0, dropIndex = draggingIndex } = draggingData.value;
|
|
279
|
-
const movedRow = viewSettingDragSortOptions.value[draggingIndex];
|
|
280
|
-
const newList = [
|
|
281
|
-
...viewSettingDragSortOptions.value.slice(0, draggingIndex),
|
|
282
|
-
...viewSettingDragSortOptions.value.slice(draggingIndex + 1)
|
|
283
|
-
];
|
|
284
|
-
newList.splice(dropIndex, 0, movedRow);
|
|
285
|
-
viewSettingDragSortOptions.value = newList;
|
|
286
|
-
// 清理工作
|
|
287
|
-
clearMovingData();
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
const throttledMoveHandler = throttle(handleMove, 10);
|
|
1
|
+
import { onBeforeUnmount, onMounted, ref, Ref } from 'vue';
|
|
2
|
+
import { IColumnConfig, IDraggingData, IEmits, IProps } from "./types"
|
|
3
|
+
import throttle from "lodash/throttle"
|
|
4
|
+
|
|
5
|
+
interface IUseDragSortParams {
|
|
6
|
+
props: IProps
|
|
7
|
+
emit: IEmits
|
|
8
|
+
viewSettingDragSortOptions: Ref<IColumnConfig[]>
|
|
9
|
+
beforeDragStart: () => boolean
|
|
10
|
+
currScope: Ref<any>
|
|
11
|
+
pageSize: Ref<number>
|
|
12
|
+
tableDomRef: Ref<any>
|
|
13
|
+
}
|
|
14
|
+
export default function useDragSort({ props, emit, viewSettingDragSortOptions, pageSize, beforeDragStart, currScope, tableDomRef }: IUseDragSortParams) {
|
|
15
|
+
|
|
16
|
+
const draggingData = ref<IDraggingData>({}); // 拖拽相关数据
|
|
17
|
+
const isMouseDown = ref(false);
|
|
18
|
+
const dragType = ref<'row' | 'view-setting'>('row');
|
|
19
|
+
// 如果页面存在多个table实例,如果没有这个值来区分正在操作哪个表格,拖拽功能会有异常
|
|
20
|
+
const isOperating = ref(false);
|
|
21
|
+
|
|
22
|
+
onMounted(() => {
|
|
23
|
+
tableDomRef.value.$el.addEventListener('mousedown', () => { isOperating.value = true });
|
|
24
|
+
document.addEventListener('mousedown', handleDocumentMouseDown);
|
|
25
|
+
document.addEventListener('mousemove', handleDocumentMouseMove);
|
|
26
|
+
document.addEventListener('mouseup', handleDocumentMouseUp);
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
onBeforeUnmount(() => {
|
|
30
|
+
tableDomRef.value.$el.removeEventListener('mousedown', () => isOperating.value = true);
|
|
31
|
+
document.removeEventListener('mousedown', handleDocumentMouseDown);
|
|
32
|
+
document.removeEventListener('mousemove', handleDocumentMouseMove);
|
|
33
|
+
document.removeEventListener('mouseup', handleDocumentMouseUp);
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const handleDocumentMouseDown = (e) => {
|
|
37
|
+
isMouseDown.value = true;
|
|
38
|
+
const target = e.target as HTMLElement
|
|
39
|
+
|
|
40
|
+
if (typeof target.dataset?.index === 'undefined') return
|
|
41
|
+
|
|
42
|
+
if ([...target.classList].includes('row-drag-target')) {
|
|
43
|
+
dragType.value = 'row';
|
|
44
|
+
if (!isOperating.value) return
|
|
45
|
+
// 处理列表行拖拽
|
|
46
|
+
handleDragMouseDown(e, +target.dataset.index);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if ([...target.classList].includes('view-setting-drag-target')) {
|
|
50
|
+
dragType.value = 'view-setting';
|
|
51
|
+
// 处理显示设置拖拽
|
|
52
|
+
handleViewSettingDragMouseDown(e, +target.dataset.index);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const handleDocumentMouseMove = (e) => {
|
|
57
|
+
if (!isMouseDown.value || typeof draggingData.value.draggingIndex === 'undefined') {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
throttledMoveHandler(e);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const handleDocumentMouseUp = (e) => {
|
|
65
|
+
isOperating.value = false;
|
|
66
|
+
isMouseDown.value = false;
|
|
67
|
+
if (typeof draggingData.value.draggingIndex === 'undefined') {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (dragType.value === 'row') {
|
|
71
|
+
handleDragDrop(e, currScope.value);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (dragType.value === 'view-setting') {
|
|
75
|
+
handleViewSettingDragDrop();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const handleDragMouseDown = (event, draggingIndex) => {
|
|
80
|
+
if (!beforeDragStart()) return
|
|
81
|
+
const rows = [...document.getElementsByClassName(`custom-row-classname`)] as HTMLElement[];
|
|
82
|
+
const rowDoms: Record<number, HTMLElement[]> = [];
|
|
83
|
+
for (let i = 0; i < rows.length; i++) {
|
|
84
|
+
const row = rows[i];
|
|
85
|
+
const clsIndex = ([...row.classList].find(cls => cls.startsWith(`custom-row-classname-`)) ?? '').split('-').pop() ?? 'NaN';
|
|
86
|
+
if (typeof +clsIndex === 'number') {
|
|
87
|
+
rowDoms[+clsIndex] = rowDoms[+clsIndex] || [];
|
|
88
|
+
rowDoms[+clsIndex].push(row);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
draggingData.value.isDragging = true;
|
|
93
|
+
draggingData.value.rowDoms = rowDoms;
|
|
94
|
+
draggingData.value.draggingIndex = +draggingIndex;
|
|
95
|
+
draggingData.value.rowsRange = [];
|
|
96
|
+
|
|
97
|
+
draggingData.value.startPosition = {
|
|
98
|
+
x: event.clientX,
|
|
99
|
+
y: event.clientY
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// 列表过大时拖拽有性能问题,所以拖拽范围限制在拖拽元素的上下15个元素内
|
|
103
|
+
const dragSemiRange = props.dragSemiRange ?? 15;
|
|
104
|
+
for (const i of Object.keys(rowDoms).map(Number)) {
|
|
105
|
+
if (i < draggingIndex - dragSemiRange || i > draggingIndex + dragSemiRange) {
|
|
106
|
+
draggingData.value.rowsRange[i] = undefined
|
|
107
|
+
continue
|
|
108
|
+
}
|
|
109
|
+
const rowdom = rowDoms[i];
|
|
110
|
+
// 在Chrom中,relative加z-index可以让拖拽更流畅,然而在Safari中无效
|
|
111
|
+
// 如果在Safari中relative有效,其实蒙层都没有必要了
|
|
112
|
+
rowdom.forEach(el => el.style.setProperty('position', 'relative'));
|
|
113
|
+
|
|
114
|
+
if (i !== draggingData.value.draggingIndex) {
|
|
115
|
+
rowdom.forEach(el => el.style.setProperty('transition', 'transform 0.25s ease'));
|
|
116
|
+
} else {
|
|
117
|
+
rowdom.forEach(el => el.style.setProperty('z-index', '100'));
|
|
118
|
+
// 当有固定列时,一行的内容并不是一个tr,而是两个或多个tr的叠加显示,其中有的列内容被隐藏
|
|
119
|
+
// 所以拖拽时,需要同时拖拽所有的tr,并显示所有内容,否则拖拽效果会显示异常
|
|
120
|
+
const tds = rowdom
|
|
121
|
+
.map(dom => dom.querySelectorAll('td'))
|
|
122
|
+
.reduce((pre, curr) => ([...pre, ...curr]), [] as HTMLElement[])
|
|
123
|
+
.filter(td => td.classList.contains('is-hidden'));
|
|
124
|
+
draggingData.value.hiddenTds = tds;
|
|
125
|
+
tds.forEach(td => td.classList.remove('is-hidden'));
|
|
126
|
+
|
|
127
|
+
// 生成一个蒙层,防止拖动时文字被选中
|
|
128
|
+
const fullScreenDiv = document.createElement('div');
|
|
129
|
+
fullScreenDiv.style.position = 'fixed';
|
|
130
|
+
fullScreenDiv.style.top = '0';
|
|
131
|
+
fullScreenDiv.style.left = '0';
|
|
132
|
+
fullScreenDiv.style.right = '0';
|
|
133
|
+
fullScreenDiv.style.bottom = '0';
|
|
134
|
+
fullScreenDiv.style.zIndex = '999';
|
|
135
|
+
fullScreenDiv.style.cursor = 'grabbing';
|
|
136
|
+
document.body.appendChild(fullScreenDiv);
|
|
137
|
+
draggingData.value.fullScreenDiv = fullScreenDiv;
|
|
138
|
+
}
|
|
139
|
+
// 计算每一行的高度范围
|
|
140
|
+
const rect = rowdom[0].getBoundingClientRect()
|
|
141
|
+
draggingData.value.rowsRange = draggingData.value.rowsRange || [];
|
|
142
|
+
draggingData.value.rowsRange[i] = ([
|
|
143
|
+
rect.top,
|
|
144
|
+
rect.bottom
|
|
145
|
+
]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const calcPositionRowShouldBePlace = (rowsRange: ([number, number])[], draggingClientY: number) => {
|
|
150
|
+
if (!draggingData.value.rowsRange ||
|
|
151
|
+
typeof draggingData.value.draggingIndex === 'undefined' ||
|
|
152
|
+
typeof props.dragSemiRange === 'undefined'
|
|
153
|
+
) return;
|
|
154
|
+
const rangeLeft = draggingData.value.draggingIndex - props.dragSemiRange <= 0 ? 0 : draggingData.value.draggingIndex - props.dragSemiRange
|
|
155
|
+
const rangeRight = draggingData.value.draggingIndex + props.dragSemiRange >= draggingData.value.rowsRange.length ? draggingData.value.rowsRange.length - 1 : draggingData.value.draggingIndex + props.dragSemiRange
|
|
156
|
+
if (!rowsRange) return -1;
|
|
157
|
+
if (draggingClientY <= rowsRange[rangeLeft][0]) return rangeLeft;
|
|
158
|
+
if (draggingClientY >= rowsRange[rangeRight][1]) return rangeRight;
|
|
159
|
+
for (let i = rangeLeft; i <= rangeRight; i++) {
|
|
160
|
+
const [top, bottom] = rowsRange[i];
|
|
161
|
+
if (draggingClientY > top && draggingClientY < bottom) {
|
|
162
|
+
return i;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return -1;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const clearMovingData = () => {
|
|
169
|
+
const rowdoms = draggingData.value.rowDoms || [];
|
|
170
|
+
const draggingIndex = draggingData.value.draggingIndex ?? -1
|
|
171
|
+
const dragSemiRange = props.dragSemiRange ?? 15;
|
|
172
|
+
for (const i of Object.keys(rowdoms).map(Number)) {
|
|
173
|
+
if (i < draggingIndex - dragSemiRange || i > draggingIndex + dragSemiRange) continue
|
|
174
|
+
const doms = rowdoms[i];
|
|
175
|
+
doms.forEach(el => {
|
|
176
|
+
el.style.removeProperty('position');
|
|
177
|
+
el.style.removeProperty('transition');
|
|
178
|
+
el.style.removeProperty('transform');
|
|
179
|
+
el.style.removeProperty('z-index');
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
draggingData.value.fullScreenDiv?.parentNode?.removeChild(draggingData.value.fullScreenDiv);
|
|
183
|
+
draggingData.value.hiddenTds?.forEach(el => el.classList.add('is-hidden'));
|
|
184
|
+
draggingData.value = {};
|
|
185
|
+
currScope.value = null
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const handleDragDrop = (event, scope) => {
|
|
189
|
+
if (!scope) return
|
|
190
|
+
const { draggingIndex = 0, dropIndex = draggingIndex } = draggingData.value;
|
|
191
|
+
const dataList = scope.store.states.data;
|
|
192
|
+
const movedRow = dataList[draggingIndex];
|
|
193
|
+
const newList = [
|
|
194
|
+
...dataList.slice(0, +draggingIndex),
|
|
195
|
+
...dataList.slice(draggingIndex + 1)
|
|
196
|
+
];
|
|
197
|
+
newList.splice(dropIndex, 0, movedRow);
|
|
198
|
+
scope.store.states.data = newList;
|
|
199
|
+
emit('row-drag-drop', {
|
|
200
|
+
row: movedRow,
|
|
201
|
+
fromIndex: draggingIndex,
|
|
202
|
+
toIndex: dropIndex,
|
|
203
|
+
page: props.currentPage,
|
|
204
|
+
size: pageSize.value
|
|
205
|
+
});
|
|
206
|
+
// 清理工作
|
|
207
|
+
clearMovingData();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const handleViewSettingDragMouseDown = (event, index) => {
|
|
211
|
+
const rowDoms = [...document.getElementsByClassName('view-setting-draggable-item')]
|
|
212
|
+
.reduce((pre, item, index) => ({ ...pre, [index]: [item] }), {});
|
|
213
|
+
draggingData.value.isDragging = true;
|
|
214
|
+
draggingData.value.rowDoms = rowDoms;
|
|
215
|
+
draggingData.value.draggingIndex = +index;
|
|
216
|
+
draggingData.value.startPosition = {
|
|
217
|
+
x: event.clientX,
|
|
218
|
+
y: event.clientY
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
for (const i of Object.keys(rowDoms).map(Number)) {
|
|
222
|
+
const rowdoms = rowDoms[i];
|
|
223
|
+
rowdoms.forEach((el) => {
|
|
224
|
+
el.style.setProperty('position', 'relative');
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
if (i !== draggingData.value.draggingIndex) {
|
|
228
|
+
rowdoms.forEach(el => el.style.setProperty('transition', 'transform 0.25s ease'));
|
|
229
|
+
}
|
|
230
|
+
const rect = rowdoms[0].getBoundingClientRect();
|
|
231
|
+
draggingData.value.rowsRange = draggingData.value.rowsRange || [];
|
|
232
|
+
draggingData.value.rowsRange.push([
|
|
233
|
+
rect.top,
|
|
234
|
+
rect.bottom
|
|
235
|
+
]);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const handleMove = (event) => {
|
|
240
|
+
if (!draggingData.value.isDragging) return;
|
|
241
|
+
const { y = 0 } = draggingData.value.startPosition || {};
|
|
242
|
+
const { draggingIndex = -1, rowDoms = {} } = draggingData.value;
|
|
243
|
+
const draggingRow = rowDoms?.[draggingIndex ?? 0];
|
|
244
|
+
for (let i = 0; i < draggingRow.length; i++) {
|
|
245
|
+
const dom = draggingRow[i];
|
|
246
|
+
dom?.style.setProperty('transform', `translateY(${event.clientY - y}px)`);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// 判断应该落在第几行
|
|
250
|
+
const idx = calcPositionRowShouldBePlace(draggingData.value.rowsRange as [number, number][], event.clientY);
|
|
251
|
+
if (typeof idx !== 'number') return;
|
|
252
|
+
const [top, bottom] = draggingData.value.rowsRange![draggingIndex] as [number, number];
|
|
253
|
+
draggingData.value.dropIndex = idx;
|
|
254
|
+
const rowHeight = bottom - top;
|
|
255
|
+
const dragSemiRange = props.dragSemiRange ?? 15;
|
|
256
|
+
for (const i of Object.keys(rowDoms).map(Number)) {
|
|
257
|
+
if (i < draggingIndex - dragSemiRange || i > draggingIndex + dragSemiRange || draggingIndex === i) continue
|
|
258
|
+
const doms = rowDoms[i];
|
|
259
|
+
if (idx < draggingIndex) {
|
|
260
|
+
if (i >= idx && i < draggingIndex) {
|
|
261
|
+
doms.forEach(el => el.style.setProperty('transform', `translateY(${rowHeight}px)`));
|
|
262
|
+
} else {
|
|
263
|
+
doms.forEach(el => el.style.removeProperty('transform'));
|
|
264
|
+
}
|
|
265
|
+
} else if (idx > draggingIndex) {
|
|
266
|
+
if (i <= idx && i > draggingIndex) {
|
|
267
|
+
doms.forEach(el => el.style.setProperty('transform', `translateY(${-rowHeight}px)`));
|
|
268
|
+
} else {
|
|
269
|
+
doms.forEach(el => el.style.removeProperty('transform'));
|
|
270
|
+
}
|
|
271
|
+
} else {
|
|
272
|
+
doms.forEach(el => el.style.removeProperty('transform'));
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const handleViewSettingDragDrop = () => {
|
|
278
|
+
const { draggingIndex = 0, dropIndex = draggingIndex } = draggingData.value;
|
|
279
|
+
const movedRow = viewSettingDragSortOptions.value[draggingIndex];
|
|
280
|
+
const newList = [
|
|
281
|
+
...viewSettingDragSortOptions.value.slice(0, draggingIndex),
|
|
282
|
+
...viewSettingDragSortOptions.value.slice(draggingIndex + 1)
|
|
283
|
+
];
|
|
284
|
+
newList.splice(dropIndex, 0, movedRow);
|
|
285
|
+
viewSettingDragSortOptions.value = newList;
|
|
286
|
+
// 清理工作
|
|
287
|
+
clearMovingData();
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
const throttledMoveHandler = throttle(handleMove, 10);
|
|
291
291
|
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import { ref } from "vue"
|
|
2
|
-
import { IEmits } from "./types"
|
|
3
|
-
|
|
4
|
-
interface IParams {
|
|
5
|
-
emit: IEmits
|
|
6
|
-
beforePageChange: () => void
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export default function usePagination({ emit, beforePageChange }: IParams) {
|
|
10
|
-
|
|
11
|
-
const pageSize = ref(10);
|
|
12
|
-
|
|
13
|
-
const handlePageSizeChange = (size: number) => {
|
|
14
|
-
pageSize.value = size;
|
|
15
|
-
// searchValue.value = {};
|
|
16
|
-
beforePageChange();
|
|
17
|
-
emit('page-change', { size, page: 1 });
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const handleCurrPageChange = (curr: number) => {
|
|
21
|
-
// searchValue.value = {};
|
|
22
|
-
beforePageChange();
|
|
23
|
-
emit('page-change', { size: pageSize.value, page: curr });
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
pageSize,
|
|
28
|
-
handlePageSizeChange,
|
|
29
|
-
handleCurrPageChange,
|
|
30
|
-
}
|
|
1
|
+
import { ref } from "vue"
|
|
2
|
+
import { IEmits } from "./types"
|
|
3
|
+
|
|
4
|
+
interface IParams {
|
|
5
|
+
emit: IEmits
|
|
6
|
+
beforePageChange: () => void
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function usePagination({ emit, beforePageChange }: IParams) {
|
|
10
|
+
|
|
11
|
+
const pageSize = ref(10);
|
|
12
|
+
|
|
13
|
+
const handlePageSizeChange = (size: number) => {
|
|
14
|
+
pageSize.value = size;
|
|
15
|
+
// searchValue.value = {};
|
|
16
|
+
beforePageChange();
|
|
17
|
+
emit('page-change', { size, page: 1 });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const handleCurrPageChange = (curr: number) => {
|
|
21
|
+
// searchValue.value = {};
|
|
22
|
+
beforePageChange();
|
|
23
|
+
emit('page-change', { size: pageSize.value, page: curr });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
pageSize,
|
|
28
|
+
handlePageSizeChange,
|
|
29
|
+
handleCurrPageChange,
|
|
30
|
+
}
|
|
31
31
|
}
|