br-dionysus 1.17.7 → 1.18.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.
- package/README.md +73 -24
- package/attributes.json +1 -1
- package/cypress/component/MSelect.cy.ts +0 -1
- package/cypress/component/MSelectTable.cy.ts +538 -0
- package/cypress/component/MSelectV2.cy.ts +0 -1
- package/cypress/component/MTable.cy.ts +123 -0
- package/cypress/e2e/1-getting-started/todo.cy.js +143 -0
- package/cypress/e2e/2-advanced-examples/actions.cy.js +321 -0
- package/cypress/e2e/2-advanced-examples/aliasing.cy.js +39 -0
- package/cypress/e2e/2-advanced-examples/assertions.cy.js +176 -0
- package/cypress/e2e/2-advanced-examples/connectors.cy.js +98 -0
- package/cypress/e2e/2-advanced-examples/cookies.cy.js +118 -0
- package/cypress/e2e/2-advanced-examples/cypress_api.cy.js +184 -0
- package/cypress/e2e/2-advanced-examples/files.cy.js +85 -0
- package/cypress/e2e/2-advanced-examples/location.cy.js +32 -0
- package/cypress/e2e/2-advanced-examples/misc.cy.js +98 -0
- package/cypress/e2e/2-advanced-examples/navigation.cy.js +55 -0
- package/cypress/e2e/2-advanced-examples/network_requests.cy.js +163 -0
- package/cypress/e2e/2-advanced-examples/querying.cy.js +114 -0
- package/cypress/e2e/2-advanced-examples/spies_stubs_clocks.cy.js +204 -0
- package/cypress/e2e/2-advanced-examples/storage.cy.js +117 -0
- package/cypress/e2e/2-advanced-examples/traversal.cy.js +121 -0
- package/cypress/e2e/2-advanced-examples/utilities.cy.js +107 -0
- package/cypress/e2e/2-advanced-examples/viewport.cy.js +58 -0
- package/cypress/e2e/2-advanced-examples/waiting.cy.js +30 -0
- package/cypress/e2e/2-advanced-examples/window.cy.js +22 -0
- package/cypress/e2e/toolSlotsToData.cy.ts +127 -0
- package/cypress/e2e/toolUniqueByKey.cy.ts +79 -0
- package/cypress/support/component.ts +20 -1
- package/cypress.config.ts +1 -0
- package/dist/br-dionysus.es.js +5872 -5696
- package/dist/br-dionysus.umd.js +6 -5
- package/dist/cypress/component/MInputNumber.cy.d.ts +0 -0
- package/dist/cypress/component/MSelect.cy.d.ts +1 -0
- package/dist/cypress/component/MSelectTable.cy.d.ts +1 -0
- package/dist/cypress/component/MSelectV2.cy.d.ts +1 -0
- package/dist/cypress/component/MTable.cy.d.ts +1 -0
- package/dist/cypress/e2e/spec.cy.d.ts +0 -0
- package/dist/cypress/e2e/toolCheckType.cy.d.ts +1 -0
- package/dist/cypress/e2e/toolCompareStructures.cy.d.ts +1 -0
- package/dist/cypress/e2e/toolCreateHash.cy.d.ts +1 -0
- package/dist/cypress/e2e/toolMoneyFormat.cy.d.ts +1 -0
- package/dist/cypress/e2e/toolSlotsToData.cy.d.ts +1 -0
- package/dist/cypress/e2e/toolUniqueByKey.cy.d.ts +1 -0
- package/dist/cypress/support/commands.d.ts +0 -0
- package/dist/cypress/support/component.d.ts +9 -0
- package/dist/cypress/support/e2e.d.ts +0 -0
- package/dist/index.css +1 -1
- package/dist/packages/Hook/usePackageConfig/usePackageConfig.d.ts +2 -0
- package/dist/packages/MTable/src/MTable.vue.d.ts +49 -15
- package/dist/packages/MTable/src/token.d.ts +13 -0
- package/dist/packages/MTableColumn/src/MTableColumn.vue.d.ts +9 -14
- package/dist/packages/Tool/globalEvents/globalEvents.d.ts +26 -0
- package/dist/packages/index.d.ts +2 -0
- package/package.json +2 -2
- package/packages/Hook/usePackageConfig/usePackageConfig.ts +6 -4
- package/packages/Hook/useZIndex/useGlobalZIndex.ts +1 -1
- package/packages/MDialog/src/MDialog.vue +8 -8
- package/packages/MSelectTable/docs/README.md +1 -0
- package/packages/MSelectTable/src/MSelectTable.vue +6 -6
- package/packages/MTable/docs/DemoTest4.vue +0 -1
- package/packages/MTable/docs/DemoTest6.vue +122 -0
- package/packages/MTable/docs/DemoTest7.vue +138 -0
- package/packages/MTable/docs/README.md +10 -10
- package/packages/MTable/docs/demo.vue +10 -2
- package/packages/MTable/src/MBatchEdit.vue +1 -0
- package/packages/MTable/src/MTable.vue +254 -38
- package/packages/MTable/src/token.ts +14 -1
- package/packages/MTableColumn/docs/README.md +1 -0
- package/packages/MTableColumn/src/MTableColumn.vue +98 -24
- package/packages/Tool/globalEvents/README.md +23 -0
- package/packages/Tool/globalEvents/globalEvents.ts +79 -0
- package/packages/index.ts +2 -0
- package/packages/typings/global.d.ts +6 -2
- package/tags.json +1 -1
- package/tsconfig.json +3 -1
- package/web-types.json +1 -1
- package/cypress/screenshots/MSelectTable.cy.ts//344/270/213/346/213/211/350/241/250/346/240/274/351/200/211/346/213/251/345/231/250/347/273/204/344/273/266MSelectTable -- /346/265/213/350/257/225/345/215/225/351/200/211/345/212/237/350/203/275 (failed).png +0 -0
- package/cypress/screenshots/MSelectTable.cy.ts//344/270/213/346/213/211/350/241/250/346/240/274/351/200/211/346/213/251/345/231/250/347/273/204/344/273/266MSelectTable -- /346/265/213/350/257/225/345/237/272/347/241/200/345/212/237/350/203/275 (failed).png +0 -0
- package/cypress/screenshots/MSelectTable.cy.ts//344/270/213/346/213/211/350/241/250/346/240/274/351/200/211/346/213/251/345/231/250/347/273/204/344/273/266MSelectTable -- /346/265/213/350/257/225/345/244/232/351/200/211/345/212/237/350/203/275 (failed).png +0 -0
- package/cypress/screenshots/MSelectTable.cy.ts//344/270/213/346/213/211/350/241/250/346/240/274/351/200/211/346/213/251/345/231/250/347/273/204/344/273/266MSelectTable -- /346/265/213/350/257/225/350/277/234/347/250/213/346/220/234/347/264/242/345/212/237/350/203/275 (failed).png +0 -0
- package/src/global.d.ts +0 -5
|
@@ -2,18 +2,22 @@
|
|
|
2
2
|
<div
|
|
3
3
|
class="br-m-table-box"
|
|
4
4
|
:data-is-expand="Boolean(props.expandProp)"
|
|
5
|
+
tabindex="0"
|
|
6
|
+
@keydown="onKeydown"
|
|
5
7
|
>
|
|
6
8
|
<el-table
|
|
7
9
|
ref="tableRef"
|
|
8
|
-
v-bind="
|
|
10
|
+
v-bind="attrs"
|
|
9
11
|
:size="props.size"
|
|
10
12
|
:data="tableData"
|
|
11
13
|
:expandRowKeys="expandRowKeys"
|
|
12
14
|
:rowKey="props.rowKey"
|
|
13
15
|
:cellStyle="cellStyle"
|
|
16
|
+
:summaryMethod="props.circleTotal ? summaryMethodFun : props.summaryMethod"
|
|
14
17
|
@paste="paste"
|
|
15
18
|
@cellClick="cellClick"
|
|
16
19
|
@expandChange="expandChange"
|
|
20
|
+
@cellMouseEnter="cellMouseEnter"
|
|
17
21
|
>
|
|
18
22
|
<slot name="default"></slot>
|
|
19
23
|
<slot name="append"></slot>
|
|
@@ -29,11 +33,12 @@
|
|
|
29
33
|
</template>
|
|
30
34
|
|
|
31
35
|
<script setup lang="ts">
|
|
32
|
-
import { ref, onMounted, computed, useSlots, watch, provide, reactive, getCurrentInstance } from 'vue'
|
|
36
|
+
import { ref, onMounted, computed, useSlots, watch, provide, reactive, getCurrentInstance, onUnmounted, useAttrs } from 'vue'
|
|
33
37
|
import checkType from '../../Tool/checkType/checkType'
|
|
34
38
|
import { TableConfig } from './../../Hook/useTableConfig/useTableConfig'
|
|
35
39
|
import { tableKey } from './token'
|
|
36
40
|
import slotsToData, { SlotsToDataReturnItem } from './../../Tool/slotsToData/slotsToData'
|
|
41
|
+
import globalEvents from '../../Tool/globalEvents/globalEvents'
|
|
37
42
|
|
|
38
43
|
interface FilterValue {
|
|
39
44
|
[key: string]: Array<string | number>;
|
|
@@ -55,10 +60,14 @@ const props = withDefaults(defineProps<{
|
|
|
55
60
|
rowKey?: Function | string;
|
|
56
61
|
/** 表格配置key */
|
|
57
62
|
tableConfigKey?: string;
|
|
58
|
-
/**
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
|
|
63
|
+
/** 选中列 */
|
|
64
|
+
selectionCell?: string | number | symbol;
|
|
65
|
+
// /** 是否在表尾显示合计行 */
|
|
66
|
+
// showSummary?: boolean;
|
|
67
|
+
/** 自定义的合计计算方法 */
|
|
68
|
+
summaryMethod?:((data: { columns: any[], data: any[] }) => string[]) | null;
|
|
69
|
+
/** 是否圈选合计 */
|
|
70
|
+
circleTotal?: boolean;
|
|
62
71
|
}>(), {
|
|
63
72
|
size: '',
|
|
64
73
|
sole: 'key',
|
|
@@ -69,16 +78,76 @@ const props = withDefaults(defineProps<{
|
|
|
69
78
|
expandRowKeys: () => [],
|
|
70
79
|
rowKey: '',
|
|
71
80
|
tableConfigKey: '',
|
|
72
|
-
|
|
73
|
-
|
|
81
|
+
selectionCell: '',
|
|
82
|
+
// showSummary: false,
|
|
83
|
+
summaryMethod: null,
|
|
84
|
+
circleTotal: true
|
|
74
85
|
})
|
|
75
86
|
|
|
76
87
|
const slots = useSlots()
|
|
77
88
|
|
|
89
|
+
const attrs = useAttrs()
|
|
90
|
+
|
|
91
|
+
const summaryMethodFun = (param: { columns: any[], data: Record<any, any>[] }): string[] => {
|
|
92
|
+
const value: string[] = []
|
|
93
|
+
const tableTitle: TableTitle[] = getTableTitle()
|
|
94
|
+
const tableTitleMap: Record<string, TableTitle> = {}
|
|
95
|
+
tableTitle.forEach(item => {
|
|
96
|
+
tableTitleMap[item.prop as string] = item
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
// 是否存在圈选
|
|
100
|
+
const isExistRange = selectionArea.startX !== null && selectionArea.startY !== null && selectionArea.endX !== null && selectionArea.endY !== null
|
|
101
|
+
if (!isExistRange) {
|
|
102
|
+
param.columns.forEach(column => {
|
|
103
|
+
let qty: number | string = ''
|
|
104
|
+
const isSummary = tableTitleMap[column.property]?.isSummary ?? true
|
|
105
|
+
|
|
106
|
+
param.data.forEach(item => {
|
|
107
|
+
const isNumber = checkType(item[column.property]).isNumber()
|
|
108
|
+
if (isNumber && isSummary) qty = (qty || 0) + item[column.property]
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
if (!column.property) value.push((attrs as any)?.sumText ?? '合')
|
|
112
|
+
else if (column.property === 'sn') value.push('')
|
|
113
|
+
else value.push(qty)
|
|
114
|
+
})
|
|
115
|
+
return value
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const startX: number = (selectionArea.startX || 0) > (selectionArea.endX || 0) ? (selectionArea.endX || 0) : (selectionArea.startX || 0)
|
|
119
|
+
const startY: number = (selectionArea.startY || 0) > (selectionArea.endY || 0) ? (selectionArea.endY || 0) : (selectionArea.startY || 0)
|
|
120
|
+
const endX: number = (selectionArea.startX || 0) > (selectionArea.endX || 0) ? (selectionArea.startX || 0) : (selectionArea.endX || 0)
|
|
121
|
+
const endY: number = (selectionArea.startY || 0) > (selectionArea.endY || 0) ? (selectionArea.startY || 0) : (selectionArea.endY || 0)
|
|
122
|
+
|
|
123
|
+
param.columns.forEach((column, x) => {
|
|
124
|
+
let qty: number | string = ''
|
|
125
|
+
const isSummary = tableTitleMap[column.property]?.isSummary ?? true
|
|
126
|
+
|
|
127
|
+
// 是否为圈选行
|
|
128
|
+
const isRangeCol = x >= startX && x <= endX
|
|
129
|
+
|
|
130
|
+
param.data.forEach((item, y) => {
|
|
131
|
+
const isNumber = checkType(item[column.property]).isNumber()
|
|
132
|
+
// 是否在圈选范围
|
|
133
|
+
const isRange = x >= startX && x <= endX && y >= startY && y <= endY
|
|
134
|
+
if (isNumber && !isRangeCol && isSummary) qty = (qty || 0) + item[column.property]
|
|
135
|
+
if (isNumber && isRangeCol && isRange && isSummary) qty = (qty || 0) + item[column.property]
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
if (!column.property) value.push((attrs as any)?.sumText ?? '合')
|
|
139
|
+
else if (column.property === 'sn') value.push('')
|
|
140
|
+
else value.push(qty)
|
|
141
|
+
})
|
|
142
|
+
return value
|
|
143
|
+
}
|
|
144
|
+
|
|
78
145
|
/**
|
|
79
|
-
* 获取表格头信息
|
|
146
|
+
* @description 获取表格头信息
|
|
147
|
+
* @param {boolean} isComplete 是否包含完整信息(既多选列等)
|
|
148
|
+
* @return {TableTitle[]} 表格头信息
|
|
80
149
|
* */
|
|
81
|
-
const getTableTitle = (): TableTitle[] => {
|
|
150
|
+
const getTableTitle = (isComplete: boolean = false): TableTitle[] => {
|
|
82
151
|
const slotDefaultData = slotsToData(slots, {
|
|
83
152
|
name: 'default',
|
|
84
153
|
isJumpFgt: false,
|
|
@@ -92,7 +161,7 @@ const getTableTitle = (): TableTitle[] => {
|
|
|
92
161
|
mTableColumnItemList.push(item)
|
|
93
162
|
}
|
|
94
163
|
})
|
|
95
|
-
|
|
164
|
+
let tableTitle: TableTitle[] = mTableColumnItemList.map(item => {
|
|
96
165
|
return {
|
|
97
166
|
label: item.props?.label ?? '',
|
|
98
167
|
prop: item.props?.prop ?? '',
|
|
@@ -102,9 +171,11 @@ const getTableTitle = (): TableTitle[] => {
|
|
|
102
171
|
fixed: item.props?.fixed ?? false,
|
|
103
172
|
isBatchEdit: item.props?.isBatchEdit === '' || item.props?.isBatchEdit === true,
|
|
104
173
|
show: item.props?.show ?? true,
|
|
105
|
-
sort: item.props?.sort ?? 0
|
|
174
|
+
sort: item.props?.sort ?? 0,
|
|
175
|
+
isSummary: item.props?.isSummary ?? true
|
|
106
176
|
}
|
|
107
|
-
})
|
|
177
|
+
})
|
|
178
|
+
if (!isComplete) tableTitle = tableTitle.filter(item => item.prop)
|
|
108
179
|
return tableTitle
|
|
109
180
|
}
|
|
110
181
|
|
|
@@ -175,30 +246,124 @@ const emit = defineEmits<{
|
|
|
175
246
|
/** expandProp模式下 当用户对某一行展开或者关闭的时候会触发该事件 */
|
|
176
247
|
privateExpandChange: [row: any, expandedRows: any[]];
|
|
177
248
|
/** 选中单元格更新 */
|
|
178
|
-
'update:selectionCell': [string];
|
|
249
|
+
'update:selectionCell': [ string | number | symbol ];
|
|
250
|
+
/** 复制事件 */
|
|
251
|
+
copyData: [ data: { text: string, selection: { startX: number, startY: number, endX: number, endY: number } } ];
|
|
179
252
|
}>()
|
|
180
253
|
|
|
181
|
-
interface
|
|
182
|
-
/**
|
|
183
|
-
|
|
184
|
-
/**
|
|
185
|
-
|
|
186
|
-
/**
|
|
187
|
-
|
|
254
|
+
interface SelectionAreaType {
|
|
255
|
+
/** 开始x */
|
|
256
|
+
startX: number | null;
|
|
257
|
+
/** 开始Y */
|
|
258
|
+
startY: number | null;
|
|
259
|
+
/** 结束x */
|
|
260
|
+
endX: number | null;
|
|
261
|
+
/** 结束Y */
|
|
262
|
+
endY: number | null;
|
|
263
|
+
/** 圈选中 */
|
|
264
|
+
isInProgress: boolean;
|
|
188
265
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
266
|
+
/** 选中区域 */
|
|
267
|
+
const selectionArea: SelectionAreaType = reactive<SelectionAreaType>({
|
|
268
|
+
/** 开始x */
|
|
269
|
+
startX: null,
|
|
270
|
+
/** 开始Y */
|
|
271
|
+
startY: null,
|
|
272
|
+
/** 结束x */
|
|
273
|
+
endX: null,
|
|
274
|
+
/** 结束Y */
|
|
275
|
+
endY: null,
|
|
276
|
+
/** 圈选中 */
|
|
277
|
+
isInProgress: false
|
|
193
278
|
})
|
|
194
279
|
const cellStyle = (data: { row: any, column: any, rowIndex: number, columnIndex: number }): Record<string, any> => {
|
|
195
|
-
if (
|
|
196
|
-
|
|
197
|
-
|
|
280
|
+
if (selectionArea.startX === null || selectionArea.startY === null || selectionArea.endX === null || selectionArea.endY === null) return {}
|
|
281
|
+
const startX = selectionArea.startX > selectionArea.endX ? selectionArea.endX : selectionArea.startX
|
|
282
|
+
const startY = selectionArea.startY > selectionArea.endY ? selectionArea.endY : selectionArea.startY
|
|
283
|
+
const endX = selectionArea.startX > selectionArea.endX ? selectionArea.startX : selectionArea.endX
|
|
284
|
+
const endY = selectionArea.startY > selectionArea.endY ? selectionArea.startY : selectionArea.endY
|
|
285
|
+
if (data.columnIndex < startX || data.columnIndex > endX) return {}
|
|
286
|
+
if (data.rowIndex < startY || data.rowIndex > endY) return {}
|
|
198
287
|
return {
|
|
199
288
|
backgroundColor: 'var(--el-color-primary-light-9)'
|
|
200
289
|
}
|
|
201
290
|
}
|
|
291
|
+
const cellMouseEnter = (row: any, column: any, cell: HTMLTableCellElement) => {
|
|
292
|
+
if (!selectionArea.isInProgress) return
|
|
293
|
+
|
|
294
|
+
const tr = cell.parentElement
|
|
295
|
+
if (!tr) return
|
|
296
|
+
const parent = tr.parentNode
|
|
297
|
+
if (!parent) return
|
|
298
|
+
const rowIndex = Array.from(parent.children).indexOf(tr)
|
|
299
|
+
|
|
300
|
+
selectionArea.endX = cell.cellIndex
|
|
301
|
+
selectionArea.endY = rowIndex
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
const taskUpKey = 'MTable-onmouseup-' + createHash()
|
|
305
|
+
globalEvents().register({
|
|
306
|
+
id: taskUpKey,
|
|
307
|
+
eventName: 'onmouseup',
|
|
308
|
+
callback: () => {
|
|
309
|
+
selectionArea.isInProgress = false
|
|
310
|
+
}
|
|
311
|
+
})
|
|
312
|
+
onUnmounted(() => {
|
|
313
|
+
globalEvents().unregister(taskUpKey)
|
|
314
|
+
})
|
|
315
|
+
const taskDownKey = 'MTable-onmousedown-' + createHash()
|
|
316
|
+
globalEvents().register({
|
|
317
|
+
id: taskDownKey,
|
|
318
|
+
eventName: 'onmousedown',
|
|
319
|
+
callback: () => {
|
|
320
|
+
selectionArea.isInProgress = false
|
|
321
|
+
selectionArea.startX = null
|
|
322
|
+
selectionArea.startY = null
|
|
323
|
+
selectionArea.endX = null
|
|
324
|
+
selectionArea.endY = null
|
|
325
|
+
}
|
|
326
|
+
})
|
|
327
|
+
onUnmounted(() => {
|
|
328
|
+
globalEvents().unregister(taskDownKey)
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
watch(
|
|
332
|
+
() => [selectionArea.startX, selectionArea.endX],
|
|
333
|
+
() => {
|
|
334
|
+
let prop: string | number | symbol = ''
|
|
335
|
+
if (selectionArea.startX === selectionArea.endX && selectionArea.startX !== null && selectionArea.endX !== null) {
|
|
336
|
+
const tableTitle = getTableTitle(true)
|
|
337
|
+
prop = (tableTitle[selectionArea.startX] ?? {})?.prop ?? ''
|
|
338
|
+
}
|
|
339
|
+
selectionCell.value = prop
|
|
340
|
+
emit('update:selectionCell', prop)
|
|
341
|
+
}
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
/** 复制内容到粘贴板 */
|
|
345
|
+
const copyTextToClipboard = async (text: string) => {
|
|
346
|
+
const textarea = document.createElement('textarea')
|
|
347
|
+
textarea.value = text
|
|
348
|
+
|
|
349
|
+
textarea.style.position = 'fixed'
|
|
350
|
+
textarea.style.opacity = '0'
|
|
351
|
+
textarea.style.pointerEvents = 'none'
|
|
352
|
+
|
|
353
|
+
document.body.appendChild(textarea)
|
|
354
|
+
textarea.select()
|
|
355
|
+
textarea.setSelectionRange(0, textarea.value.length)
|
|
356
|
+
|
|
357
|
+
let success = false
|
|
358
|
+
try {
|
|
359
|
+
success = document.execCommand('copy')
|
|
360
|
+
} catch (err) {
|
|
361
|
+
console.error('复制失败:', err)
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
document.body.removeChild(textarea)
|
|
365
|
+
return success
|
|
366
|
+
}
|
|
202
367
|
|
|
203
368
|
const privateExpandChange = (index: number) => {
|
|
204
369
|
const row = tableData.value[index]
|
|
@@ -257,15 +422,16 @@ const cellClick = (row: any, column: { property: string; }, cell: any) => {
|
|
|
257
422
|
elDom.value?.addEventListener('paste', disablePasteEvent)
|
|
258
423
|
}
|
|
259
424
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
425
|
+
if (!selectionArea.isInProgress) {
|
|
426
|
+
const tr = cell.parentElement
|
|
427
|
+
if (!tr) return
|
|
428
|
+
const parent = tr.parentNode
|
|
429
|
+
const rowIndex = Array.from(parent.children).indexOf(tr)
|
|
430
|
+
selectionArea.startX = cell.cellIndex
|
|
431
|
+
selectionArea.startY = rowIndex
|
|
432
|
+
selectionArea.endX = cell.cellIndex
|
|
433
|
+
selectionArea.endY = rowIndex
|
|
434
|
+
}
|
|
269
435
|
}
|
|
270
436
|
const instance = getCurrentInstance()
|
|
271
437
|
const disablePasteEvent = (e: { preventDefault: () => void; }) => {
|
|
@@ -353,7 +519,9 @@ provide(tableKey, {
|
|
|
353
519
|
rowKey: props.rowKey,
|
|
354
520
|
tableConfigKey: props.tableConfigKey,
|
|
355
521
|
privateExpandChange,
|
|
356
|
-
showFilter: Boolean(props.filtersValue)
|
|
522
|
+
showFilter: Boolean(props.filtersValue),
|
|
523
|
+
/** 选中区域 */
|
|
524
|
+
selectionArea
|
|
357
525
|
})
|
|
358
526
|
|
|
359
527
|
defineExpose({
|
|
@@ -372,6 +540,54 @@ defineExpose({
|
|
|
372
540
|
setScrollLeft: (left: number) => tableRef.value?.setScrollLeft(left),
|
|
373
541
|
getTableTitle
|
|
374
542
|
})
|
|
543
|
+
|
|
544
|
+
/** 选中的单元格 */
|
|
545
|
+
const selectionCell = ref<string | number | symbol>(props.selectionCell)
|
|
546
|
+
watch(
|
|
547
|
+
() => props.selectionCell,
|
|
548
|
+
() => {
|
|
549
|
+
selectionCell.value = props.selectionCell
|
|
550
|
+
}
|
|
551
|
+
)
|
|
552
|
+
|
|
553
|
+
/** 表格单元格复制 */
|
|
554
|
+
const buildCopyText = (): string => {
|
|
555
|
+
if (selectionArea.startX === null || selectionArea.startY === null || selectionArea.endX === null || selectionArea.endY === null) return ''
|
|
556
|
+
const startX = selectionArea.startX < selectionArea.endX ? selectionArea.startX : selectionArea.endX
|
|
557
|
+
const startY = selectionArea.startY < selectionArea.endY ? selectionArea.startY : selectionArea.endY
|
|
558
|
+
const endX = selectionArea.startX > selectionArea.endX ? selectionArea.startX : selectionArea.endX
|
|
559
|
+
const endY = selectionArea.startY > selectionArea.endY ? selectionArea.startY : selectionArea.endY
|
|
560
|
+
const tableTitle = getTableTitle(true)
|
|
561
|
+
const copyColKey: (string | number | symbol)[] = []
|
|
562
|
+
for (let i = startX; i < endX + 1; i++) {
|
|
563
|
+
copyColKey.push(tableTitle[i].prop)
|
|
564
|
+
}
|
|
565
|
+
const text: any[] = []
|
|
566
|
+
for (let i = startY; i < endY; i++) {
|
|
567
|
+
const row: any[] = []
|
|
568
|
+
copyColKey.forEach(key => {
|
|
569
|
+
row.push(props.data[i][key as string])
|
|
570
|
+
})
|
|
571
|
+
text.push(row.join('\t'))
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
return text.join('\n')
|
|
575
|
+
}
|
|
576
|
+
const onKeydown = async (e: KeyboardEvent) => {
|
|
577
|
+
if (!((e.ctrlKey || e.metaKey) && String(e.key).toLowerCase() === 'c')) return
|
|
578
|
+
const text = buildCopyText()
|
|
579
|
+
if (!text) return
|
|
580
|
+
await copyTextToClipboard(text)
|
|
581
|
+
emit('copyData', {
|
|
582
|
+
text,
|
|
583
|
+
selection: {
|
|
584
|
+
startX: selectionArea.startX as number,
|
|
585
|
+
startY: selectionArea.startY as number,
|
|
586
|
+
endX: selectionArea.endX as number,
|
|
587
|
+
endY: selectionArea.endY as number
|
|
588
|
+
}
|
|
589
|
+
})
|
|
590
|
+
}
|
|
375
591
|
</script>
|
|
376
592
|
|
|
377
593
|
<style scoped lang="scss">
|
|
@@ -20,5 +20,18 @@ export const tableKey: InjectionKey<{
|
|
|
20
20
|
/** expandProp模式下 当用户对某一行展开或者关闭的时候会触发 */
|
|
21
21
|
privateExpandChange: Function,
|
|
22
22
|
/** 是否显示筛选图标 */
|
|
23
|
-
showFilter: boolean
|
|
23
|
+
showFilter: boolean,
|
|
24
|
+
/** 选中区域 */
|
|
25
|
+
selectionArea: {
|
|
26
|
+
/** 开始x */
|
|
27
|
+
startX: number | null;
|
|
28
|
+
/** 开始Y */
|
|
29
|
+
startY: number | null;
|
|
30
|
+
/** 结束x */
|
|
31
|
+
endX: number | null;
|
|
32
|
+
/** 结束Y */
|
|
33
|
+
endY: number | null;
|
|
34
|
+
/** 圈选中 */
|
|
35
|
+
isInProgress: boolean;
|
|
36
|
+
}
|
|
24
37
|
}> = Symbol('tableKey')
|
|
@@ -19,4 +19,5 @@ import demo from './demo.vue'
|
|
|
19
19
|
| filters | 表格筛选数据 | string[],number[] | - | any[] |
|
|
20
20
|
| filterMethod | 筛选方法 | Function | - | () => void |
|
|
21
21
|
| children | 多级表头 时使用传递对应数据进行循环 | Table-column API[] | - | [] |
|
|
22
|
+
| isBatchEdit | 是否允许批改 | boolean | - | false |
|
|
22
23
|
| 其余参数 | 参考el官网的table | any | - | https://element-plus.org/zh-CN/component/table.html |
|
|
@@ -9,12 +9,30 @@
|
|
|
9
9
|
>
|
|
10
10
|
<slot
|
|
11
11
|
name="default"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
v-bind="{
|
|
13
|
+
index: scope.$index,
|
|
14
|
+
...scope
|
|
15
|
+
}"
|
|
16
16
|
></slot>
|
|
17
17
|
</template>
|
|
18
|
+
<template
|
|
19
|
+
#default="scope"
|
|
20
|
+
v-if="!slots.default"
|
|
21
|
+
>
|
|
22
|
+
<div
|
|
23
|
+
class="u-my-table-column-text"
|
|
24
|
+
@mousedown="mousedown($event, scope.cellIndex, scope.$index)"
|
|
25
|
+
>
|
|
26
|
+
{{ columnData[scope.$index] }}
|
|
27
|
+
<slot
|
|
28
|
+
name="default"
|
|
29
|
+
v-bind="{
|
|
30
|
+
index: scope.$index,
|
|
31
|
+
...scope
|
|
32
|
+
}"
|
|
33
|
+
></slot>
|
|
34
|
+
</div>
|
|
35
|
+
</template>
|
|
18
36
|
|
|
19
37
|
<!--展开行开始-->
|
|
20
38
|
<template
|
|
@@ -32,10 +50,10 @@
|
|
|
32
50
|
</el-icon>
|
|
33
51
|
<slot
|
|
34
52
|
name="default"
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
53
|
+
v-bind="{
|
|
54
|
+
index: scope.$index,
|
|
55
|
+
...scope
|
|
56
|
+
}"
|
|
39
57
|
></slot>
|
|
40
58
|
</div>
|
|
41
59
|
</template>
|
|
@@ -57,8 +75,9 @@
|
|
|
57
75
|
</template>
|
|
58
76
|
<!--展开行结束-->
|
|
59
77
|
|
|
78
|
+
<!--子行开始-->
|
|
60
79
|
<template v-if="props.children && props.children.length">
|
|
61
|
-
<
|
|
80
|
+
<MTableColumn
|
|
62
81
|
v-for="child in props.children"
|
|
63
82
|
:key="child.prop"
|
|
64
83
|
:prop="child.prop"
|
|
@@ -66,16 +85,20 @@
|
|
|
66
85
|
:minWidth="child.minWidth"
|
|
67
86
|
showOverflowTooltip
|
|
68
87
|
:children="child.children || []"
|
|
69
|
-
|
|
88
|
+
:isBatchEdit="child.isBatchEdit"
|
|
89
|
+
></MTableColumn>
|
|
70
90
|
</template>
|
|
91
|
+
<!--子行结束-->
|
|
92
|
+
|
|
93
|
+
<!--表格配置开始-->
|
|
71
94
|
<template #header="scope">
|
|
72
95
|
<span>
|
|
73
96
|
<slot
|
|
74
97
|
name="header"
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
98
|
+
v-bind="{
|
|
99
|
+
index: scope.$index,
|
|
100
|
+
...scope
|
|
101
|
+
}"
|
|
79
102
|
></slot>
|
|
80
103
|
<span>
|
|
81
104
|
<span v-if="!slots.header">{{ scope.column.label }}</span>
|
|
@@ -134,15 +157,16 @@
|
|
|
134
157
|
<el-checkbox
|
|
135
158
|
v-for="item in getCheckboxOptions(props.filters)"
|
|
136
159
|
:key="item.value"
|
|
137
|
-
:
|
|
160
|
+
:value="item.value"
|
|
138
161
|
>
|
|
139
162
|
<template v-if="slots.default">
|
|
140
163
|
<slot
|
|
141
164
|
name="default"
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
165
|
+
v-bind="{
|
|
166
|
+
index: scope.$index,
|
|
167
|
+
...scope,
|
|
168
|
+
row: { [scope.column.property]: item.text }
|
|
169
|
+
}"
|
|
146
170
|
></slot>
|
|
147
171
|
</template>
|
|
148
172
|
<template v-if="!slots.default">{{ item.text }}</template>
|
|
@@ -177,6 +201,7 @@
|
|
|
177
201
|
</span>
|
|
178
202
|
</span>
|
|
179
203
|
</template>
|
|
204
|
+
<!--表格配置开始-->
|
|
180
205
|
</el-table-column>
|
|
181
206
|
</template>
|
|
182
207
|
|
|
@@ -185,6 +210,8 @@ import { ref, useSlots, useAttrs, inject, computed } from 'vue'
|
|
|
185
210
|
import checkType from '../../Tool/checkType/checkType'
|
|
186
211
|
import { tableKey } from './../../MTable/src/token'
|
|
187
212
|
import { useZIndex } from 'element-plus'
|
|
213
|
+
import { MTableColumn } from 'packages/MTableColumn'
|
|
214
|
+
import { ArrowRight } from '@element-plus/icons-vue'
|
|
188
215
|
|
|
189
216
|
interface FilterValue {
|
|
190
217
|
[key: string]: Array<string | number>
|
|
@@ -197,17 +224,20 @@ interface PropChildren {
|
|
|
197
224
|
|
|
198
225
|
const props = withDefaults(defineProps<{
|
|
199
226
|
/** 列筛选过滤条件(当为null时,不显示筛选图标) */
|
|
200
|
-
filtersValue?: FilterValue | null
|
|
227
|
+
filtersValue?: FilterValue | null;
|
|
201
228
|
/** 过滤选项 */
|
|
202
|
-
filters?: Array<{ text: string | number, value: string | number }
|
|
229
|
+
filters?: Array<{ text: string | number, value: string | number }>;
|
|
203
230
|
/** 过滤方法 */
|
|
204
|
-
filterMethod?: Function | null
|
|
205
|
-
children?: Array<PropChildren
|
|
231
|
+
filterMethod?: Function | null;
|
|
232
|
+
children?: Array<PropChildren>;
|
|
233
|
+
/** 是否允许批改 */
|
|
234
|
+
isBatchEdit?: boolean;
|
|
206
235
|
}>(), {
|
|
207
236
|
filtersValue: null,
|
|
208
237
|
filters: () => [],
|
|
209
238
|
filterMethod: null,
|
|
210
|
-
children: () => []
|
|
239
|
+
children: () => [],
|
|
240
|
+
isBatchEdit: false
|
|
211
241
|
})
|
|
212
242
|
|
|
213
243
|
const slots = useSlots()
|
|
@@ -350,6 +380,17 @@ const boxStyle = ref<BoxStyle>({
|
|
|
350
380
|
right: 'unset',
|
|
351
381
|
zIndex: thisZIndex
|
|
352
382
|
})
|
|
383
|
+
|
|
384
|
+
// 选中区域
|
|
385
|
+
const selectionArea = tableKeyData?.selectionArea ?? { startX: null, startY: null, endX: null, endY: null, isInProgress: false }
|
|
386
|
+
const mousedown = (event: Event, x: number, y: number) => {
|
|
387
|
+
selectionArea.isInProgress = true
|
|
388
|
+
selectionArea.startX = x
|
|
389
|
+
selectionArea.startY = y
|
|
390
|
+
selectionArea.endX = null
|
|
391
|
+
selectionArea.endY = null
|
|
392
|
+
event.stopPropagation()
|
|
393
|
+
}
|
|
353
394
|
</script>
|
|
354
395
|
|
|
355
396
|
<style scoped lang="scss">
|
|
@@ -388,6 +429,15 @@ const boxStyle = ref<BoxStyle>({
|
|
|
388
429
|
transform: rotate(90deg);
|
|
389
430
|
}
|
|
390
431
|
}
|
|
432
|
+
|
|
433
|
+
.u-my-table-column-text {
|
|
434
|
+
overflow: hidden;
|
|
435
|
+
display: block;
|
|
436
|
+
overflow-wrap: break-word;
|
|
437
|
+
text-overflow: ellipsis;
|
|
438
|
+
white-space: nowrap;
|
|
439
|
+
user-select: none;
|
|
440
|
+
}
|
|
391
441
|
</style>
|
|
392
442
|
|
|
393
443
|
<style lang="scss">
|
|
@@ -471,4 +521,28 @@ const boxStyle = ref<BoxStyle>({
|
|
|
471
521
|
.filter-i {
|
|
472
522
|
background-color: var(--el-color-primary);
|
|
473
523
|
}
|
|
524
|
+
|
|
525
|
+
.br-m-table-box {
|
|
526
|
+
.el-table__body-wrapper {
|
|
527
|
+
.el-table .el-table__cell {
|
|
528
|
+
padding-top: 0;
|
|
529
|
+
padding-bottom: 0;
|
|
530
|
+
|
|
531
|
+
.u-my-table-column-text {
|
|
532
|
+
padding-top: 8px;
|
|
533
|
+
padding-bottom: 8px;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
.el-table .cell {
|
|
538
|
+
padding-left: 0;
|
|
539
|
+
padding-right: 0;
|
|
540
|
+
|
|
541
|
+
.u-my-table-column-text {
|
|
542
|
+
padding-left: 12px;
|
|
543
|
+
padding-right: 12px;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
474
548
|
</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
## 全局事件代理 globalEvents
|
|
2
|
+
|
|
3
|
+
### 1) 参数
|
|
4
|
+
|
|
5
|
+
| 参数 | 描述 | 类型 | 默认值 |
|
|
6
|
+
|-------|--------------------------|--------|--------|
|
|
7
|
+
| point | 锚点(绑定事件的dom节点的class,id等) | string | 'body' |
|
|
8
|
+
|
|
9
|
+
### 2) 返参
|
|
10
|
+
|
|
11
|
+
| 参数 | 描述 | 类型 | 默认值 |
|
|
12
|
+
|------------|----------------------------|--------------------------------------|-----|
|
|
13
|
+
| register | 注册行为 | (options: EventRegistration) => void | - |
|
|
14
|
+
| unregister | 注销行为(id存在即注销对应行为,不存在即注销所有) | (id?: string \| number) => void | - |
|
|
15
|
+
|
|
16
|
+
#### 2.1) EventRegistration
|
|
17
|
+
|
|
18
|
+
| 参数 | 描述 | 类型 | 默认值 |
|
|
19
|
+
|-----------|------------------|--------------------|-----|
|
|
20
|
+
| eventName | 事件类型 | GlobalEventName | - |
|
|
21
|
+
| id | 唯一标识符 | string \| number | - |
|
|
22
|
+
| callback | 事件回调 | (event: T) => void | - |
|
|
23
|
+
| priority | 事件优先级(数字越小优先级越高) | number | - |
|