20260902223822

This commit is contained in:
oneao committed 2026-09-02 22:38:23 +08:00
1 parent db7813a2d2
commit c8940f6e03
11 files changed
+327 -922

No files matched your search

@@ -10,6 +10,8 @@ defineOptions({ inheritAttrs: false })
const props = defineProps({
virtual: { type: Boolean, default: true },
virtualX: { type: Boolean, default: true },
// 是否在非横向虚拟滚动时自动铺满容器;默认按列配置宽度展示。
autoFitWidth: { type: Boolean, default: false },
// 列宽拖拽默认开启;false=关闭;{ disabled: (col) => boolean }=按列禁用
// (铺满容器的弹性列应禁用拖拽,见库文档「列宽铺满容器hack方式」)
colResizable: { type: [Boolean, Object], default: true },
@@ -73,7 +75,7 @@ const tableTheme = computed(() => props.theme ?? (appStore.darkMode ? 'dark' : '
// 需从 vnode.props 探测;绑定关系在模板编写时确定,运行期不会变化,无需响应式。
const columnsBound =
'onUpdate:columns' in (getCurrentInstance()?.vnode.props ?? {})
const effectiveColResizable = columnsBound ? props.colResizable : false
const effectiveColResizable = columnsBound && !props.autoFitWidth ? props.colResizable : false
// Tab 面板从隐藏恢复时,等到容器拥有有效尺寸再刷新虚拟滚动布局。
// rAF 将同一帧内的多次 ResizeObserver 通知合并,避免重复重排。
@@ -276,6 +278,14 @@ const seqConfig = computed(() => {
width: Number(cfg.width ?? 50),
}
})
const seqWidth = ref(seqConfig.value.width)
watch(
() => seqConfig.value.width,
(width) => {
seqWidth.value = width
},
{ immediate: true },
)
const columnDragConfig = computed(() => {
if (!columnsBound || !props.columnDraggable) return false
const configured = props.columnDraggable === true ? {} : props.columnDraggable
@@ -298,16 +308,18 @@ const columnDragConfig = computed(() => {
}
})
const hasRowSelection = computed(() => Boolean(props.rowSelection))
const selectionWidth = ref(44)
const dragRowColumn = {
type: 'dragRow',
dataIndex: '__drag_row__',
title: '',
width: 40,
resizable: false,
}
const dragRowWidth = ref(dragRowColumn.width)
function getHeaderAlign(column) {
if (column.headerAlign) return column.headerAlign
if (column.type === 'seq') return 'center'
if (isSelectionColumn(column)) return 'center'
if (column.dataIndex === 'actions') return 'center'
if (column.actions && column.actions.length) return 'center'
@@ -322,14 +334,13 @@ const displayColumns = computed(() => {
if (seq.enabled) {
cols.unshift({
type: 'seq',
width: seq.width,
width: seqWidth.value,
dataIndex: '',
title: seq.title,
resizable: false,
})
}
if (props.rowDraggable) cols.unshift(dragRowColumn)
if (hasRowSelection.value) cols.unshift(selectionColumn)
if (props.rowDraggable) cols.unshift({ ...dragRowColumn, width: dragRowWidth.value })
if (hasRowSelection.value) cols.unshift({ ...selectionColumn, width: selectionWidth.value })
return cols.map((column) => ({
...column,
headerAlign: getHeaderAlign(column),
@@ -338,6 +349,15 @@ const displayColumns = computed(() => {
// 剥离内部列(选择列、序号列、拖拽列)后回传,避免污染父组件 columns
function onColumnsUpdate(columns) {
for (const column of columns || []) {
if (isSelectionColumn(column) && column.width != null) {
selectionWidth.value = Number.parseInt(column.width, 10) || selectionWidth.value
} else if (column.type === 'seq' && column.width != null) {
seqWidth.value = Number.parseInt(column.width, 10) || seqWidth.value
} else if (column.type === 'dragRow' && column.width != null) {
dragRowWidth.value = Number.parseInt(column.width, 10) || dragRowWidth.value
}
}
const originalByKey = new Map(
props.columns.map((col) => [String(col.key ?? col.dataIndex ?? ''), col]),
)
@@ -592,7 +612,7 @@ defineExpose({
<div
ref="rootRef"
class="fms-table"
:class="[bordered ? 'fms-table--bordered' : '']"
:class="[bordered ? 'fms-table--bordered' : '', autoFitWidth ? 'fms-table--auto-fit-width' : '']"
@keydown.capture="handleKeydownCapture"
>
<StkTable
@@ -660,6 +680,11 @@ defineExpose({
will-change: transform;
}
}
/* 不自适应时按列配置宽度展示;自适应模式不启用列宽拖拽,使用库默认布局。 */
.fms-table:not(.fms-table--auto-fit-width) :deep(.stk-table-main) {
flex: none;
}
</style>
<!-- 非 scoped 全局样式:选择列原生 checkbox 外观模拟 antdv-next Checkbox,
@@ -684,15 +709,6 @@ defineExpose({
}
}
/* 列宽铺满容器(库文档「列宽铺满容器hack方式」):
开启 col-resizable 后库默认把 .stk-table-main 设为 flex:none + fit-content,
表格收缩到内容宽。非 virtual-x(列数 ≤ 阈值、未设宽列走原生自适应)时覆盖回
flex:1 使表格铺满容器;配合「固定列设 width、弹性列设 minWidth 且禁用其拖拽」
的列配置约定使用。宽表(virtual-x,横向滚动)保持库的收缩行为。 */
.fms-table__inner.stk-table:not(.virtual-x) .stk-table-main {
flex: 1;
}
.fms-checkbox {
display: flex;
align-items: center;