mirror of
https://github.com/Tencent/WeKnora.git
synced 2026-09-19 02:18:25 +08:00
fix(frontend): polish knowledge list sticky header and floating batch bar
- Detect sticky state via IntersectionObserver and flatten the table header's top corners when stuck so the rounded cut-outs no longer reveal the list container's background while scrolling. - Lift the batch-action toolbar out of flex flow and float it 12px above the scroll container bottom so selecting rows no longer shrinks the visible list; strengthen its shadow to match the floating treatment.
This commit is contained in:
@@ -3024,6 +3024,7 @@ async function createNewSession(value: string): Promise<void> {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
position: relative; /* 作为批量工具栏悬浮的定位上下文 */
|
||||
}
|
||||
|
||||
.doc-filter-bar {
|
||||
@@ -3137,10 +3138,21 @@ async function createNewSession(value: string): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
/* 批量条在滚动区外,始终贴主内容列底部,不随列表高度在列内上下漂移 */
|
||||
/* 批量条悬浮在滚动区底部,不挤占列表高度 */
|
||||
.doc-batch-bar-anchor {
|
||||
flex-shrink: 0;
|
||||
padding-top: 4px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 12px;
|
||||
z-index: 6;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0 16px;
|
||||
pointer-events: none;
|
||||
|
||||
& > * {
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// Header 样式(无底部分割线,留更多空间给下方内容区)
|
||||
|
||||
@@ -61,7 +61,7 @@ const { t } = useI18n();
|
||||
background: var(--td-bg-color-container);
|
||||
border: 1px solid var(--td-component-stroke);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.batch-bar-left {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { formatFileSize, getFileIcon } from '@/utils/files';
|
||||
|
||||
@@ -124,6 +124,25 @@ const onMoreVisible = (id: string, visible: boolean) => {
|
||||
moreOpen.value = visible ? id : null;
|
||||
};
|
||||
|
||||
// 吸顶检测:哨兵离开视口说明 header 已吸附在滚动容器顶部
|
||||
const stickySentinel = ref<HTMLElement | null>(null);
|
||||
const headerStuck = ref(false);
|
||||
let stickyObserver: IntersectionObserver | null = null;
|
||||
onMounted(() => {
|
||||
if (!stickySentinel.value || typeof IntersectionObserver === 'undefined') return;
|
||||
stickyObserver = new IntersectionObserver(
|
||||
(entries) => {
|
||||
headerStuck.value = !entries[0].isIntersecting;
|
||||
},
|
||||
{ threshold: 0 },
|
||||
);
|
||||
stickyObserver.observe(stickySentinel.value);
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
stickyObserver?.disconnect();
|
||||
stickyObserver = null;
|
||||
});
|
||||
|
||||
const handleAction = (action: 'edit' | 'reparse' | 'move' | 'delete', item: KnowledgeItem) => {
|
||||
moreOpen.value = null;
|
||||
item.isMore = false;
|
||||
@@ -134,7 +153,8 @@ const handleAction = (action: 'edit' | 'reparse' | 'move' | 'delete', item: Know
|
||||
|
||||
<template>
|
||||
<div class="doc-list-view" :class="{ 'is-loading': loading }">
|
||||
<div class="doc-list-header" role="row">
|
||||
<div ref="stickySentinel" class="doc-list-sticky-sentinel" aria-hidden="true"></div>
|
||||
<div class="doc-list-header" :class="{ 'is-stuck': headerStuck }" role="row">
|
||||
<div class="cell cell-check" role="columnheader" @click.stop>
|
||||
<t-checkbox
|
||||
class="doc-list-check"
|
||||
@@ -305,6 +325,14 @@ const handleAction = (action: 'edit' | 'reparse' | 'move' | 'delete', item: Know
|
||||
padding: 0 16px;
|
||||
}
|
||||
|
||||
.doc-list-sticky-sentinel {
|
||||
height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.doc-list-header {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
@@ -318,6 +346,12 @@ const handleAction = (action: 'edit' | 'reparse' | 'move' | 'delete', item: Know
|
||||
border-bottom: 1px solid var(--td-component-stroke);
|
||||
border-radius: 8px 8px 0 0;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
transition: border-radius 0.15s ease, box-shadow 0.2s ease;
|
||||
|
||||
&.is-stuck {
|
||||
border-radius: 0;
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.doc-list-body {
|
||||
|
||||
Reference in New Issue
Block a user