@ctzy-web-client/plugin-component-vue 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/package.json +43 -0
  2. package/src/advance-select/advance-operation.vue +44 -0
  3. package/src/advance-select/advance-option.vue +115 -0
  4. package/src/advance-select/advance-select.vue +343 -0
  5. package/src/advance-select/events-helpers.js +40 -0
  6. package/src/advance-select/index.js +13 -0
  7. package/src/advance-select/use-advance-option.js +58 -0
  8. package/src/advance-select/use-advance-select.js +142 -0
  9. package/src/application-slot/application-slot.js +70 -0
  10. package/src/application-slot/breadcrumb-item.vue +12 -0
  11. package/src/application-slot/header-tools-item.vue +12 -0
  12. package/src/application-slot/index.js +17 -0
  13. package/src/breadcrumb-select/breadcrumb-select.vue +97 -0
  14. package/src/breadcrumb-select/index.js +6 -0
  15. package/src/components.js +39 -0
  16. package/src/contextmenu/contextmenu-item.vue +13 -0
  17. package/src/contextmenu/contextmenu.vue +56 -0
  18. package/src/contextmenu/index.js +11 -0
  19. package/src/contextmenu/use-contextmenu.js +117 -0
  20. package/src/data-form/data-form-item.vue +49 -0
  21. package/src/data-form/data-form.vue +212 -0
  22. package/src/data-form/dynamic-component.js +24 -0
  23. package/src/data-form/form-components/Blots/AtBlot.js +32 -0
  24. package/src/data-form/form-components/bwa-date-picker.vue +43 -0
  25. package/src/data-form/form-components/bwa-date-time-picker.vue +49 -0
  26. package/src/data-form/form-components/bwa-input-float.vue +41 -0
  27. package/src/data-form/form-components/bwa-input-integer.vue +58 -0
  28. package/src/data-form/form-components/bwa-input.vue +32 -0
  29. package/src/data-form/form-components/bwa-multi-select.vue +27 -0
  30. package/src/data-form/form-components/bwa-rich-text-tinymce.vue +561 -0
  31. package/src/data-form/form-components/bwa-rich-text.vue +395 -0
  32. package/src/data-form/form-components/bwa-select.vue +67 -0
  33. package/src/data-form/form-components/bwa-textarea.vue +28 -0
  34. package/src/data-form/form-components/bwa-upload.vue +145 -0
  35. package/src/data-form/form-components/bwa-user-multi-select.vue +25 -0
  36. package/src/data-form/form-components/bwa-user-select.vue +81 -0
  37. package/src/data-form/index.js +35 -0
  38. package/src/data-table/data-column-view.vue +131 -0
  39. package/src/data-table/data-table-card.vue +81 -0
  40. package/src/data-table/data-table-column.vue +52 -0
  41. package/src/data-table/data-table.vue +426 -0
  42. package/src/data-table/dynamic-component.js +58 -0
  43. package/src/data-table/index.js +13 -0
  44. package/src/data-table/use-datatable-drag.js +156 -0
  45. package/src/datatable-settings/datatable-settings.vue +323 -0
  46. package/src/datatable-settings/index.js +6 -0
  47. package/src/date-range/date-picker.vue +115 -0
  48. package/src/date-range/date-range.vue +202 -0
  49. package/src/date-range/index.js +6 -0
  50. package/src/drag-list/constants.js +1 -0
  51. package/src/drag-list/drag-item.vue +46 -0
  52. package/src/drag-list/drag-list.vue +50 -0
  53. package/src/drag-list/index.js +6 -0
  54. package/src/drag-list/use-drag-list.js +209 -0
  55. package/src/dragable/constants.js +3 -0
  56. package/src/dragable/dragable-item.vue +19 -0
  57. package/src/dragable/dragable-operation.vue +28 -0
  58. package/src/dragable/dragable.vue +26 -0
  59. package/src/dragable/index.js +14 -0
  60. package/src/dragable/use-dragable.js +227 -0
  61. package/src/filter-panel/conditions/condition.js +35 -0
  62. package/src/filter-panel/conditions/date-range-condition.vue +35 -0
  63. package/src/filter-panel/conditions/department-condition/data.json +29537 -0
  64. package/src/filter-panel/conditions/department-condition/department-condition.vue +92 -0
  65. package/src/filter-panel/conditions/department-condition/department-node.vue +52 -0
  66. package/src/filter-panel/conditions/index.js +22 -0
  67. package/src/filter-panel/conditions/input-condition.vue +63 -0
  68. package/src/filter-panel/conditions/multi-user-condition.vue +56 -0
  69. package/src/filter-panel/conditions/multiple-menu-condition.vue +45 -0
  70. package/src/filter-panel/conditions/single-menu-condition.vue +58 -0
  71. package/src/filter-panel/conditions/single-user-condition.vue +56 -0
  72. package/src/filter-panel/filter-panel-item.vue +46 -0
  73. package/src/filter-panel/filter-panel.vue +149 -0
  74. package/src/filter-panel/index.js +17 -0
  75. package/src/filter-panel/use-filter-panel-item.js +59 -0
  76. package/src/filter-panel/use-filter-panel.js +203 -0
  77. package/src/hooks/use-data/index.js +234 -0
  78. package/src/index.js +48 -0
  79. package/src/layout/index.js +6 -0
  80. package/src/layout/layout.vue +74 -0
  81. package/src/make-installer.js +36 -0
  82. package/src/math/Rectangle.js +28 -0
  83. package/src/menu/index.js +6 -0
  84. package/src/menu/menu-item.vue +41 -0
  85. package/src/menu/menu.vue +53 -0
  86. package/src/panel/index.js +6 -0
  87. package/src/panel/panel.vue +42 -0
  88. package/src/panel-tabs/index.js +6 -0
  89. package/src/panel-tabs/panel-tabs.js +92 -0
  90. package/src/pct-filter-panel/index.js +10 -0
  91. package/src/pct-filter-panel/pct-compents/index.js +10 -0
  92. package/src/pct-filter-panel/pct-compents/pct-Input-condition.vue +63 -0
  93. package/src/pct-filter-panel/pct-compents/pct-date-range-condition.vue +60 -0
  94. package/src/pct-filter-panel/pct-compents/pct-multiple-menu-condition.vue +177 -0
  95. package/src/pct-filter-panel/pct-compents/pct-multiple-menu-condition2.vue +142 -0
  96. package/src/pct-filter-panel/pct-filter-panel-item.vue +46 -0
  97. package/src/pct-filter-panel/pct-filter-panel.vue +201 -0
  98. package/src/pct-filter-panel/use-filter-panel-item.js +61 -0
  99. package/src/pct-filter-panel/use-filter-panel.js +206 -0
  100. package/src/plugins.js +3 -0
  101. package/src/progress/index.js +8 -0
  102. package/src/progress/progress-item.vue +81 -0
  103. package/src/progress/progress.vue +58 -0
  104. package/src/progress/use-progress.js +66 -0
  105. package/src/utils/db.js +8 -0
  106. package/src/utils.js +263 -0
  107. package/src/where-filter-panel/index.js +0 -0
  108. package/src/where-filter-panel/use-where-filter-panel.js +28 -0
  109. package/src/where-filter-panel/where-filter-panel.vue +9 -0
  110. package/style/advance-select.scss +316 -0
  111. package/style/breadcrumb-select.scss +80 -0
  112. package/style/common/var.scss +240 -0
  113. package/style/common.scss +48 -0
  114. package/style/contextmenu.scss +58 -0
  115. package/style/data-form.scss +35 -0
  116. package/style/data-table.scss +81 -0
  117. package/style/datatable-settings.scss +125 -0
  118. package/style/date-range.scss +136 -0
  119. package/style/department-condition.scss +39 -0
  120. package/style/drag-list.scss +68 -0
  121. package/style/dragable.scss +8 -0
  122. package/style/filter-panel.scss +199 -0
  123. package/style/index.scss +22 -0
  124. package/style/input-condition.scss +30 -0
  125. package/style/layout.scss +70 -0
  126. package/style/menu.scss +184 -0
  127. package/style/mixins/_var.scss +21 -0
  128. package/style/mixins/config.scss +4 -0
  129. package/style/mixins/function.scss +62 -0
  130. package/style/mixins/mixins.scss +88 -0
  131. package/style/panel-tabs.scss +60 -0
  132. package/style/panel.scss +110 -0
  133. package/style/pct-filter-panel.scss +306 -0
  134. package/style/progress.scss +122 -0
  135. package/style/rich-text.scss +30 -0
  136. package/style/theme/theme.scss +161 -0
  137. package/style/theme/var.scss +34 -0
  138. package/style/var.scss +21 -0
@@ -0,0 +1,426 @@
1
+ <template>
2
+ <div :class="ns.b()" ref="dataTableEl">
3
+ <slot :dataTable="dataTable">
4
+ <ElTable
5
+ class="content"
6
+ height="100%"
7
+ ref="elTable"
8
+ :data="data"
9
+ :row-key="dataTable.primaryKey"
10
+ show-header
11
+ stripe
12
+ v-bind="attrs"
13
+ @selection-change="selectionChange"
14
+ @sort-change="sortHandle"
15
+ :border="border"
16
+ >
17
+ <ElTableColumn v-if="showDrag" width="40px">
18
+ <div :class="ns.e('drag')">
19
+ <slot>
20
+ <i class="ptp-icon ptp-buzhou-yidong"></i>
21
+ </slot>
22
+ </div>
23
+ </ElTableColumn>
24
+ <slot v-if="selection" name="selection">
25
+ <ElTableColumn type="selection" align="center" width="56" :reserve-selection="true" />
26
+ </slot>
27
+ <slot v-if="showIndex" name="index">
28
+ <ElTableColumn
29
+ type="index"
30
+ width="60"
31
+ align="center"
32
+ :label="indexColumnLabel"
33
+ />
34
+ </slot>
35
+
36
+ <slot name="table-columns" :dataTable="dataTable">
37
+ <BwaDataTableColumn
38
+ v-for="item in displayColumns"
39
+ :column-key="item.attrName"
40
+ :key="item.attrName"
41
+ :label="item.title"
42
+ :prop="item.fullAttrName"
43
+ :min-width="item.width"
44
+ :align="item.align"
45
+ v-bind="item.componentProps"
46
+ :sortable="item.sortable=='custom'"
47
+ >
48
+ <template #header>
49
+ <slot :name="`table-header-col-${item.attrName}`">
50
+ {{ item.title }}
51
+ </slot>
52
+ </template>
53
+ <template #default="{ row, $index }">
54
+ <slot
55
+ v-if="data.length"
56
+ :name="'table-col-' + item.attrName"
57
+ :row="row"
58
+ :index="$index"
59
+ :column="item"
60
+ :dataTable="dataTable"
61
+ >
62
+ <DynamicComponent :column="item" :record="row" />
63
+ </slot>
64
+ </template>
65
+ </BwaDataTableColumn>
66
+ </slot>
67
+
68
+ <slot name="column-append"></slot>
69
+ <template #empty>
70
+ <slot name="empty-table"></slot>
71
+ </template>
72
+ </ElTable>
73
+ </slot>
74
+ <div v-if="showPagination" :class="ns.e('pagination')">
75
+ <div :class="ns.e('pagination-info')">
76
+ 共{{ totalPage }}页,{{ dataTable.totalRecCount }}条
77
+ </div>
78
+ <ElPagination
79
+ :currentPage="dataTable.pageNum"
80
+ :page-sizes="paginationPageSizes"
81
+ :page-size="dataTable.pageSize"
82
+ :layout="paginationLayout"
83
+ :total="dataTable.totalRecCount"
84
+ @size-change="dataTable.setPageSize($event)"
85
+ @current-change="dataTable.pageTo($event)"
86
+ :teleported="false"
87
+ />
88
+ </div>
89
+ <div
90
+ v-if="barRectangle"
91
+ :class="ns.e('dragbar')"
92
+ :style="{
93
+ left: barRectangle.left + 'px',
94
+ top: barRectangle.top + 'px',
95
+ width: barRectangle.width + 'px',
96
+ height: barRectangle.height + 'px',
97
+ }"
98
+ ></div>
99
+ </div>
100
+ </template>
101
+ <script setup>
102
+ import { ElMessage, ElPagination, ElTable, ElTableColumn } from 'element-plus';
103
+ import {
104
+ computed,
105
+ nextTick,
106
+ onBeforeUnmount,
107
+ onUnmounted,
108
+ provide,
109
+ reactive,
110
+ watch,
111
+ ref,
112
+ unref,
113
+ useAttrs,
114
+ } from 'vue';
115
+ import {
116
+ dataTableKey,
117
+ useNamespace,
118
+ useEventDispatcher,
119
+ useGlobalConfig,
120
+ useService,
121
+ } from 'web-base-client-vue';
122
+ import DynamicComponent from './dynamic-component.js';
123
+ import BwaDataTableColumn from './data-table-column.vue';
124
+ import { useDataTableDrag } from './use-datatable-drag';
125
+ import { get } from 'lodash';
126
+ import {
127
+ from,
128
+ delayWhen,
129
+ map,
130
+ skipWhile,
131
+ Observable,
132
+ filter,
133
+ Subject,
134
+ debounceTime,
135
+ } from 'rxjs';
136
+
137
+ defineOptions({ name: 'BwaDataTable' });
138
+
139
+ const props = defineProps({
140
+ dataTable: {
141
+ type: Object,
142
+ required: true,
143
+ },
144
+ autoLoad: {
145
+ type: Boolean,
146
+ default: true,
147
+ },
148
+ showIndex: {
149
+ type: Boolean,
150
+ default: false,
151
+ },
152
+ indexColumnLabel: {
153
+ type: String,
154
+ default: '编号',
155
+ },
156
+ selection: {
157
+ type: Boolean,
158
+ default: false,
159
+ },
160
+ paginationLayout: {
161
+ type: String,
162
+ default: 'sizes, prev, pager, next, jumper',
163
+ },
164
+ paginationPageSizes: {
165
+ type: Array,
166
+ default: () => [10, 20, 50, 100, 200],
167
+ },
168
+ showPagination: {
169
+ type: Boolean,
170
+ default: true,
171
+ },
172
+ whereParamName: {
173
+ type: String,
174
+ default: '',
175
+ },
176
+ showDrag: {
177
+ type: Boolean,
178
+ default: false,
179
+ },
180
+ border: {
181
+ type: Boolean,
182
+ default: true,
183
+ }
184
+ });
185
+
186
+ const attrs = useAttrs();
187
+
188
+ const userService = useService('UserService');
189
+
190
+ const elTable = ref(null);
191
+
192
+ const dataTable = props.dataTable;
193
+ dataTable._userService = userService.value?.getUserList
194
+
195
+ const dataTableEl = ref(null);
196
+
197
+ const displayColumns = computed(
198
+ () => unref(dataTable).getDisplayColumns() || []
199
+ );
200
+
201
+ watch(
202
+ computed(() => props.whereParamName),
203
+ (whereParamName) => {
204
+ dataTable.setWhereParamName(whereParamName || '');
205
+ },
206
+ { immediate: true, flush: 'sync' }
207
+ );
208
+
209
+ const searchParams = computed(() => props.searchParams);
210
+
211
+ const emit = defineEmits(['drag']);
212
+
213
+ const debounceDelay = useGlobalConfig('debounceDelay', 500);
214
+
215
+ //当前data table 上下文对象
216
+ provide(
217
+ dataTableKey,
218
+ reactive({
219
+ dataTable,
220
+ displayColumns,
221
+ })
222
+ );
223
+
224
+ const ns = useNamespace('datatable');
225
+
226
+ const { barRectangle } = useDataTableDrag(
227
+ dataTableEl,
228
+ '.bwa-datatable__drag',
229
+ '.el-table__row',
230
+ { emit }
231
+ );
232
+
233
+ const processing = ref(false);
234
+
235
+ const data = computed(() => {
236
+ return props.dataTable.data;
237
+ });
238
+
239
+ useEventDispatcher(dataTable, 'load-successfully', async (res) => {
240
+ if (res.code != 0) {
241
+ return;
242
+ }
243
+
244
+ const _userService = unref(userService);
245
+
246
+ if (!_userService) {
247
+ return;
248
+ }
249
+
250
+ let columns = dataTable.getColumns();
251
+
252
+ const componentNames = ['BwaUserSelect', 'BwaUserMultiSelect'];
253
+
254
+ columns = columns
255
+ .filter((column) => componentNames.includes(column.formComponent))
256
+ .filter((column) => column.visible)
257
+ .filter((column) => column.isExtend);
258
+
259
+ if (!columns.length) {
260
+ return;
261
+ }
262
+
263
+ processing.value = true;
264
+
265
+ const data = res.data;
266
+
267
+ let ids = data
268
+ .reduce((result, item) => {
269
+ return result.concat(
270
+ columns.reduce((result, column) => {
271
+ let value = get(item, column.fullAttrName);
272
+
273
+ value = Array.isArray(value) ? value : value ? [value] : [];
274
+
275
+ return result.concat(value);
276
+ }, [])
277
+ );
278
+ }, [])
279
+ .map((id) => id + '');
280
+
281
+ ids = [...new Set(ids)];
282
+
283
+ try {
284
+ const userListResult = await _userService.getUserListByIds(ids);
285
+
286
+ if (userListResult.code != 0) {
287
+ return;
288
+ }
289
+
290
+ for (const column of columns) {
291
+ column.componentProps = column.componentProps || {};
292
+ column.componentProps.options = (userListResult.data || []).map(
293
+ (item) => ({
294
+ label: item.label,
295
+ value: item.value,
296
+ })
297
+ );
298
+ }
299
+
300
+ console.log(userListResult);
301
+ } finally {
302
+ processing.value = false;
303
+ }
304
+ });
305
+
306
+ //手动排序
307
+ const sortHandle = (column, prop, order) => {
308
+ let sortColumn = ''
309
+ let sortType = ''
310
+ if (column.order){
311
+ sortColumn = column.prop
312
+ sortType = column.order=="descending"?0:1
313
+ dataTable.setParam('sortColumn', sortColumn);
314
+ dataTable.setParam('sortType', sortType);
315
+ }else{
316
+ dataTable.setParam('sortColumn', sortColumn);
317
+ dataTable.setParam('sortType', sortType);
318
+ }
319
+ dataTable.load()
320
+ }
321
+
322
+ useEventDispatcher(dataTable, 'load-successfully', (res) => {
323
+ if (!elTable.value) {
324
+ return;
325
+ }
326
+
327
+ unref(elTable).store.updateSelectionByRowKey();
328
+
329
+ if (res.code != 0) {
330
+ ElMessage.error(res.msg);
331
+ }
332
+ });
333
+
334
+ function sortColumn(array) {
335
+ array.forEach((item) => {
336
+ item.no = item.getColumnIndex?.();
337
+ if (item.children?.length) {
338
+ sortColumn(item.children);
339
+ }
340
+ });
341
+ array.sort((cur, pre) => cur.no - pre.no);
342
+ }
343
+
344
+ const tableSelectSubject = new Subject();
345
+ const selectionChange = tableSelectSubject.next.bind(tableSelectSubject);
346
+
347
+ const totalPage = computed(() => dataTable.getTotalPage());
348
+
349
+ const tableSelectSubscription = tableSelectSubject
350
+ .pipe(debounceTime(debounceDelay))
351
+ .subscribe(unref(dataTable).setSelection.bind(unref(dataTable)));
352
+
353
+ const selectChangeAPIObservable = new Observable((observer) =>
354
+ useEventDispatcher(
355
+ props.dataTable,
356
+ 'select-change',
357
+ observer.next.bind(observer)
358
+ )
359
+ )
360
+ .pipe(
361
+ filter((selection) => {
362
+ if (!unref(elTable)) {
363
+ return false;
364
+ }
365
+
366
+ const selectionRows = unref(elTable).getSelectionRows();
367
+
368
+ if (selectionRows.length !== selection.length) {
369
+ return true;
370
+ }
371
+
372
+ const primaryKey = dataTable.primaryKey;
373
+ return !selectionRows.every((item) =>
374
+ selection.find((itm) => item[primaryKey] === item[primaryKey])
375
+ );
376
+ })
377
+ )
378
+ .subscribe((selection) => {
379
+ unref(elTable).clearSelection();
380
+ for (const item of selection) {
381
+ unref(elTable).toggleRowSelection(item, true);
382
+ }
383
+ });
384
+
385
+ if (props.autoLoad) {
386
+ //初始化加载
387
+ dataTable.load();
388
+ }
389
+
390
+ const searchParamsSubscription = new Observable((observer) =>
391
+ useEventDispatcher(
392
+ props.dataTable.filterPanel,
393
+ 'params-change',
394
+ observer.next.bind(observer)
395
+ )
396
+ )
397
+ .pipe(
398
+ filter(() => props.dataTable.filterPanel.ready),
399
+ debounceTime(unref(debounceDelay))
400
+ )
401
+ .subscribe(() => {
402
+ props.dataTable.load();
403
+ });
404
+
405
+ const subscription = props.dataTable
406
+ .getDisplayColumnsSubject()
407
+ .pipe(
408
+ map(() => unref(elTable)),
409
+ delayWhen(() => from(nextTick())),
410
+ map((elTable) => elTable?.store),
411
+ skipWhile((store) => !store)
412
+ )
413
+ .subscribe((store) => {
414
+ sortColumn(unref(store.states._columns));
415
+
416
+ store.updateColumns();
417
+ store.scheduleLayout();
418
+ });
419
+
420
+ onUnmounted(() => {
421
+ selectChangeAPIObservable.unsubscribe();
422
+ subscription.unsubscribe();
423
+ tableSelectSubscription.unsubscribe();
424
+ searchParamsSubscription.unsubscribe();
425
+ });
426
+ </script>
@@ -0,0 +1,58 @@
1
+ import { computed, h, unref } from 'vue';
2
+ import get from 'lodash/get';
3
+ import { useDynamicComponent } from '../utils.js';
4
+
5
+ const formatValue = (column, value) => {
6
+ const options = column.componentProps.options || [];
7
+
8
+ const _value = Array.isArray(value) ? value : [value];
9
+
10
+ const labels = _value.map(
11
+ (v) => options.find((option) => option.value === v) ?? null
12
+ );
13
+
14
+ if (labels.includes(null)) {
15
+ return null;
16
+ }
17
+
18
+ return labels.map((item) => item.label).join(',');
19
+ };
20
+
21
+ export default {
22
+ props: {
23
+ column: Object,
24
+ record: Object,
25
+ },
26
+ emits: ['on-change'],
27
+ setup(props, context) {
28
+ //组件信息
29
+ const { component, params } = useDynamicComponent(
30
+ props,
31
+ context,
32
+ 'BwaDataColumnView',
33
+ 'fullAttrName'
34
+ );
35
+
36
+ const viewType = computed(() =>
37
+ props.column.formComponent === 'BwaRichText' ? 'html' : ''
38
+ );
39
+
40
+ return () => {
41
+ let value = get(props.record, props.column.fullAttrName);
42
+
43
+ if (Array.isArray(props.column.componentProps?.options)) {
44
+ value = formatValue(props.column, value) || value;
45
+ }
46
+
47
+ return h(unref(component), {
48
+ ...unref(params),
49
+ value,
50
+ type: props.column.type,
51
+ align: props.column.align,
52
+ rule: props.column.rule,
53
+ template: props.column.template,
54
+ defaultValue: props.column.default || '-',
55
+ });
56
+ };
57
+ },
58
+ };
@@ -0,0 +1,13 @@
1
+ import { withInstall } from 'element-plus/es/utils/vue/install';
2
+ import DataTable from './data-table.vue';
3
+ import DataTableColumn from './data-table-column.vue';
4
+ import DataColumnView from '../data-table/data-column-view.vue';
5
+
6
+ export const BwaDataTable = withInstall(DataTable, {
7
+ DataTableColumn,
8
+ DataColumnView,
9
+ });
10
+ export const BwaDataTableColumn = withInstall(DataTableColumn);
11
+ export const BwaDataColumnView = withInstall(DataColumnView);
12
+
13
+ export default BwaDataTable;
@@ -0,0 +1,156 @@
1
+ import { onBeforeUnmount, onMounted, ref, unref } from 'vue';
2
+ import { filter, fromEvent, map, switchMap, takeUntil, tap } from 'rxjs';
3
+ import { Rectangle } from '../math/Rectangle';
4
+
5
+ /**
6
+ * @param {import("vue").Ref<HTMLElement>} el
7
+ * @param {string} dragClass
8
+ * @param {string} itemClass
9
+ */
10
+ export const useDataTableDrag = (el, dragClass, itemClass, context) => {
11
+ /** @type {import("rxjs").Subscription} */
12
+ let mousedownSubscription = null;
13
+
14
+ let barRectangle = ref(null);
15
+
16
+ onMounted(() => {
17
+ /** @type {import("rxjs").Observable<MouseEvent>} */
18
+ let mouseDownObservable = fromEvent(unref(el), 'mousedown');
19
+ /** @type {import("rxjs").Observable<MouseEvent>} */
20
+ let mousemoveObservable = fromEvent(unref(document), 'mousemove');
21
+ /** @type {import("rxjs").Observable<MouseEvent>} */
22
+ let mouseupObservable = fromEvent(unref(document), 'mouseup');
23
+
24
+ /** @type {Rectangle[]} */
25
+ let rectangles = [];
26
+
27
+ /** @type {HTMLElement} */
28
+ let cloneEl = null;
29
+ let offsetX = 0;
30
+ let offsetY = 0;
31
+ let targetIndex = -1;
32
+
33
+ // moousedown mousemove* mouseup
34
+ mousedownSubscription = mouseDownObservable
35
+ .pipe(
36
+ filter((event) => {
37
+ const list = Array.from(unref(el).querySelectorAll(dragClass));
38
+ const item = list.find((item) => item.contains(event.target));
39
+
40
+ if (item) {
41
+ event.index = list.indexOf(item);
42
+
43
+ const row = Array.from(unref(el).querySelectorAll(itemClass)).find(
44
+ (row) => row.contains(item)
45
+ );
46
+ const _cloneEl = row.cloneNode(true);
47
+
48
+ const boundary = row.getBoundingClientRect();
49
+
50
+ cloneEl = document.createElement('div');
51
+ cloneEl.className = 'bwa-datatable';
52
+ const tableEl = document.createElement('table');
53
+ tableEl.className = 'el-table';
54
+ const tbodyEl = document.createElement('tbody');
55
+ cloneEl.append(tableEl);
56
+ tableEl.appendChild(tbodyEl);
57
+ tbodyEl.appendChild(_cloneEl);
58
+
59
+ offsetX = event.x - boundary.left;
60
+ offsetY = event.y - boundary.top;
61
+
62
+ console.log();
63
+
64
+ Object.assign(cloneEl.style, {
65
+ position: 'absolute',
66
+ left: event.clientX - offsetX + 'px',
67
+ top: event.clientY - offsetY + 'px',
68
+ zIndex: '9999',
69
+ height: boundary.height + 'px',
70
+ width: boundary.width + 'px',
71
+ opacity: '0.6',
72
+ pointerEvents: 'none',
73
+ });
74
+
75
+ document.body.appendChild(cloneEl);
76
+
77
+ document.body.style.cursor = 'move';
78
+ document.body.style.userSelect = 'none';
79
+ }
80
+
81
+ return !!item;
82
+ }),
83
+ tap(() => {
84
+ rectangles = Array.from(unref(el).querySelectorAll(itemClass)).map(
85
+ (item) => {
86
+ const { x, y, width, height } = item.getBoundingClientRect();
87
+ return new Rectangle(x, y, width, height);
88
+ }
89
+ );
90
+ }),
91
+ map((event) => {
92
+ return {
93
+ index: event.index,
94
+ x: event.clientX,
95
+ y: event.clientY,
96
+ };
97
+ }),
98
+ switchMap(({ index, x, y }) => {
99
+ return mousemoveObservable.pipe(
100
+ takeUntil(
101
+ mouseupObservable.pipe(
102
+ tap(() => {
103
+ if (targetIndex !== -1) {
104
+ context.emit('drag', index, targetIndex);
105
+ }
106
+ cloneEl?.remove();
107
+ rectangles = [];
108
+ offsetX = offsetY = 0;
109
+ document.body.style.cursor = '';
110
+ document.body.style.userSelect = '';
111
+ barRectangle.value = null;
112
+ targetIndex = -1;
113
+ })
114
+ )
115
+ ),
116
+ map((event) => {
117
+ Object.assign(cloneEl.style, {
118
+ left: event.clientX - offsetX + 'px',
119
+ top: event.clientY - offsetY + 'px',
120
+ });
121
+
122
+ const rectangle = rectangles.find((rectangle) =>
123
+ rectangle.pointIn(event.x, event.y)
124
+ );
125
+
126
+ if (!rectangle) {
127
+ targetIndex = -1;
128
+ barRectangle.value = null;
129
+ return;
130
+ }
131
+
132
+ targetIndex = rectangles.indexOf(rectangle);
133
+ const direction =
134
+ event.clientY >= rectangle.cy ? 'after' : 'before';
135
+
136
+ targetIndex = targetIndex + (direction === 'after' ? 1 : 0);
137
+
138
+ barRectangle.value = new Rectangle(
139
+ rectangle.left,
140
+ direction === 'after' ? rectangle.bottom : rectangle.top,
141
+ rectangle.width,
142
+ 2
143
+ );
144
+ })
145
+ );
146
+ })
147
+ )
148
+ .subscribe((info) => {});
149
+ });
150
+
151
+ onBeforeUnmount(() => {
152
+ mousedownSubscription?.unsubscribe();
153
+ });
154
+
155
+ return { barRectangle };
156
+ };