From fd78993b9105519dfeb8a7a0a3bf925a8f15e3b3 Mon Sep 17 00:00:00 2001
From: IanShaw027 <131567472+IanShaw027@users.noreply.github.com>
Date: Sat, 27 Dec 2025 20:01:36 +0800
Subject: [PATCH 1/4] =?UTF-8?q?feat(frontend):=20DataTable=E7=BB=84?=
=?UTF-8?q?=E4=BB=B6=E5=A2=9E=E5=BC=BA=20-=20=E6=93=8D=E4=BD=9C=E5=88=97?=
=?UTF-8?q?=E5=AE=BD=E5=BA=A6=E8=87=AA=E9=80=82=E5=BA=94=E5=92=8C=E5=88=97?=
=?UTF-8?q?=E6=95=B0=E8=87=AA=E9=80=82=E5=BA=94padding?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
新增功能:
1. 操作列宽度自适应
- checkActionsColumnWidth 方法:智能检测操作按钮是否超出列宽
- 临时展开所有按钮测量实际宽度
- 计算包含gap的总宽度
- 与可用宽度对比,自动显示/隐藏"展开"按钮
- 新增 actionsCount prop:
- 用于快速判断是否需要展开功能
- 避免DOM查询带来的性能开销
2. 列数自适应padding
- getAdaptivePaddingClass 方法:根据列数动态调整内边距
- ≥10列 → px-2 (8px)
- ≥7列 → px-3 (12px)
- ≥5列 → px-4 (16px)
- <5列 → px-6 (24px,原始值)
- 让表格在列数较多时更紧凑,提升空间利用率
---
frontend/src/components/common/DataTable.vue | 79 ++++++++++++++++----
1 file changed, 63 insertions(+), 16 deletions(-)
diff --git a/frontend/src/components/common/DataTable.vue b/frontend/src/components/common/DataTable.vue
index 2dae2d4c..52029119 100644
--- a/frontend/src/components/common/DataTable.vue
+++ b/frontend/src/components/common/DataTable.vue
@@ -15,7 +15,8 @@
:key="column.key"
scope="col"
:class="[
- 'sticky-header-cell px-6 py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-dark-400',
+ 'sticky-header-cell py-3 text-left text-xs font-medium uppercase tracking-wider text-gray-500 dark:text-dark-400',
+ getAdaptivePaddingClass(),
{ 'cursor-pointer hover:bg-gray-100 dark:hover:bg-dark-700': column.sortable },
getStickyColumnClass(column, index)
]"
@@ -81,7 +82,7 @@
- |
+ |
@@ -92,7 +93,7 @@
|
@@ -128,7 +129,8 @@
v-for="(column, colIndex) in columns"
:key="column.key"
:class="[
- 'whitespace-nowrap px-6 py-4 text-sm text-gray-900 dark:text-gray-100',
+ 'whitespace-nowrap py-4 text-sm text-gray-900 dark:text-gray-100',
+ getAdaptivePaddingClass(),
getStickyColumnClass(column, colIndex)
]"
>
@@ -165,24 +167,46 @@ const checkScrollable = () => {
const checkActionsColumnWidth = () => {
if (!tableWrapperRef.value) return
- // 查找操作列的表头单元格
- const actionsHeader = tableWrapperRef.value.querySelector('th:has(button[title*="Expand"], button[title*="展开"])')
- if (!actionsHeader) return
-
// 查找第一行的操作列单元格
const firstActionCell = tableWrapperRef.value.querySelector('tbody tr:first-child td:last-child')
if (!firstActionCell) return
- // 获取操作列内容的实际宽度
- const actionsContent = firstActionCell.querySelector('div')
- if (!actionsContent) return
+ // 查找操作列内容的容器div
+ const actionsContainer = firstActionCell.querySelector('div')
+ if (!actionsContainer) return
- // 比较内容宽度和单元格宽度
- const contentWidth = actionsContent.scrollWidth
- const cellWidth = (firstActionCell as HTMLElement).clientWidth
+ // 临时展开以测量完整宽度
+ const wasExpanded = actionsExpanded.value
+ actionsExpanded.value = true
- // 如果内容宽度超过单元格宽度,说明需要展开
- actionsColumnNeedsExpanding.value = contentWidth > cellWidth
+ // 等待DOM更新
+ nextTick(() => {
+ // 测量所有按钮的总宽度
+ const buttons = actionsContainer.querySelectorAll('button')
+ if (buttons.length <= 2) {
+ actionsColumnNeedsExpanding.value = false
+ actionsExpanded.value = wasExpanded
+ return
+ }
+
+ // 计算所有按钮的总宽度(包括gap)
+ let totalWidth = 0
+ buttons.forEach((btn, index) => {
+ totalWidth += (btn as HTMLElement).offsetWidth
+ if (index < buttons.length - 1) {
+ totalWidth += 4 // gap-1 = 4px
+ }
+ })
+
+ // 获取单元格可用宽度(减去padding)
+ const cellWidth = (firstActionCell as HTMLElement).clientWidth - 32 // 减去左右padding
+
+ // 如果总宽度超过可用宽度,需要展开功能
+ actionsColumnNeedsExpanding.value = totalWidth > cellWidth
+
+ // 恢复原来的展开状态
+ actionsExpanded.value = wasExpanded
+ })
}
// 监听尺寸变化
@@ -219,6 +243,7 @@ interface Props {
stickyFirstColumn?: boolean
stickyActionsColumn?: boolean
expandableActions?: boolean
+ actionsCount?: number // 操作按钮总数,用于判断是否需要展开功能
}
const props = withDefaults(defineProps (), {
@@ -268,6 +293,12 @@ const sortedData = computed(() => {
// 检查是否有可展开的操作列
const hasExpandableActions = computed(() => {
+ // 如果明确指定了actionsCount,使用它来判断
+ if (props.actionsCount !== undefined) {
+ return props.expandableActions && props.columns.some((col) => col.key === 'actions') && props.actionsCount > 2
+ }
+
+ // 否则使用原来的检测逻辑
return (
props.expandableActions &&
props.columns.some((col) => col.key === 'actions') &&
@@ -312,6 +343,22 @@ const getStickyColumnClass = (column: Column, index: number) => {
return classes.join(' ')
}
+
+// 根据列数自适应调整内边距
+const getAdaptivePaddingClass = () => {
+ const columnCount = props.columns.length
+
+ // 列数越多,内边距越小
+ if (columnCount >= 10) {
+ return 'px-2' // 8px
+ } else if (columnCount >= 7) {
+ return 'px-3' // 12px
+ } else if (columnCount >= 5) {
+ return 'px-4' // 16px
+ } else {
+ return 'px-6' // 24px (原始值)
+ }
+}
|