niuma-ui 1.0.0 → 1.0.2
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/CHANGELOG.md +50 -1
- package/NOTICE +2 -2
- package/package.json +13 -5
- package/src/__tests__/RsButton.spec.ts +47 -0
- package/src/__tests__/RsCard.spec.ts +160 -1
- package/src/__tests__/RsConfirmDialog.spec.ts +127 -0
- package/src/__tests__/RsContextMenu.spec.ts +12 -0
- package/src/__tests__/RsDateTimePicker.spec.ts +11 -0
- package/src/__tests__/RsDescriptions.spec.ts +50 -0
- package/src/__tests__/RsDialog.spec.ts +117 -0
- package/src/__tests__/RsDrawer.spec.ts +96 -3
- package/src/__tests__/RsDynamicTags.spec.ts +52 -0
- package/src/__tests__/RsForm.spec.ts +245 -1
- package/src/__tests__/RsInput.spec.ts +15 -1
- package/src/__tests__/RsMenu.spec.ts +406 -14
- package/src/__tests__/RsPagination.spec.ts +67 -2
- package/src/__tests__/RsSelect.spec.ts +42 -1
- package/src/__tests__/RsSwitch.spec.ts +44 -0
- package/src/__tests__/RsTable.a11y.spec.ts +83 -0
- package/src/__tests__/RsTable.dom-baseline.spec.ts +87 -0
- package/src/__tests__/RsTable.perf.spec.ts +23 -4
- package/src/__tests__/RsTable.spec.ts +63 -8
- package/src/__tests__/RsTable.ssr.spec.ts +71 -0
- package/src/__tests__/RsTable.summary.spec.ts +45 -0
- package/src/__tests__/RsTabs.spec.ts +102 -4
- package/src/__tests__/RsTerminal.spec.ts +1 -1
- package/src/__tests__/RsTimePicker.spec.ts +11 -0
- package/src/__tests__/RsUpload.spec.ts +62 -6
- package/src/__tests__/createRsDialog.spec.ts +145 -0
- package/src/__tests__/form-rules.spec.ts +76 -0
- package/src/__tests__/perf-budgets.ts +32 -0
- package/src/__tests__/rs-table-api.spec.ts +206 -0
- package/src/__tests__/rs-table-compat-matrix.spec.ts +108 -0
- package/src/__tests__/rs-table-echarts-adapter.spec.ts +43 -0
- package/src/__tests__/rs-table-grid-nav.spec.ts +63 -0
- package/src/__tests__/rs-table-isolation.spec.ts +158 -0
- package/src/__tests__/split-pane-utils.spec.ts +21 -0
- package/src/__tests__/table-chart-utils.spec.ts +88 -0
- package/src/__tests__/table-summary-utils.spec.ts +62 -0
- package/src/__tests__/table-utils.spec.ts +124 -0
- package/src/__tests__/theme.spec.ts +25 -0
- package/src/__tests__/useRsTableColumnResize.spec.ts +25 -0
- package/src/__tests__/useRsTableCore.perf.spec.ts +170 -0
- package/src/components/RsAlert.vue +212 -0
- package/src/components/RsButton.vue +145 -21
- package/src/components/RsCard.vue +200 -16
- package/src/components/RsConfirmDialog.vue +215 -28
- package/src/components/RsContextMenu.vue +51 -13
- package/src/components/RsDatePicker.vue +267 -34
- package/src/components/RsDateTimePicker.vue +19 -2
- package/src/components/RsDescriptions.vue +186 -0
- package/src/components/RsDescriptionsItem.vue +32 -0
- package/src/components/RsDialog.vue +363 -51
- package/src/components/RsDivider.vue +89 -0
- package/src/components/RsDrawer.vue +558 -33
- package/src/components/RsDropdown.vue +33 -2
- package/src/components/RsDynamicTags.vue +517 -0
- package/src/components/RsForm.vue +97 -8
- package/src/components/RsInput.vue +80 -82
- package/src/components/RsInputNumber.vue +64 -23
- package/src/components/RsLabel.vue +20 -5
- package/src/components/RsLoadingBar.vue +151 -0
- package/src/components/RsMenu.vue +73 -15
- package/src/components/RsMenuItems.vue +147 -9
- package/src/components/RsPagination.vue +93 -14
- package/src/components/RsRadio.vue +81 -0
- package/src/components/RsRadioItem.vue +156 -0
- package/src/components/RsSelect.vue +67 -58
- package/src/components/RsSplitPane.vue +69 -1
- package/src/components/RsSwitch.vue +179 -0
- package/src/components/RsTable.vue +653 -2555
- package/src/components/RsTabs.vue +415 -83
- package/src/components/RsTag.vue +191 -0
- package/src/components/RsTerminal.vue +3 -3
- package/src/components/RsTimePicker.vue +44 -5
- package/src/components/RsTimePickerColumns.vue +136 -77
- package/src/components/RsToaster.vue +58 -18
- package/src/components/RsTree.vue +39 -21
- package/src/components/RsUpload.vue +145 -12
- package/src/components/RsVNodeHost.vue +20 -0
- package/src/components/button-utils.ts +39 -0
- package/src/components/context-menu-utils.ts +6 -0
- package/src/components/date-picker-utils.ts +84 -4
- package/src/components/descriptions-utils.ts +24 -0
- package/src/components/dialog-utils.ts +147 -0
- package/src/components/dialog-window.ts +74 -9
- package/src/components/drawer-utils.ts +73 -0
- package/src/components/form-rules.ts +257 -0
- package/src/components/form-utils.ts +52 -2
- package/src/components/menu-utils.ts +11 -0
- package/src/components/overlay-utils.ts +3 -0
- package/src/components/radio-utils.ts +12 -0
- package/src/components/reka.ts +5 -0
- package/src/components/select-utils.ts +21 -2
- package/src/components/split-pane-utils.ts +65 -12
- package/src/components/table/RsTableBody.vue +217 -0
- package/src/components/table/RsTableBodyRow.vue +90 -1
- package/src/components/table/RsTableColGroup.vue +41 -0
- package/src/components/table/RsTableHeader.vue +158 -0
- package/src/components/table/RsTableSummaryRow.vue +52 -0
- package/src/components/table/rs-table-api.ts +99 -0
- package/src/components/table/rs-table-compat-matrix.ts +71 -0
- package/src/components/table/rs-table-echarts-adapter.ts +81 -0
- package/src/components/table/rs-table-feature-host.ts +178 -0
- package/src/components/table/rs-table-grid-nav.ts +122 -0
- package/src/components/table/rs-table-header-types.ts +47 -0
- package/src/components/table/rs-table-module-registry.ts +72 -0
- package/src/components/table/rs-table-props.ts +274 -0
- package/src/components/table/rs-table-view-context.ts +258 -0
- package/src/components/table/rs-table.css +84 -6
- package/src/components/table/table-chart-utils.ts +165 -0
- package/src/components/table/table-features.ts +284 -0
- package/src/components/table/table-summary-utils.ts +194 -0
- package/src/components/table-utils.ts +452 -2
- package/src/components/tabs-utils.ts +142 -2
- package/src/components/terminal-utils.ts +1 -1
- package/src/components/terminal-wheel.ts +1 -1
- package/src/components/time-picker-utils.ts +76 -3
- package/src/components/upload-utils.ts +122 -0
- package/src/components/virtual-list-utils.ts +15 -2
- package/src/composables/assembleRsTableApi.ts +79 -0
- package/src/composables/bindRsTableViewContext.ts +269 -0
- package/src/composables/createRsDialog.ts +357 -0
- package/src/composables/createRsTableEditEmitBridge.ts +38 -0
- package/src/composables/useRsLoadingBar.ts +36 -0
- package/src/composables/useRsTable.ts +134 -0
- package/src/composables/useRsTableA11y.ts +52 -0
- package/src/composables/useRsTableChartBridge.ts +79 -0
- package/src/composables/useRsTableColumnLayout.ts +320 -0
- package/src/composables/useRsTableColumnResize.ts +244 -0
- package/src/composables/useRsTableColumnVirtual.ts +180 -0
- package/src/composables/useRsTableColumns.ts +200 -0
- package/src/composables/useRsTableContextMenu.ts +257 -0
- package/src/composables/useRsTableCore.ts +256 -0
- package/src/composables/useRsTableEditActions.ts +606 -0
- package/src/composables/useRsTableEditLayer.ts +251 -0
- package/src/composables/useRsTableEngine.ts +357 -0
- package/src/composables/useRsTableGridKeyboard.ts +123 -0
- package/src/composables/useRsTableHeadless.ts +137 -0
- package/src/composables/useRsTableInteraction.ts +433 -0
- package/src/composables/useRsTableScrollHost.ts +75 -0
- package/src/composables/useRsTableScrollLayout.ts +255 -0
- package/src/composables/useRsTableSelectionSource.ts +89 -0
- package/src/composables/useRsTableShell.ts +416 -0
- package/src/composables/useRsTableShellChrome.ts +170 -0
- package/src/composables/useRsTableSummary.ts +113 -0
- package/src/composables/useRsTableViewProvide.ts +263 -0
- package/src/composables/useRsTableVirtual.ts +154 -0
- package/src/composables/useRsTabsNav.ts +4 -0
- package/src/composables/useTableEdit.ts +1 -1
- package/src/icons/lucide.ts +2 -2
- package/src/index.ts +309 -9
- package/src/locale/messages.ts +30 -0
- package/src/styles.css +305 -52
- package/src/theme/brand.example.css +21 -2
- package/src/theme/presets.ts +4 -0
- package/src/theme/types.ts +67 -0
- package/src/components/RsTableColgroup.vue +0 -17
- package/src/components/RsTableHeaderRow.vue +0 -30
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RsTable 壳层装配:前缀列几何 + 列宽/列虚拟/列布局 + 交互 + 右键菜单。
|
|
3
|
+
*
|
|
4
|
+
* 性能约定(不可破):
|
|
5
|
+
* - 列宽拖拽仍走 useRsTableColumnResize 的 DOM 直写(禁止拖拽中写 reactive 全表宽)
|
|
6
|
+
* - columnVirtual 在 isColumnResizing 时冻结切片,避免拖宽时重算窗口
|
|
7
|
+
* - 不引入对 data 的 deep watch;状态经 getter / 受控 ref 读写
|
|
8
|
+
*
|
|
9
|
+
* 不做:Engine/Virtual 行切片(useRsTableCore)、编辑提交(useRsTableEditActions)、模板。
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { computed, type ComputedRef, type Ref } from 'vue'
|
|
13
|
+
import type { RsContextMenuItem } from '../components/context-menu-utils'
|
|
14
|
+
import type { RsTableRowDragTrigger, RsTableRowDropMode } from '../components/table-drag'
|
|
15
|
+
import type {
|
|
16
|
+
RsTableColumn,
|
|
17
|
+
RsTableRowData,
|
|
18
|
+
RsTableRowEntry,
|
|
19
|
+
RsTableRowKey,
|
|
20
|
+
RsTableSelectionType,
|
|
21
|
+
RsTableSortState,
|
|
22
|
+
RsTableTreeConfig,
|
|
23
|
+
RsTableTreeNodeIndex,
|
|
24
|
+
RsTableRowDropPosition,
|
|
25
|
+
} from '../components/table-utils'
|
|
26
|
+
import { resolveScrollWidth, selectRowKeys } from '../components/table-utils'
|
|
27
|
+
import {
|
|
28
|
+
measureRsTablePrefixWidth,
|
|
29
|
+
RS_TABLE_PREFIX_COL_WIDTH,
|
|
30
|
+
useRsTableColumnVirtual,
|
|
31
|
+
} from './useRsTableColumnVirtual'
|
|
32
|
+
import { useRsTableColumnLayout } from './useRsTableColumnLayout'
|
|
33
|
+
import { useRsTableColumnResize } from './useRsTableColumnResize'
|
|
34
|
+
import { useRsTableContextMenu } from './useRsTableContextMenu'
|
|
35
|
+
import { useRsTableInteraction } from './useRsTableInteraction'
|
|
36
|
+
import { resolveVirtualListHeight } from '../components/virtual-list-utils'
|
|
37
|
+
|
|
38
|
+
/** 壳层依赖的 Core 状态切片(显式列出,避免吞整个 core) */
|
|
39
|
+
export interface UseRsTableShellCoreSlice<T extends RsTableRowData> {
|
|
40
|
+
displayColumns: ComputedRef<RsTableColumn<T>[]>
|
|
41
|
+
resolvedColumnWidths: {
|
|
42
|
+
get: () => Record<string, number>
|
|
43
|
+
set: (value: Record<string, number>) => void
|
|
44
|
+
} | Ref<Record<string, number>>
|
|
45
|
+
useStableColumnWidths: ComputedRef<boolean>
|
|
46
|
+
scrollLeft: Ref<number>
|
|
47
|
+
measuredViewportWidth: Ref<number>
|
|
48
|
+
virtualScrollEnabled: ComputedRef<boolean>
|
|
49
|
+
dataRows: ComputedRef<Array<Extract<RsTableRowEntry<T>, { type: 'row' }>>>
|
|
50
|
+
selectedRows: ComputedRef<T[]>
|
|
51
|
+
rowKeyByIndex: ComputedRef<Map<number, string>>
|
|
52
|
+
selectedRowKeys: {
|
|
53
|
+
get: () => string[]
|
|
54
|
+
set: (keys: string[]) => void
|
|
55
|
+
} | Ref<string[]>
|
|
56
|
+
selectedKeySet: ComputedRef<Set<string>>
|
|
57
|
+
selectableRowKeys: ComputedRef<string[]>
|
|
58
|
+
selectAllState: ComputedRef<'checked' | 'indeterminate' | 'unchecked'>
|
|
59
|
+
expandedRowKeys: {
|
|
60
|
+
get: () => string[]
|
|
61
|
+
set: (keys: string[]) => void
|
|
62
|
+
} | Ref<string[]>
|
|
63
|
+
expandedKeySet: ComputedRef<Set<string>>
|
|
64
|
+
detailExpandable: ComputedRef<boolean>
|
|
65
|
+
treeMode: ComputedRef<boolean>
|
|
66
|
+
treeCheckStrictly: ComputedRef<boolean>
|
|
67
|
+
treeLazy: ComputedRef<boolean>
|
|
68
|
+
treeChildrenField: ComputedRef<string>
|
|
69
|
+
treeIsLeafField: ComputedRef<string>
|
|
70
|
+
treeLoadingKeys: {
|
|
71
|
+
get: () => string[]
|
|
72
|
+
set: (keys: string[]) => void
|
|
73
|
+
} | Ref<string[]>
|
|
74
|
+
treeLoadingKeySet: ComputedRef<Set<string>>
|
|
75
|
+
tableTreeNodeIndex: ComputedRef<Map<string, RsTableTreeNodeIndex> | null>
|
|
76
|
+
sortState: {
|
|
77
|
+
get: () => RsTableSortState | null
|
|
78
|
+
set: (value: RsTableSortState | null) => void
|
|
79
|
+
} | Ref<RsTableSortState | null>
|
|
80
|
+
sortsState: {
|
|
81
|
+
get: () => RsTableSortState[]
|
|
82
|
+
set: (value: RsTableSortState[]) => void
|
|
83
|
+
} | Ref<RsTableSortState[]>
|
|
84
|
+
columnOrderState: {
|
|
85
|
+
get: () => string[]
|
|
86
|
+
set: (value: string[]) => void
|
|
87
|
+
} | Ref<string[]>
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function asAccessor<T>(source: { get: () => T; set: (v: T) => void } | Ref<T>): {
|
|
91
|
+
get: () => T
|
|
92
|
+
set: (v: T) => void
|
|
93
|
+
} {
|
|
94
|
+
if ('get' in source && typeof source.get === 'function') return source
|
|
95
|
+
const r = source as Ref<T>
|
|
96
|
+
return {
|
|
97
|
+
get: () => r.value,
|
|
98
|
+
set: (v) => {
|
|
99
|
+
r.value = v
|
|
100
|
+
},
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface UseRsTableShellOptions<T extends RsTableRowData> {
|
|
105
|
+
core: UseRsTableShellCoreSlice<T>
|
|
106
|
+
// chrome / layout props
|
|
107
|
+
rowDraggable: () => boolean
|
|
108
|
+
rowDragTrigger: () => RsTableRowDragTrigger
|
|
109
|
+
selectable: () => boolean
|
|
110
|
+
selectionType: () => RsTableSelectionType
|
|
111
|
+
scrollX: () => number | string | undefined
|
|
112
|
+
resizable: () => boolean
|
|
113
|
+
minColumnWidth: () => number | undefined
|
|
114
|
+
maxColumnWidth: () => number | undefined
|
|
115
|
+
columnLayout: () => 'auto' | 'fixed'
|
|
116
|
+
virtualColumns: () => boolean | 'auto' | undefined
|
|
117
|
+
virtualColumnsAutoThreshold: () => number | undefined
|
|
118
|
+
virtualColumnOverscan: () => number | undefined
|
|
119
|
+
fill: () => boolean
|
|
120
|
+
infinite: () => boolean
|
|
121
|
+
height: () => number | string | undefined
|
|
122
|
+
showEditGutterColumn: () => boolean
|
|
123
|
+
showIndexColumn: () => boolean
|
|
124
|
+
showRowStatusColumn: () => boolean
|
|
125
|
+
resolvedGutterWidth: () => number
|
|
126
|
+
resolvedIndexWidth: () => number
|
|
127
|
+
// interaction
|
|
128
|
+
multiSort: () => boolean
|
|
129
|
+
maxSort: () => number | undefined
|
|
130
|
+
columnDraggable: () => boolean
|
|
131
|
+
rowSelectable?: (row: T, index: number) => boolean
|
|
132
|
+
rowDropMode: () => RsTableRowDropMode
|
|
133
|
+
rowDraggableWhen?: (row: T, index: number) => boolean
|
|
134
|
+
rowDropTargetWhen?: (row: T, index: number) => boolean
|
|
135
|
+
canRowDrop?: (dragKeys: string[], dropKey: string) => boolean
|
|
136
|
+
rowKey: () => RsTableRowKey<T> | undefined
|
|
137
|
+
treeConfig: () => RsTableTreeConfig<T> | undefined
|
|
138
|
+
expandable: () => boolean
|
|
139
|
+
rowExpandable?: (row: T, index: number) => boolean
|
|
140
|
+
isEditingAny: () => boolean
|
|
141
|
+
applyRowClickHighlight: (key: string) => void
|
|
142
|
+
onRowClickEmit: (row: T, index: number) => void
|
|
143
|
+
onRowDblclickEmit: (row: T, index: number) => void
|
|
144
|
+
onRowDragStartEmit: (dragKeys: string[], event: DragEvent) => void
|
|
145
|
+
onRowDropEmit: (dragKeys: string[], dropKey: string, position: RsTableRowDropPosition) => void
|
|
146
|
+
onColumnResize: (key: string, width: number) => void
|
|
147
|
+
// context menu
|
|
148
|
+
contextMenuEnabled: ComputedRef<boolean> | (() => boolean)
|
|
149
|
+
copyCellLabel: () => string
|
|
150
|
+
copyRowLabel: () => string
|
|
151
|
+
contextMenuItems?: (row: T | null, selectedRows: T[]) => RsContextMenuItem[]
|
|
152
|
+
mergeFeatureMenuItems?: (
|
|
153
|
+
items: RsContextMenuItem[],
|
|
154
|
+
ctx: { row: T | null; selectedRows: T[] },
|
|
155
|
+
) => RsContextMenuItem[]
|
|
156
|
+
selectOnContextmenu: () => boolean
|
|
157
|
+
getDraft: (rowKey: string, colKey: string) => string | undefined
|
|
158
|
+
onContextMenuSelect: (key: string, row: T | null, selected: T[]) => void
|
|
159
|
+
onRowContextmenuEmit: (row: T, rowIndex: number, event: MouseEvent) => void
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 装配壳层:列几何/布局/交互/右键。
|
|
164
|
+
*/
|
|
165
|
+
export function useRsTableShell<T extends RsTableRowData>(options: UseRsTableShellOptions<T>) {
|
|
166
|
+
const { core } = options
|
|
167
|
+
const PREFIX_COL_WIDTH = RS_TABLE_PREFIX_COL_WIDTH
|
|
168
|
+
|
|
169
|
+
const showRowDragHandle = computed(
|
|
170
|
+
() => options.rowDraggable() && options.rowDragTrigger() === 'handle',
|
|
171
|
+
)
|
|
172
|
+
const dragColumnOffset = computed(() => (showRowDragHandle.value ? 40 : 0))
|
|
173
|
+
const expandColumnOffset = computed(
|
|
174
|
+
() => dragColumnOffset.value + (core.detailExpandable.value ? 40 : 0),
|
|
175
|
+
)
|
|
176
|
+
const showSelectColumn = computed(
|
|
177
|
+
() => options.selectable() && options.selectionType() !== 'row',
|
|
178
|
+
)
|
|
179
|
+
const isRowSelection = computed(
|
|
180
|
+
() => options.selectable() && options.selectionType() === 'row',
|
|
181
|
+
)
|
|
182
|
+
const isRadioSelection = computed(() => options.selectionType() === 'radio')
|
|
183
|
+
const selectColumnOffset = computed(
|
|
184
|
+
() => expandColumnOffset.value + (showSelectColumn.value ? 40 : 0),
|
|
185
|
+
)
|
|
186
|
+
const tableMinWidth = computed(() => resolveScrollWidth(options.scrollX()))
|
|
187
|
+
|
|
188
|
+
const selectedRowKeysAcc = asAccessor(core.selectedRowKeys)
|
|
189
|
+
const expandedRowKeysAcc = asAccessor(core.expandedRowKeys)
|
|
190
|
+
const treeLoadingKeysAcc = asAccessor(core.treeLoadingKeys)
|
|
191
|
+
const sortStateAcc = asAccessor(core.sortState)
|
|
192
|
+
const sortsStateAcc = asAccessor(core.sortsState)
|
|
193
|
+
const columnOrderStateAcc = asAccessor(core.columnOrderState)
|
|
194
|
+
const resolvedWidthsAcc = asAccessor(core.resolvedColumnWidths)
|
|
195
|
+
|
|
196
|
+
const {
|
|
197
|
+
tableRef,
|
|
198
|
+
isColumnResizing,
|
|
199
|
+
resizePaintWidths,
|
|
200
|
+
onResizeStart,
|
|
201
|
+
} = useRsTableColumnResize<T>({
|
|
202
|
+
resizable: () => options.resizable(),
|
|
203
|
+
minColumnWidth: () => options.minColumnWidth(),
|
|
204
|
+
maxColumnWidth: () => options.maxColumnWidth(),
|
|
205
|
+
displayColumns: () => core.displayColumns.value,
|
|
206
|
+
resolvedColumnWidths: resolvedWidthsAcc,
|
|
207
|
+
measurePrefixColumnWidth: () =>
|
|
208
|
+
measureRsTablePrefixWidth({
|
|
209
|
+
showRowDragHandle: showRowDragHandle.value,
|
|
210
|
+
detailExpandable: core.detailExpandable.value,
|
|
211
|
+
showSelectColumn: showSelectColumn.value,
|
|
212
|
+
showEditGutterColumn: options.showEditGutterColumn(),
|
|
213
|
+
showIndexColumn: options.showIndexColumn(),
|
|
214
|
+
gutterWidth: options.resolvedGutterWidth(),
|
|
215
|
+
indexWidth: options.resolvedIndexWidth(),
|
|
216
|
+
}),
|
|
217
|
+
tableMinWidth: () => tableMinWidth.value,
|
|
218
|
+
onColumnResize: options.onColumnResize,
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
/** 拖拽帧用快照,否则持久化宽 —— 供布局/列虚拟共用,避免双份计算 */
|
|
222
|
+
const effectiveColumnWidths = computed(
|
|
223
|
+
() => resizePaintWidths.value ?? resolvedWidthsAcc.get(),
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
const {
|
|
227
|
+
virtualColumnsEnabled,
|
|
228
|
+
visibleDataColumns,
|
|
229
|
+
columnPadLeft,
|
|
230
|
+
columnPadRight,
|
|
231
|
+
} = useRsTableColumnVirtual<T>({
|
|
232
|
+
displayColumns: () => core.displayColumns.value,
|
|
233
|
+
virtualColumns: () => options.virtualColumns(),
|
|
234
|
+
virtualColumnsAutoThreshold: () => options.virtualColumnsAutoThreshold(),
|
|
235
|
+
virtualColumnOverscan: () => options.virtualColumnOverscan(),
|
|
236
|
+
isColumnResizing: () => isColumnResizing.value,
|
|
237
|
+
scrollLeft: () => core.scrollLeft.value,
|
|
238
|
+
measuredViewportWidth: () => core.measuredViewportWidth.value,
|
|
239
|
+
columnWidths: () => effectiveColumnWidths.value,
|
|
240
|
+
showRowDragHandle: () => showRowDragHandle.value,
|
|
241
|
+
detailExpandable: () => core.detailExpandable.value,
|
|
242
|
+
showSelectColumn: () => showSelectColumn.value,
|
|
243
|
+
showEditGutterColumn: () => options.showEditGutterColumn(),
|
|
244
|
+
showIndexColumn: () => options.showIndexColumn(),
|
|
245
|
+
showRowStatusColumn: () => options.showRowStatusColumn(),
|
|
246
|
+
resolvedGutterWidth: () => options.resolvedGutterWidth(),
|
|
247
|
+
resolvedIndexWidth: () => options.resolvedIndexWidth(),
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
const layout = useRsTableColumnLayout<T>({
|
|
251
|
+
displayColumns: () => core.displayColumns.value,
|
|
252
|
+
effectiveColumnWidths: () => effectiveColumnWidths.value,
|
|
253
|
+
measuredViewportWidth: () => core.measuredViewportWidth.value,
|
|
254
|
+
tableMinWidth: () => tableMinWidth.value,
|
|
255
|
+
resizable: () => options.resizable(),
|
|
256
|
+
columnLayout: () => options.columnLayout(),
|
|
257
|
+
useStableColumnWidths: () => core.useStableColumnWidths.value,
|
|
258
|
+
isColumnResizing: () => isColumnResizing.value,
|
|
259
|
+
virtualColumnsEnabled: () => virtualColumnsEnabled.value,
|
|
260
|
+
scrollX: () => options.scrollX(),
|
|
261
|
+
showRowDragHandle: () => showRowDragHandle.value,
|
|
262
|
+
detailExpandable: () => core.detailExpandable.value,
|
|
263
|
+
showSelectColumn: () => showSelectColumn.value,
|
|
264
|
+
showEditGutterColumn: () => options.showEditGutterColumn(),
|
|
265
|
+
showIndexColumn: () => options.showIndexColumn(),
|
|
266
|
+
showRowStatusColumn: () => options.showRowStatusColumn(),
|
|
267
|
+
resolvedGutterWidth: () => options.resolvedGutterWidth(),
|
|
268
|
+
resolvedIndexWidth: () => options.resolvedIndexWidth(),
|
|
269
|
+
dragColumnOffset: () => dragColumnOffset.value,
|
|
270
|
+
expandColumnOffset: () => expandColumnOffset.value,
|
|
271
|
+
selectColumnOffset: () => selectColumnOffset.value,
|
|
272
|
+
resizePaintWidths: () => resizePaintWidths.value,
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
const useScrollContainer = computed(
|
|
276
|
+
() =>
|
|
277
|
+
core.virtualScrollEnabled.value ||
|
|
278
|
+
options.infinite() ||
|
|
279
|
+
virtualColumnsEnabled.value,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
const scrollContainerStyle = computed(() => {
|
|
283
|
+
const style: Record<string, string> = {}
|
|
284
|
+
if (useScrollContainer.value && !options.fill()) {
|
|
285
|
+
const resolvedHeight = resolveVirtualListHeight(options.height(), 320)
|
|
286
|
+
if (resolvedHeight) {
|
|
287
|
+
style.height = resolvedHeight
|
|
288
|
+
style.maxHeight = resolvedHeight
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (options.showEditGutterColumn()) {
|
|
292
|
+
style['--rs-table-gutter-width'] = `${options.resolvedGutterWidth()}px`
|
|
293
|
+
}
|
|
294
|
+
if (showSelectColumn.value) {
|
|
295
|
+
style['--rs-table-select-width'] = `${PREFIX_COL_WIDTH.select}px`
|
|
296
|
+
}
|
|
297
|
+
if (options.showIndexColumn()) {
|
|
298
|
+
style['--rs-table-index-width'] = `${options.resolvedIndexWidth()}px`
|
|
299
|
+
}
|
|
300
|
+
return Object.keys(style).length ? style : undefined
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
const bodyColspan = computed(() => {
|
|
304
|
+
let count = visibleDataColumns.value.length
|
|
305
|
+
if (columnPadLeft.value > 0) count += 1
|
|
306
|
+
if (columnPadRight.value > 0) count += 1
|
|
307
|
+
if (showRowDragHandle.value) count += 1
|
|
308
|
+
if (core.detailExpandable.value) count += 1
|
|
309
|
+
if (showSelectColumn.value) count += 1
|
|
310
|
+
if (options.showEditGutterColumn() || options.showIndexColumn()) count += 1
|
|
311
|
+
if (options.showRowStatusColumn()) count += 1
|
|
312
|
+
return count
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
const emptyContentStyle = computed(() => {
|
|
316
|
+
const w = core.measuredViewportWidth.value
|
|
317
|
+
if (w <= 0) return undefined
|
|
318
|
+
return { width: `${w}px` }
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
const interaction = useRsTableInteraction<T>({
|
|
322
|
+
multiSort: () => options.multiSort(),
|
|
323
|
+
maxSort: () => options.maxSort(),
|
|
324
|
+
columnDraggable: () => options.columnDraggable(),
|
|
325
|
+
selectable: () => options.selectable(),
|
|
326
|
+
selectionType: () => options.selectionType(),
|
|
327
|
+
rowSelectable: options.rowSelectable,
|
|
328
|
+
rowDraggable: () => options.rowDraggable(),
|
|
329
|
+
rowDragTrigger: () => options.rowDragTrigger(),
|
|
330
|
+
rowDropMode: () => options.rowDropMode(),
|
|
331
|
+
rowDraggableWhen: options.rowDraggableWhen,
|
|
332
|
+
rowDropTargetWhen: options.rowDropTargetWhen,
|
|
333
|
+
canRowDrop: options.canRowDrop,
|
|
334
|
+
rowKey: () => options.rowKey(),
|
|
335
|
+
rowKeyByIndex: () => core.rowKeyByIndex.value,
|
|
336
|
+
selectedRowKeys: selectedRowKeysAcc,
|
|
337
|
+
selectedKeySet: () => core.selectedKeySet.value,
|
|
338
|
+
selectableRowKeys: () => core.selectableRowKeys.value,
|
|
339
|
+
selectAllState: () => core.selectAllState.value,
|
|
340
|
+
expandedRowKeys: expandedRowKeysAcc,
|
|
341
|
+
expandedKeySet: () => core.expandedKeySet.value,
|
|
342
|
+
treeMode: () => core.treeMode.value,
|
|
343
|
+
treeCheckStrictly: () => core.treeCheckStrictly.value,
|
|
344
|
+
treeLazy: () => core.treeLazy.value,
|
|
345
|
+
treeChildrenField: () => core.treeChildrenField.value,
|
|
346
|
+
treeIsLeafField: () => core.treeIsLeafField.value,
|
|
347
|
+
treeLoadingKeys: treeLoadingKeysAcc,
|
|
348
|
+
treeLoadingKeySet: () => core.treeLoadingKeySet.value,
|
|
349
|
+
tableTreeNodeIndex: () => core.tableTreeNodeIndex.value,
|
|
350
|
+
treeConfig: () => options.treeConfig(),
|
|
351
|
+
expandable: () => options.expandable(),
|
|
352
|
+
rowExpandable: options.rowExpandable,
|
|
353
|
+
sortState: sortStateAcc,
|
|
354
|
+
sortsState: sortsStateAcc,
|
|
355
|
+
columnOrderState: columnOrderStateAcc,
|
|
356
|
+
isEditingAny: () => options.isEditingAny(),
|
|
357
|
+
applyRowClickHighlight: options.applyRowClickHighlight,
|
|
358
|
+
onRowClickEmit: options.onRowClickEmit,
|
|
359
|
+
onRowDblclickEmit: options.onRowDblclickEmit,
|
|
360
|
+
onRowDragStartEmit: options.onRowDragStartEmit,
|
|
361
|
+
onRowDropEmit: options.onRowDropEmit,
|
|
362
|
+
})
|
|
363
|
+
|
|
364
|
+
const contextMenu = useRsTableContextMenu<T>({
|
|
365
|
+
enabled: options.contextMenuEnabled,
|
|
366
|
+
dataRows: () => core.dataRows.value,
|
|
367
|
+
displayColumns: () => core.displayColumns.value,
|
|
368
|
+
selectedRows: () => core.selectedRows.value,
|
|
369
|
+
rowKey: () => options.rowKey(),
|
|
370
|
+
rowKeyByIndex: () => core.rowKeyByIndex.value,
|
|
371
|
+
copyCellLabel: () => options.copyCellLabel(),
|
|
372
|
+
copyRowLabel: () => options.copyRowLabel(),
|
|
373
|
+
contextMenuItems: (row, selected) => options.contextMenuItems?.(row, selected) ?? [],
|
|
374
|
+
mergeFeatureMenuItems: options.mergeFeatureMenuItems,
|
|
375
|
+
shouldSelectOnContextmenu: () => options.selectOnContextmenu(),
|
|
376
|
+
canSelectRow: interaction.canSelectRow,
|
|
377
|
+
isRowSelected: interaction.isRowSelected,
|
|
378
|
+
selectionType: () => options.selectionType(),
|
|
379
|
+
getSelectedRowKeys: () => selectedRowKeysAcc.get(),
|
|
380
|
+
setSelectedRowKeys: (keys) => selectedRowKeysAcc.set(keys),
|
|
381
|
+
selectRowKeys,
|
|
382
|
+
getDraft: options.getDraft,
|
|
383
|
+
onSelect: options.onContextMenuSelect,
|
|
384
|
+
onRowContextmenu: options.onRowContextmenuEmit,
|
|
385
|
+
})
|
|
386
|
+
|
|
387
|
+
return {
|
|
388
|
+
PREFIX_COL_WIDTH,
|
|
389
|
+
showRowDragHandle,
|
|
390
|
+
dragColumnOffset,
|
|
391
|
+
expandColumnOffset,
|
|
392
|
+
showSelectColumn,
|
|
393
|
+
isRowSelection,
|
|
394
|
+
isRadioSelection,
|
|
395
|
+
selectColumnOffset,
|
|
396
|
+
tableMinWidth,
|
|
397
|
+
tableRef,
|
|
398
|
+
isColumnResizing,
|
|
399
|
+
resizePaintWidths,
|
|
400
|
+
onResizeStart,
|
|
401
|
+
effectiveColumnWidths,
|
|
402
|
+
virtualColumnsEnabled,
|
|
403
|
+
visibleDataColumns,
|
|
404
|
+
columnPadLeft,
|
|
405
|
+
columnPadRight,
|
|
406
|
+
...layout,
|
|
407
|
+
useScrollContainer,
|
|
408
|
+
scrollContainerStyle,
|
|
409
|
+
bodyColspan,
|
|
410
|
+
emptyContentStyle,
|
|
411
|
+
...interaction,
|
|
412
|
+
...contextMenu,
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
export type RsTableShellApi<T extends RsTableRowData> = ReturnType<typeof useRsTableShell<T>>
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RsTable 壳层编排:i18n 文案、a11y 绑定、Grid 键盘、滚动宿主 class。
|
|
3
|
+
* 从 RsTable.vue 下沉,SFC 只保留接线。
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { computed, useAttrs, useSlots, type ComputedRef, type Ref } from 'vue'
|
|
7
|
+
import type { useTableEdit } from './useTableEdit'
|
|
8
|
+
import { useRsI18n } from './useRsI18n'
|
|
9
|
+
import { useRsTableA11y } from './useRsTableA11y'
|
|
10
|
+
import { useRsTableGridKeyboard } from './useRsTableGridKeyboard'
|
|
11
|
+
import type { RsTableColumn, RsTableRowData, RsTableRowEntry } from '../components/table-utils'
|
|
12
|
+
|
|
13
|
+
type TableEditApi = ReturnType<typeof useTableEdit>
|
|
14
|
+
|
|
15
|
+
export interface UseRsTableShellChromeOptions<T extends RsTableRowData> {
|
|
16
|
+
ariaLabel: () => string | undefined
|
|
17
|
+
loading: () => boolean
|
|
18
|
+
dataRows:
|
|
19
|
+
| Ref<Array<Extract<RsTableRowEntry<T>, { type: 'row' }>>>
|
|
20
|
+
| ComputedRef<Array<Extract<RsTableRowEntry<T>, { type: 'row' }>>>
|
|
21
|
+
visibleDataColumns: Ref<RsTableColumn<T>[]> | ComputedRef<RsTableColumn<T>[]>
|
|
22
|
+
displayColumns: () => RsTableColumn<T>[]
|
|
23
|
+
tableEdit: TableEditApi
|
|
24
|
+
rowKeyFor: (entry: Extract<RsTableRowEntry<T>, { type: 'row' }>) => string
|
|
25
|
+
applyRowClickHighlight: (rowKey: string) => void
|
|
26
|
+
pageSize: () => number
|
|
27
|
+
onTableKeydown: (event: KeyboardEvent) => void
|
|
28
|
+
scrollContainerRef?: Ref<HTMLElement | null | undefined>
|
|
29
|
+
/** 滚动宿主 class 所需状态 */
|
|
30
|
+
hostClass: {
|
|
31
|
+
bordered: () => boolean
|
|
32
|
+
columnBordered: () => boolean
|
|
33
|
+
rounded: () => boolean
|
|
34
|
+
fill: () => boolean
|
|
35
|
+
compact: () => boolean
|
|
36
|
+
resolvedSize: () => string
|
|
37
|
+
virtualScrollEnabled: () => boolean
|
|
38
|
+
virtualColumnsEnabled: () => boolean
|
|
39
|
+
dataLength: () => number
|
|
40
|
+
infinite: () => boolean
|
|
41
|
+
resizable: () => boolean
|
|
42
|
+
columnLayout: () => string
|
|
43
|
+
useFixedColumnLayout: () => boolean
|
|
44
|
+
striped: () => boolean
|
|
45
|
+
selectable: () => boolean
|
|
46
|
+
isRowSelection: () => boolean
|
|
47
|
+
detailExpandable: () => boolean
|
|
48
|
+
treeMode: () => boolean
|
|
49
|
+
rowDraggable: () => boolean
|
|
50
|
+
columnDraggable: () => boolean
|
|
51
|
+
scrollX: () => number | string | undefined
|
|
52
|
+
overflowXEnabled: () => boolean
|
|
53
|
+
contextMenuEnabled: () => boolean
|
|
54
|
+
showEditGutterColumn: () => boolean
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 壳层 chrome:文案 / a11y / 键盘 / 宿主 class。
|
|
60
|
+
*/
|
|
61
|
+
export function useRsTableShellChrome<T extends RsTableRowData>(
|
|
62
|
+
options: UseRsTableShellChromeOptions<T>,
|
|
63
|
+
) {
|
|
64
|
+
const { t } = useRsI18n()
|
|
65
|
+
const slots = useSlots()
|
|
66
|
+
const attrs = useAttrs()
|
|
67
|
+
|
|
68
|
+
const hasData = computed(() => options.dataRows.value.length > 0)
|
|
69
|
+
|
|
70
|
+
const headerLabels = computed(() => ({
|
|
71
|
+
selectAll: t('table.selectAll'),
|
|
72
|
+
index: t('table.index'),
|
|
73
|
+
rowStatus: t('table.rowStatus'),
|
|
74
|
+
dragColumn: t('table.dragColumn'),
|
|
75
|
+
filterColumn: t('table.filterColumn'),
|
|
76
|
+
filterPlaceholder: t('table.filterPlaceholder'),
|
|
77
|
+
filterClear: t('table.filterClear'),
|
|
78
|
+
filterApply: t('table.filterApply'),
|
|
79
|
+
}))
|
|
80
|
+
|
|
81
|
+
const bodyLabels = computed(() => ({
|
|
82
|
+
loading: t('table.loading'),
|
|
83
|
+
empty: t('table.empty'),
|
|
84
|
+
loadingMore: t('table.loadingMore'),
|
|
85
|
+
dragRow: t('table.dragRow'),
|
|
86
|
+
expandRow: t('table.expandRow'),
|
|
87
|
+
collapseRow: t('table.collapseRow'),
|
|
88
|
+
selectRow: t('table.selectRow'),
|
|
89
|
+
rowCommit: t('table.rowCommit'),
|
|
90
|
+
rowRollback: t('table.rowRollback'),
|
|
91
|
+
gutterCommit: t('table.gutterCommit'),
|
|
92
|
+
}))
|
|
93
|
+
|
|
94
|
+
function hasColumnSlot(key: string): boolean {
|
|
95
|
+
return Boolean(slots[key])
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function hasEditSlot(key: string): boolean {
|
|
99
|
+
return Boolean(slots[`edit-${key}`])
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const { shellA11y, tableA11y } = useRsTableA11y({
|
|
103
|
+
ariaLabel: options.ariaLabel,
|
|
104
|
+
defaultLabel: () => t('table.a11yLabel'),
|
|
105
|
+
loading: options.loading,
|
|
106
|
+
rowCount: () => options.dataRows.value.length,
|
|
107
|
+
colCount: () => options.visibleDataColumns.value.length,
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const shellBind = computed(() => ({
|
|
111
|
+
...shellA11y.value,
|
|
112
|
+
...attrs,
|
|
113
|
+
}))
|
|
114
|
+
|
|
115
|
+
const { onGridKeydown } = useRsTableGridKeyboard<T>({
|
|
116
|
+
tableEdit: options.tableEdit,
|
|
117
|
+
dataRows: () => options.dataRows.value,
|
|
118
|
+
rowKeyFor: options.rowKeyFor,
|
|
119
|
+
colKeys: () => options.visibleDataColumns.value.map((c) => c.key),
|
|
120
|
+
displayColumns: options.displayColumns,
|
|
121
|
+
applyRowClickHighlight: options.applyRowClickHighlight,
|
|
122
|
+
pageSize: options.pageSize,
|
|
123
|
+
scrollContainerRef: options.scrollContainerRef,
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
function onShellKeydown(event: KeyboardEvent): void {
|
|
127
|
+
if (onGridKeydown(event)) return
|
|
128
|
+
options.onTableKeydown(event)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const h = options.hostClass
|
|
132
|
+
const scrollHostClass = computed(() => ({
|
|
133
|
+
'rs-table--bordered': h.bordered(),
|
|
134
|
+
'rs-table--column-bordered': h.columnBordered(),
|
|
135
|
+
'rs-table--rounded': h.rounded(),
|
|
136
|
+
'rs-table--fill': h.fill(),
|
|
137
|
+
'rs-table--compact': h.compact(),
|
|
138
|
+
[`rs-table--${h.resolvedSize()}`]: true,
|
|
139
|
+
'rs-table--virtual': h.virtualScrollEnabled(),
|
|
140
|
+
'rs-table--virtual-cols': h.virtualColumnsEnabled(),
|
|
141
|
+
'rs-table--content-visibility': !h.virtualScrollEnabled() && h.dataLength() >= 30,
|
|
142
|
+
'rs-table--infinite': h.infinite(),
|
|
143
|
+
'rs-table--resizable': h.resizable(),
|
|
144
|
+
'rs-table--col-auto': h.resizable() && h.columnLayout() === 'auto',
|
|
145
|
+
'rs-table--col-fixed': h.useFixedColumnLayout(),
|
|
146
|
+
'rs-table--striped': h.striped(),
|
|
147
|
+
'rs-table--selectable': h.selectable(),
|
|
148
|
+
'rs-table--row-select': h.isRowSelection(),
|
|
149
|
+
'rs-table--expandable': h.detailExpandable(),
|
|
150
|
+
'rs-table--tree': h.treeMode(),
|
|
151
|
+
'rs-table--draggable': h.rowDraggable() || h.columnDraggable(),
|
|
152
|
+
'rs-table--scroll-x': !!h.scrollX(),
|
|
153
|
+
'rs-table--overflow-x': h.overflowXEnabled(),
|
|
154
|
+
'rs-table--ctx': h.contextMenuEnabled(),
|
|
155
|
+
'rs-table--edit-gutter': h.showEditGutterColumn(),
|
|
156
|
+
}))
|
|
157
|
+
|
|
158
|
+
return {
|
|
159
|
+
t,
|
|
160
|
+
hasData,
|
|
161
|
+
headerLabels,
|
|
162
|
+
bodyLabels,
|
|
163
|
+
hasColumnSlot,
|
|
164
|
+
hasEditSlot,
|
|
165
|
+
tableA11y,
|
|
166
|
+
shellBind,
|
|
167
|
+
onShellKeydown,
|
|
168
|
+
scrollHostClass,
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RsTable 汇总行编排:是否启用、footer 单元格、前缀 colspan。
|
|
3
|
+
*
|
|
4
|
+
* 纯聚合算法在 table-summary-utils;本 composable 对接 props / slots / 前缀列状态。
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { computed, watch, type ComputedRef } from 'vue'
|
|
8
|
+
import type { RsTableColumn, RsTableRowData } from '../components/table-utils'
|
|
9
|
+
import {
|
|
10
|
+
buildTableSummaryCells,
|
|
11
|
+
hasTableSummaryConfig,
|
|
12
|
+
warnSummaryCompatibility,
|
|
13
|
+
type RsTableColumnSummary,
|
|
14
|
+
type RsTableSummaryData,
|
|
15
|
+
type RsTableSummaryMode,
|
|
16
|
+
} from '../components/table/table-summary-utils'
|
|
17
|
+
|
|
18
|
+
function read<T>(source: ComputedRef<T> | (() => T)): T {
|
|
19
|
+
return typeof source === 'function' ? (source as () => T)() : source.value
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
type ColumnWithSummary<T extends RsTableRowData> = RsTableColumn<T> & {
|
|
23
|
+
summary?: RsTableColumnSummary<T>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface UseRsTableSummaryOptions<T extends RsTableRowData> {
|
|
27
|
+
/** 显式开启汇总行 */
|
|
28
|
+
showSummary: ComputedRef<boolean | undefined> | (() => boolean | undefined)
|
|
29
|
+
summaryMode: ComputedRef<RsTableSummaryMode> | (() => RsTableSummaryMode)
|
|
30
|
+
summaryData: ComputedRef<RsTableSummaryData | null | undefined> | (() => RsTableSummaryData | null | undefined)
|
|
31
|
+
/** 原始列(判断是否配置 summary) */
|
|
32
|
+
columns: ComputedRef<ColumnWithSummary<T>[]> | (() => ColumnWithSummary<T>[])
|
|
33
|
+
/** 展示列(footer 与表体对齐) */
|
|
34
|
+
displayColumns: ComputedRef<ColumnWithSummary<T>[]> | (() => ColumnWithSummary<T>[])
|
|
35
|
+
viewRows: ComputedRef<T[]> | (() => T[])
|
|
36
|
+
/** 是否存在 #summary 插槽(有则不渲染内置行) */
|
|
37
|
+
hasSummarySlot: ComputedRef<boolean> | (() => boolean)
|
|
38
|
+
treeMode: ComputedRef<boolean> | (() => boolean)
|
|
39
|
+
detailExpandable: ComputedRef<boolean> | (() => boolean)
|
|
40
|
+
showRowDragHandle: ComputedRef<boolean> | (() => boolean)
|
|
41
|
+
showSelectColumn: ComputedRef<boolean> | (() => boolean)
|
|
42
|
+
showEditGutterOrIndex: ComputedRef<boolean> | (() => boolean)
|
|
43
|
+
showRowStatusColumn: ComputedRef<boolean> | (() => boolean)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 汇总 feature 状态。
|
|
48
|
+
*
|
|
49
|
+
* @returns enabled / cells / showBuiltinSummaryRow / prefixColspan
|
|
50
|
+
*/
|
|
51
|
+
export function useRsTableSummary<T extends RsTableRowData>(options: UseRsTableSummaryOptions<T>) {
|
|
52
|
+
const summaryFeatureEnabled = computed(() => {
|
|
53
|
+
if (read(options.showSummary)) return true
|
|
54
|
+
return hasTableSummaryConfig({
|
|
55
|
+
columns: read(options.columns),
|
|
56
|
+
mode: read(options.summaryMode),
|
|
57
|
+
summaryData: read(options.summaryData),
|
|
58
|
+
})
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
const summaryCells = computed(() => {
|
|
62
|
+
if (!summaryFeatureEnabled.value) return []
|
|
63
|
+
return buildTableSummaryCells({
|
|
64
|
+
columns: read(options.displayColumns),
|
|
65
|
+
rows: read(options.viewRows),
|
|
66
|
+
mode: read(options.summaryMode),
|
|
67
|
+
summaryData: read(options.summaryData),
|
|
68
|
+
})
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
const showBuiltinSummaryRow = computed(
|
|
72
|
+
() => summaryFeatureEnabled.value && !read(options.hasSummarySlot),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
const summaryPrefixColspan = computed(() => {
|
|
76
|
+
let n = 0
|
|
77
|
+
if (read(options.showRowDragHandle)) n += 1
|
|
78
|
+
if (read(options.detailExpandable)) n += 1
|
|
79
|
+
if (read(options.showSelectColumn)) n += 1
|
|
80
|
+
if (read(options.showEditGutterOrIndex)) n += 1
|
|
81
|
+
if (read(options.showRowStatusColumn)) n += 1
|
|
82
|
+
return n
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
if (import.meta.env.DEV) {
|
|
86
|
+
watch(
|
|
87
|
+
() =>
|
|
88
|
+
[
|
|
89
|
+
summaryFeatureEnabled.value,
|
|
90
|
+
read(options.treeMode),
|
|
91
|
+
read(options.detailExpandable),
|
|
92
|
+
] as const,
|
|
93
|
+
([summaryEnabled, tree, detail]) => {
|
|
94
|
+
warnSummaryCompatibility({
|
|
95
|
+
summaryEnabled,
|
|
96
|
+
tree,
|
|
97
|
+
detailExpandable: detail,
|
|
98
|
+
})
|
|
99
|
+
},
|
|
100
|
+
{ immediate: true },
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
summaryFeatureEnabled,
|
|
106
|
+
summaryCells,
|
|
107
|
+
showBuiltinSummaryRow,
|
|
108
|
+
summaryPrefixColspan,
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/** 供 feature 注册表识别:summary 已由 useRsTableSummary 承载 */
|
|
113
|
+
export const RS_TABLE_SUMMARY_FEATURE_ID = 'summary' as const
|