feat: enhance sticky functionality by adding default sticky headers and row numbers in CSV table view #12

This commit is contained in:
JayBridge 2025-06-30 22:33:09 +08:00
parent 201a040a8a
commit d37a872e76
2 changed files with 76 additions and 19 deletions

View file

@ -72,6 +72,8 @@ export class CSVView extends TextFileView {
// 新增:固定行列功能
private stickyRows: Set<number> = new Set();
private stickyColumns: Set<number> = new Set();
private stickyHeaders: boolean = true; // 表头默认固定
private stickyRowNumbers: boolean = true; // 行号默认固定
constructor(leaf: any) {
super(leaf);
@ -949,35 +951,48 @@ export class CSVView extends TextFileView {
if (!this.tableEl) return;
// 移除所有现有的sticky类
this.tableEl.querySelectorAll('.csv-sticky-row, .csv-sticky-col').forEach(el => {
el.classList.remove('csv-sticky-row', 'csv-sticky-col');
this.tableEl.querySelectorAll('.csv-sticky-row, .csv-sticky-col, .csv-sticky-header, .csv-sticky-row-number').forEach(el => {
el.classList.remove('csv-sticky-row', 'csv-sticky-col', 'csv-sticky-header', 'csv-sticky-row-number');
});
// 应用固定行样式
// 默认固定表头行A、B、C、D...
if (this.stickyHeaders) {
const headerCells = this.tableEl.querySelectorAll('thead tr th');
headerCells.forEach(cell => cell.classList.add('csv-sticky-header'));
}
// 默认固定行号列0、1、2、3...
if (this.stickyRowNumbers) {
// 行号列在表头中(左上角和行号标题)
const headerRowNumber = this.tableEl.querySelector('thead tr th:first-child');
if (headerRowNumber) headerRowNumber.classList.add('csv-sticky-row-number');
// 行号列在数据行中
const rowNumberCells = this.tableEl.querySelectorAll('tbody tr td:first-child');
rowNumberCells.forEach(cell => cell.classList.add('csv-sticky-row-number'));
}
// 应用用户手动固定的行样式
this.stickyRows.forEach(rowIndex => {
// 表头行(列标题行)
if (rowIndex === -1) {
const headerCells = this.tableEl.querySelectorAll('thead tr th');
headerCells.forEach(cell => cell.classList.add('csv-sticky-row'));
} else {
// 数据行在tbody中从第1个tr开始
const rowCells = this.tableEl.querySelectorAll(`tbody tr:nth-child(${rowIndex + 1}) td`);
rowCells.forEach(cell => cell.classList.add('csv-sticky-row'));
}
// 数据行在tbody中从第1个tr开始
const rowCells = this.tableEl.querySelectorAll(`tbody tr:nth-child(${rowIndex + 1}) td`);
rowCells.forEach(cell => cell.classList.add('csv-sticky-row'));
});
// 应用固定列样式
// 应用用户手动固定的列样式
this.stickyColumns.forEach(colIndex => {
// 列头在thead中
// 列头在thead中跳过行号列
const headerCell = this.tableEl.querySelector(`thead tr th:nth-child(${colIndex + 2})`);
if (headerCell) headerCell.classList.add('csv-sticky-col');
// 数据列在tbody的所有行中
// 数据列在tbody的所有行中,跳过行号列
const dataCells = this.tableEl.querySelectorAll(`tbody tr td:nth-child(${colIndex + 2})`);
dataCells.forEach(cell => cell.classList.add('csv-sticky-col'));
});
console.log('Applied sticky styles:', {
stickyHeaders: this.stickyHeaders,
stickyRowNumbers: this.stickyRowNumbers,
stickyRows: Array.from(this.stickyRows),
stickyColumns: Array.from(this.stickyColumns)
});

View file

@ -134,25 +134,67 @@ If your plugin does not need CSS, delete this file.
}
/* Sticky行列样式 */
.csv-sticky-row {
/* 默认固定表头样式A、B、C、D... */
.csv-sticky-header {
position: sticky !important;
top: 0 !important;
background: var(--background-secondary) !important;
z-index: 20 !important;
background: var(--background-secondary) !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important;
}
.csv-sticky-col {
/* 第一个数据列的表头A列需要在行号列右侧 */
.csv-sticky-header:nth-child(2) {
left: 40px !important;
z-index: 22 !important;
}
/* 第一个数据列的所有单元格A列数据也需要在行号列右侧 */
tbody tr td:nth-child(2) {
position: sticky !important;
left: 40px !important;
z-index: 18 !important;
background: var(--background-secondary) !important;
box-shadow: 2px 0 4px rgba(0, 0, 0, 0.1) !important;
}
/* 默认固定行号列样式0、1、2、3... */
.csv-sticky-row-number {
position: sticky !important;
left: 0 !important;
z-index: 20 !important;
background: var(--background-secondary) !important;
box-shadow: 2px 0 4px rgba(0, 0, 0, 0.1) !important;
}
/* 左上角单元格(行号表头)同时是表头和行号 */
.csv-sticky-header.csv-sticky-row-number {
z-index: 25 !important;
background: var(--background-modifier-hover) !important;
}
/* 用户手动固定行样式 */
.csv-sticky-row {
position: sticky !important;
top: 30px !important; /* 在表头下方 */
z-index: 15 !important;
background: var(--background-primary) !important;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1) !important;
}
/* 用户手动固定列样式 */
.csv-sticky-col {
position: sticky !important;
left: 40px !important; /* 在行号列右侧 */
z-index: 15 !important;
background: var(--background-primary) !important;
box-shadow: 2px 0 4px rgba(0, 0, 0, 0.1) !important;
}
/* 同时是sticky行和列的单元格 */
.csv-sticky-row.csv-sticky-col {
z-index: 25 !important;
z-index: 18 !important;
box-shadow: 2px 2px 4px rgba(0, 0, 0, 0.15) !important;
}