fix(frontend): restore table scroll and loading states

This commit is contained in:
Zyy
2026-07-17 16:23:35 +08:00
parent 8f51a7546d
commit 4ebd36d404
4 changed files with 21 additions and 16 deletions
@@ -70,7 +70,7 @@ const rootClasses = computed(() => [
props.maxHeight || props.height ? undefined : 'h-full',
])
const wrapClasses = computed(() => [
'base-scrollbar-wrap min-h-0 max-h-[inherit] overflow-auto outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--cp-info-border)',
'base-scrollbar-wrap min-h-0 max-h-[inherit] overflow-auto outline-none',
props.maxHeight ? undefined : 'h-full',
])
const verticalTrackClass = computed(() =>
@@ -3,7 +3,7 @@ import type { BaseTableColumn, BaseTableSort, ResolvedTableColumn } from './colu
import type { BaseTablePagination as BaseTablePaginationConfig } from './pagination'
import { Triangle } from '@lucide/vue'
import { computed, shallowRef, useSlots, watch } from 'vue'
import { computed, shallowRef, useSlots, useTemplateRef, watch } from 'vue'
import BaseEmpty from '../BaseEmpty.vue'
import BaseScrollbar from '../BaseScrollbar.vue'
import BaseTablePagination from './BaseTablePagination.vue'
@@ -89,9 +89,15 @@ const displayRows = computed(() =>
props.loading && props.rows.length === 0 ? retainedRows.value : props.rows,
)
const hasRows = computed(() => displayRows.value.length > 0)
const headerWrapRef = useTemplateRef<HTMLDivElement>('headerWrap')
const bodyScrollbarRef = useTemplateRef<InstanceType<typeof BaseScrollbar>>('bodyScrollbar')
const tableViewRef = useTemplateRef<HTMLTableElement>('tableView')
const { horizontalScrolled, horizontalCanScrollRight, handleTableScroll }
= useHorizontalStickyShadow({
hasRows,
headerWrapRef,
bodyScrollbarRef,
tableViewRef,
watchSources: () => [displayRows.value.length, props.minWidth],
})
@@ -216,11 +222,11 @@ function sortButtonLabel(column: BaseTableColumn<Row>) {
<template>
<div class="flex h-full min-h-0 w-full max-w-full flex-col overflow-hidden">
<div
v-loading="{ loading, preserveContent: hasRows }"
v-loading="loading"
class="relative flex min-h-0 max-w-full flex-1 overflow-hidden pb-3"
>
<div class="flex min-h-0 max-w-full flex-1 flex-col overflow-hidden">
<div class="max-w-full overflow-hidden">
<div ref="headerWrap" class="max-w-full overflow-hidden">
<table
class="w-full shrink-0 table-fixed border-separate text-left"
:class="compact ? 'border-spacing-y-0.5' : 'border-spacing-y-1'"
@@ -300,6 +306,7 @@ function sortButtonLabel(column: BaseTableColumn<Row>) {
<BaseScrollbar
v-if="hasRows"
ref="bodyScrollbar"
class="min-h-0 flex-1"
horizontal
:max-height="maxHeight"
@@ -307,6 +314,7 @@ function sortButtonLabel(column: BaseTableColumn<Row>) {
@scroll="handleTableScroll"
>
<table
ref="tableView"
class="w-full table-fixed border-separate text-left"
:class="compact ? 'border-spacing-y-1' : 'border-spacing-y-2'"
:style="tableViewStyle"
@@ -2,17 +2,17 @@ import type { Ref } from 'vue'
import type BaseScrollbar from '../BaseScrollbar.vue'
import { useResizeObserver } from '@vueuse/core'
import { nextTick, onMounted, shallowRef, useTemplateRef, watch } from 'vue'
import { nextTick, onMounted, shallowRef, watch } from 'vue'
interface UseHorizontalStickyShadowOptions {
hasRows: Ref<boolean>
headerWrapRef: Readonly<Ref<HTMLDivElement | null>>
bodyScrollbarRef: Readonly<Ref<InstanceType<typeof BaseScrollbar> | null>>
tableViewRef: Readonly<Ref<HTMLTableElement | null>>
watchSources: () => unknown[]
}
export function useHorizontalStickyShadow(options: UseHorizontalStickyShadowOptions) {
const headerWrapRef = useTemplateRef<HTMLDivElement>('headerWrap')
const bodyScrollbarRef = useTemplateRef<InstanceType<typeof BaseScrollbar>>('bodyScrollbar')
const tableViewRef = useTemplateRef<HTMLTableElement>('tableView')
const horizontalScrolled = shallowRef(false)
const horizontalCanScrollRight = shallowRef(false)
@@ -21,7 +21,7 @@ export function useHorizontalStickyShadow(options: UseHorizontalStickyShadowOpti
}
function scrollWrap() {
return bodyScrollbarRef.value?.wrapRef ?? null
return options.bodyScrollbarRef.value?.wrapRef ?? null
}
function resetHorizontalScrollbar() {
@@ -48,8 +48,8 @@ export function useHorizontalStickyShadow(options: UseHorizontalStickyShadowOpti
function handleTableScroll() {
const wrap = scrollWrap()
if (wrap && headerWrapRef.value) {
headerWrapRef.value.scrollLeft = wrap.scrollLeft
if (wrap && options.headerWrapRef.value) {
options.headerWrapRef.value.scrollLeft = wrap.scrollLeft
}
updateHorizontalScrollbar()
}
@@ -61,7 +61,7 @@ export function useHorizontalStickyShadow(options: UseHorizontalStickyShadowOpti
useResizeObserver(
() =>
[scrollWrap(), tableViewRef.value].filter(
[scrollWrap(), options.tableViewRef.value].filter(
(element): element is HTMLDivElement | HTMLTableElement => Boolean(element),
),
updateHorizontalScrollbar,
@@ -73,9 +73,6 @@ export function useHorizontalStickyShadow(options: UseHorizontalStickyShadowOpti
})
return {
headerWrapRef,
bodyScrollbarRef,
tableViewRef,
horizontalScrolled,
horizontalCanScrollRight,
handleTableScroll,
+1 -1
View File
@@ -22,7 +22,7 @@ type LoadingElement = HTMLElement & {
const OVERLAY_BASE_CLASS = [
'absolute',
'inset-0',
'z-20',
'z-50',
'grid',
'min-h-18',
'place-items-center',