From 75b3fc64b05b56c52917fe4a761979c19a296c0e Mon Sep 17 00:00:00 2001 From: JayBridge <12310903@mail.sustech.edu.cn> Date: Thu, 19 Jun 2025 19:37:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=BC=BA=E6=8B=96=E6=8B=BD?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E6=B7=BB=E5=8A=A0=E8=A1=8C=E5=88=97?= =?UTF-8?q?=E9=AB=98=E4=BA=AE=E6=95=88=E6=9E=9C=E5=B9=B6=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E6=8F=92=E5=85=A5/=E5=88=A0=E9=99=A4=E6=8C=89=E9=92=AE=20#21?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/view/table-render.ts | 86 ++++++++++++++++++++++++++++------------ styles.css | 14 +++++++ 2 files changed, 74 insertions(+), 26 deletions(-) diff --git a/src/view/table-render.ts b/src/view/table-render.ts index 8d735e2..32aa94c 100644 --- a/src/view/table-render.ts +++ b/src/view/table-render.ts @@ -61,6 +61,19 @@ export function renderTable(options: TableRenderOptions) { tableEl.empty(); + // 拖拽状态变量移到函数外部作用域 + if (!(window as any)._csvLiteDragState) { + (window as any)._csvLiteDragState = { type: null, index: null }; + } + const dragState: { type: 'row' | 'col' | null, index: number | null } = (window as any)._csvLiteDragState; + function setDragState(type: 'row' | 'col' | null, index: number | null) { + dragState.type = type; + dragState.index = index; + tableEl.classList.remove('csv-dragging-row', 'csv-dragging-col'); + if (type === 'row') tableEl.classList.add('csv-dragging-row'); + if (type === 'col') tableEl.classList.add('csv-dragging-col'); + } + // 创建表头行(包含列号) const headerRow = tableEl.createEl("thead").createEl("tr"); @@ -93,9 +106,11 @@ export function renderTable(options: TableRenderOptions) { th.ondragstart = (e) => { e.dataTransfer?.setData("text/col-index", String(index)); th.classList.add("dragging"); + setDragState('col', index); }; th.ondragend = () => { th.classList.remove("dragging"); + setDragState(null, null); }; th.ondragover = (e) => { e.preventDefault(); @@ -107,25 +122,32 @@ export function renderTable(options: TableRenderOptions) { th.ondrop = (e) => { e.preventDefault(); th.classList.remove("drag-over"); + setDragState(null, null); const from = Number(e.dataTransfer?.getData("text/col-index")); const to = index; if (onColumnReorder && from !== to) { onColumnReorder(from, to); } }; - // 插入列操作按钮 - const insertLeft = th.createEl("button", { cls: "csv-insert-col-btn left" }); - insertLeft.innerText = "+"; - insertLeft.title = i18n.t("buttons.insertColBefore") || "Insert column before"; - insertLeft.onclick = (e) => { e.stopPropagation(); options.insertColAt(index, false); }; - const insertRight = th.createEl("button", { cls: "csv-insert-col-btn right" }); - insertRight.innerText = "+"; - insertRight.title = i18n.t("buttons.insertColAfter") || "Insert column after"; - insertRight.onclick = (e) => { e.stopPropagation(); options.insertColAt(index, true); }; - const delCol = th.createEl("button", { cls: "csv-del-col-btn" }); - delCol.innerText = "-"; - delCol.title = i18n.t("buttons.deleteColumn") || "Delete column"; - delCol.onclick = (e) => { e.stopPropagation(); options.deleteColAt(index); }; + // 插入列操作按钮(拖拽时隐藏) + if (!(dragState.type === 'col')) { + const insertLeft = th.createEl("button", { cls: "csv-insert-col-btn left" }); + insertLeft.innerText = "+"; + insertLeft.title = i18n.t("buttons.insertColBefore") || "Insert column before"; + insertLeft.onclick = (e) => { e.stopPropagation(); options.insertColAt(index, false); }; + const insertRight = th.createEl("button", { cls: "csv-insert-col-btn right" }); + insertRight.innerText = "+"; + insertRight.title = i18n.t("buttons.insertColAfter") || "Insert column after"; + insertRight.onclick = (e) => { e.stopPropagation(); options.insertColAt(index, true); }; + const delCol = th.createEl("button", { cls: "csv-del-col-btn" }); + delCol.innerText = "-"; + delCol.title = i18n.t("buttons.deleteColumn") || "Delete column"; + delCol.onclick = (e) => { e.stopPropagation(); options.deleteColAt(index); }; + } + // 拖拽高亮整列 + if (dragState.type === 'col' && dragState.index === index) { + th.classList.add('csv-dragging-highlight'); + } }); } @@ -177,9 +199,11 @@ export function renderTable(options: TableRenderOptions) { rowNumberCell.ondragstart = (e) => { e.dataTransfer?.setData("text/row-index", String(i)); rowNumberCell.classList.add("dragging"); + setDragState('row', i); }; rowNumberCell.ondragend = () => { rowNumberCell.classList.remove("dragging"); + setDragState(null, null); }; rowNumberCell.ondragover = (e) => { e.preventDefault(); @@ -191,25 +215,35 @@ export function renderTable(options: TableRenderOptions) { 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); } }; - // 插入行操作按钮 - 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')) { + 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 === i) { + 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` }, diff --git a/styles.css b/styles.css index 2ae8b41..443b51e 100644 --- a/styles.css +++ b/styles.css @@ -551,3 +551,17 @@ td input:focus { outline: 2px dashed var(--color-accent, #888); background: var(--color-accent-1, #f0f0f0); } + +/* 拖拽时整行/列高亮 */ +.csv-dragging-highlight { + background: var(--color-accent-1, #e6f7ff) !important; + box-shadow: 0 0 0 2px var(--color-accent, #1890ff) inset; +} + +/* 拖拽时隐藏所有插入/删除按钮 */ +.csv-dragging-row .csv-insert-row-btn, +.csv-dragging-row .csv-del-row-btn, +.csv-dragging-col .csv-insert-col-btn, +.csv-dragging-col .csv-del-col-btn { + display: none !important; +}