From b8c675228dd546365c91a0b1a8754e913a959de6 Mon Sep 17 00:00:00 2001 From: JayBridge <12310903@mail.sustech.edu.cn> Date: Mon, 30 Jun 2025 11:26:39 +0800 Subject: [PATCH] chore: update version to 1.1.0 in manifest, package.json, and package-lock.json; refactor table rendering logic to improve column header functionality --- manifest.json | 2 +- package-lock.json | 2 +- package.json | 2 +- src/view/table-render.ts | 239 +++++++++++++++++---------------------- 4 files changed, 106 insertions(+), 139 deletions(-) diff --git a/manifest.json b/manifest.json index cdd3b2e..dc927cc 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "csv-lite", "name": "CSV Lite", - "version": "1.0.6", + "version": "1.1.0", "minAppVersion": "1.8.0", "description": "Just open and edit CSV files directly, no more. Keep it simple.", "author": "Jay Bridge", diff --git a/package-lock.json b/package-lock.json index caba2cf..3d395f6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "obsidian-csv", - "version": "1.0.6", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index 963ca39..acfdedf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-csv", - "version": "1.0.6", + "version": "1.1.0", "description": "CSV viewer and editor for Obsidian", "main": "main.js", "scripts": { diff --git a/src/view/table-render.ts b/src/view/table-render.ts index c28bcc0..26d56ea 100644 --- a/src/view/table-render.ts +++ b/src/view/table-render.ts @@ -74,18 +74,117 @@ export function renderTable(options: TableRenderOptions) { if (type === 'col') tableEl.classList.add('csv-dragging-col'); } - // 创建表头行(包含列号) - const headerRow = tableEl.createEl("thead").createEl("tr"); - // 计算初始列宽(如果未设置) if (columnWidths.length === 0 && tableData[0]) { const widths = TableUtils.calculateColumnWidths(tableData); columnWidths.splice(0, columnWidths.length, ...widths); } + // 创建表格主体 - 所有行都作为普通数据行处理 + const tableBody = tableEl.createEl("tbody"); + + // 从索引0开始,包括第一行 + for (let i = 0; i < tableData.length; i++) { + const row = tableData[i]; + const tableRow = tableBody.createEl("tr"); + const rowNumberCell = tableRow.createEl("td", { cls: "csv-row-number", attr: { draggable: "true" } }); + rowNumberCell.textContent = i.toString(); + rowNumberCell.onclick = (e) => { + e.stopPropagation(); + selectRow(i); + }; + // 拖拽排序事件 + rowNumberCell.ondragstart = (e) => { + e.dataTransfer?.setData("text/row-index", String(i)); + rowNumberCell.classList.add("dragging"); + setDragState('row', i); + if (typeof requestSave === 'function') requestSave(); + }; + rowNumberCell.ondragend = () => { + rowNumberCell.classList.remove("dragging"); + setDragState(null, null); + if (typeof requestSave === 'function') requestSave(); + }; + rowNumberCell.ondragover = (e) => { + e.preventDefault(); + rowNumberCell.classList.add("drag-over"); + }; + rowNumberCell.ondragleave = () => { + rowNumberCell.classList.remove("drag-over"); + }; + rowNumberCell.ondrop = (e) => { + e.preventDefault(); + rowNumberCell.classList.remove("drag-over"); + setDragState(null, null); + const from = Number(e.dataTransfer?.getData("text/row-index")); + const to = i; + if (onRowReorder && from !== to) { + onRowReorder(from, to); + } + }; + // 插入行操作按钮(拖拽时隐藏) + if (!(dragState.type === 'row')) { + const insertAbove = rowNumberCell.createEl("button", { cls: "csv-insert-row-btn above" }); + insertAbove.innerText = "+"; + insertAbove.title = i18n.t("buttons.insertRowBefore") || "Insert row before"; + insertAbove.onclick = (e) => { e.stopPropagation(); options.insertRowAt(i, false); }; + const insertBelow = rowNumberCell.createEl("button", { cls: "csv-insert-row-btn below" }); + insertBelow.innerText = "+"; + insertBelow.title = i18n.t("buttons.insertRowAfter") || "Insert row after"; + insertBelow.onclick = (e) => { e.stopPropagation(); options.insertRowAt(i, true); }; + const delRow = rowNumberCell.createEl("button", { cls: "csv-del-row-btn" }); + delRow.innerText = "-"; + delRow.title = i18n.t("buttons.deleteRow") || "Delete row"; + delRow.onclick = (e) => { e.stopPropagation(); options.deleteRowAt(i); }; + } + // 拖拽高亮整行及相邻行 + if (dragState.type === 'row' && dragState.index !== null) { + const rowStart = Math.max(0, dragState.index - 2); + const rowEnd = Math.min(tableData.length - 1, dragState.index + 2); + if (i >= rowStart && i <= rowEnd) { + rowNumberCell.classList.add('csv-dragging-highlight'); + Array.from(tableRow.children).forEach(td => { + (td as HTMLElement).classList.add('csv-dragging-highlight'); + }); + } + } + row.forEach((cell, j) => { + const td = tableRow.createEl("td", { + attr: { style: `width: ${columnWidths[j] || 100}px` }, + }); + const input = td.createEl("input", { + cls: "csv-cell-input", + attr: { value: cell }, + }); + setupAutoResize(input); + input.oninput = (ev) => { + if (ev.currentTarget instanceof HTMLInputElement) { + saveSnapshot(); + tableData[i][j] = ev.currentTarget.value; + if (activeCellEl === ev.currentTarget && editInput) { + editInput.value = ev.currentTarget.value; + } + // 新增:表格单元格编辑时同步编辑栏 + if (renderEditBar) { + renderEditBar(i, j, ev.currentTarget); + } + requestSave(); + if (autoResize) { + adjustInputHeight(ev.currentTarget); + } + } + }; + input.onfocus = (ev) => { + setActiveCell(i, j, ev.currentTarget as HTMLInputElement); + }; + }); + } + + // 创建列号行(在表格顶部) + const headerRow = tableEl.createEl("thead").createEl("tr"); + // 添加左上角单元格 const cornerTh = headerRow.createEl("th", { cls: "csv-corner-cell" }); - // 可选:在左上角添加插入列/行按钮 // 创建列号行 if (tableData[0]) { @@ -161,138 +260,6 @@ export function renderTable(options: TableRenderOptions) { }); } - // 创建表头数据行 - const dataHeaderRow = tableEl.createEl("thead").createEl("tr"); - const headerRowNumber = dataHeaderRow.createEl("th", { cls: "csv-row-number" }); - headerRowNumber.textContent = "0"; - - if (tableData[0]) { - tableData[0].forEach((headerCell, index) => { - const th = dataHeaderRow.createEl("th", { - cls: "csv-th", - attr: { - style: `width: ${columnWidths[index] || 100}px`, - }, - }); - const headerInput = th.createEl("input", { - cls: "csv-cell-input", - attr: { value: headerCell }, - }); - headerInput.oninput = (ev) => { - if (ev.currentTarget instanceof HTMLInputElement) { - saveSnapshot(); - tableData[0][index] = ev.currentTarget.value; - requestSave(); - } - }; - headerInput.onfocus = (ev) => { - setActiveCell(0, index, ev.currentTarget as HTMLInputElement); - }; - // 在列号单元格中添加拖拽事件处理逻辑 - const resizeHandle = th.createEl("div", { cls: "resize-handle" }); - setupColumnResize(resizeHandle, index); - }); - } - - // 创建表格主体 - const tableBody = tableEl.createEl("tbody"); - const startRowIndex = tableData.length > 1 ? 1 : 0; - for (let i = startRowIndex; i < tableData.length; i++) { - const row = tableData[i]; - const tableRow = tableBody.createEl("tr"); - const rowNumberCell = tableRow.createEl("td", { cls: "csv-row-number", attr: { draggable: "true" } }); - rowNumberCell.textContent = i.toString(); - rowNumberCell.onclick = (e) => { - e.stopPropagation(); - selectRow(i); - }; - // 拖拽排序事件 - rowNumberCell.ondragstart = (e) => { - e.dataTransfer?.setData("text/row-index", String(i)); - rowNumberCell.classList.add("dragging"); - setDragState('row', i); - if (typeof requestSave === 'function') requestSave(); - }; - rowNumberCell.ondragend = () => { - rowNumberCell.classList.remove("dragging"); - setDragState(null, null); - if (typeof requestSave === 'function') requestSave(); - }; - rowNumberCell.ondragover = (e) => { - e.preventDefault(); - rowNumberCell.classList.add("drag-over"); - }; - rowNumberCell.ondragleave = () => { - rowNumberCell.classList.remove("drag-over"); - }; - rowNumberCell.ondrop = (e) => { - e.preventDefault(); - rowNumberCell.classList.remove("drag-over"); - setDragState(null, null); - const from = Number(e.dataTransfer?.getData("text/row-index")); - const to = i; - if (onRowReorder && from !== to) { - onRowReorder(from, to); - } - }; - // 插入行操作按钮(拖拽时隐藏) - if (!(dragState.type === 'row')) { - const insertAbove = rowNumberCell.createEl("button", { cls: "csv-insert-row-btn above" }); - insertAbove.innerText = "+"; - insertAbove.title = i18n.t("buttons.insertRowBefore") || "Insert row before"; - insertAbove.onclick = (e) => { e.stopPropagation(); options.insertRowAt(i, false); }; - const insertBelow = rowNumberCell.createEl("button", { cls: "csv-insert-row-btn below" }); - insertBelow.innerText = "+"; - insertBelow.title = i18n.t("buttons.insertRowAfter") || "Insert row after"; - insertBelow.onclick = (e) => { e.stopPropagation(); options.insertRowAt(i, true); }; - const delRow = rowNumberCell.createEl("button", { cls: "csv-del-row-btn" }); - delRow.innerText = "-"; - delRow.title = i18n.t("buttons.deleteRow") || "Delete row"; - delRow.onclick = (e) => { e.stopPropagation(); options.deleteRowAt(i); }; - } - // 拖拽高亮整行及相邻行 - if (dragState.type === 'row' && dragState.index !== null) { - const rowStart = Math.max(startRowIndex, dragState.index - 2); - const rowEnd = Math.min(tableData.length - 1, dragState.index + 2); - if (i >= rowStart && i <= rowEnd) { - rowNumberCell.classList.add('csv-dragging-highlight'); - Array.from(tableRow.children).forEach(td => { - (td as HTMLElement).classList.add('csv-dragging-highlight'); - }); - } - } - row.forEach((cell, j) => { - const td = tableRow.createEl("td", { - attr: { style: `width: ${columnWidths[j] || 100}px` }, - }); - const input = td.createEl("input", { - cls: "csv-cell-input", - attr: { value: cell }, - }); - setupAutoResize(input); - input.oninput = (ev) => { - if (ev.currentTarget instanceof HTMLInputElement) { - saveSnapshot(); - tableData[i][j] = ev.currentTarget.value; - if (activeCellEl === ev.currentTarget && editInput) { - editInput.value = ev.currentTarget.value; - } - // 新增:表格单元格编辑时同步编辑栏 - if (renderEditBar) { - renderEditBar(i, j, ev.currentTarget); - } - requestSave(); - if (autoResize) { - adjustInputHeight(ev.currentTarget); - } - } - }; - input.onfocus = (ev) => { - setActiveCell(i, j, ev.currentTarget as HTMLInputElement); - }; - }); - } - // 滚动条容器宽度同步逻辑建议由主类处理 // Add event listener to deselect active row or column when clicking outside