fix: 列尾按住拖拽图标不松反复进行增删列时,计数结果不准
This commit is contained in:
parent
7c26b9f1c2
commit
0c3697b405
@ -321,37 +321,44 @@ export function useTableHandle(editorRef: Ref<Editor | null>) {
|
||||
function addColRight() { execCmd('addColumnAfter') }
|
||||
|
||||
/**
|
||||
* 在表格中添加行列。
|
||||
* 先用 posAtCoords 把光标设到表格内指定位置,再执行命令。
|
||||
* 解决了点击加号条时 selection 不在表格内导致命令静默失败的问题。
|
||||
* 在表格中指定单元格位置执行命令。
|
||||
* 先用 posAtCoords 定位到目标单元格,设置 CellSelection,
|
||||
* 再通过 editor.chain()(不调 .focus(),避免将 CellSelection 转为 TextSelection 导致列命令偏移)
|
||||
* 执行表操作命令。
|
||||
* @returns 命令是否执行成功
|
||||
*/
|
||||
function execTableCmdAtCell(name: string, targetCellSelector: string) {
|
||||
function execTableCmdAtCell(name: string, targetCellSelector: string): boolean {
|
||||
const editor = editorRef.value
|
||||
if (!editor?.view) return
|
||||
if (!editor?.view) return false
|
||||
const view = editor.view
|
||||
const table = getTableEl()
|
||||
if (!table) return
|
||||
if (!table) return false
|
||||
|
||||
const cell = table.querySelector(targetCellSelector) as HTMLElement | null
|
||||
if (!cell) return
|
||||
if (!cell) return false
|
||||
|
||||
const rect = cell.getBoundingClientRect()
|
||||
const coords = view.posAtCoords({ left: rect.left + 2, top: rect.top + 2 })
|
||||
if (!coords) return
|
||||
if (!coords) return false
|
||||
|
||||
const $pos = view.state.doc.resolve(coords.pos)
|
||||
const $cell = cellAround($pos)
|
||||
if (!$cell) return
|
||||
if (!$cell) return false
|
||||
|
||||
// 把 selection 放到目标单元格
|
||||
const tr = view.state.tr
|
||||
tr.setSelection(new CellSelection($cell))
|
||||
view.dispatch(tr)
|
||||
// 先 focus view,再设置 CellSelection
|
||||
view.focus()
|
||||
view.dispatch(view.state.tr.setSelection(new CellSelection($cell)))
|
||||
|
||||
// 从已更新 state 创建 chain 执行命令
|
||||
// 注意:不使用 .focus(),避免将 CellSelection 转为 TextSelection
|
||||
const chain = editor.chain()
|
||||
const cmd = (chain as any)[name]
|
||||
if (typeof cmd !== 'function') return false
|
||||
const result = cmd().run()
|
||||
|
||||
// 执行命令并刷新 tableBbox 使加号条跟随表格新尺寸
|
||||
execCmd(name)
|
||||
refreshTableBbox()
|
||||
closeAllMenus()
|
||||
return result
|
||||
}
|
||||
|
||||
/** 刷新 tableBbox 使加号条跟表格新尺寸 */
|
||||
@ -366,40 +373,41 @@ export function useTableHandle(editorRef: Ref<Editor | null>) {
|
||||
}
|
||||
|
||||
/** 在最后一行下方加行 */
|
||||
function addRowBelowSticky() {
|
||||
execTableCmdAtCell('addRowAfter', 'tbody tr:last-child td, tbody tr:last-child th')
|
||||
function addRowBelowSticky(): boolean {
|
||||
return execTableCmdAtCell('addRowAfter', 'tbody tr:last-child td, tbody tr:last-child th')
|
||||
}
|
||||
|
||||
/** 在最后一列右侧加列 */
|
||||
function addColRightSticky() {
|
||||
execTableCmdAtCell('addColumnAfter', 'tbody tr:last-child td:last-child, tbody tr:last-child th:last-child')
|
||||
function addColRightSticky(): boolean {
|
||||
return execTableCmdAtCell('addColumnAfter', 'tbody tr:last-child td:last-child, tbody tr:last-child th:last-child')
|
||||
}
|
||||
|
||||
/** 删除最后一行(向上拖拽时使用) */
|
||||
function deleteLastRow() {
|
||||
function deleteLastRow(): boolean {
|
||||
const editor = editorRef.value
|
||||
if (!editor?.view) return
|
||||
if (!editor?.view) return false
|
||||
const table = getTableEl()
|
||||
if (table) {
|
||||
const rows = table.querySelectorAll('tbody tr')
|
||||
if (rows.length <= 1) return
|
||||
if (rows.length <= 1) return false
|
||||
}
|
||||
execTableCmdAtCell('deleteRow', 'tbody tr:last-child td, tbody tr:last-child th')
|
||||
return execTableCmdAtCell('deleteRow', 'tbody tr:last-child td, tbody tr:last-child th')
|
||||
}
|
||||
|
||||
/** 删除最后一列(向左拖拽时使用) */
|
||||
function deleteLastCol() {
|
||||
function deleteLastCol(): boolean {
|
||||
const editor = editorRef.value
|
||||
if (!editor?.view) return
|
||||
if (!editor?.view) return false
|
||||
const table = getTableEl()
|
||||
if (table) {
|
||||
const firstRow = table.querySelector('tbody tr:first-child')
|
||||
if (firstRow) {
|
||||
const cells = firstRow.querySelectorAll('td, th')
|
||||
if (cells.length <= 1) return
|
||||
}
|
||||
if (!table) return false
|
||||
// 与 deleteLastRow 保持对称:检查所有行中最少列数,防止删除最后一列
|
||||
const rows = table.querySelectorAll('tbody tr')
|
||||
let minColCount = Infinity
|
||||
for (const row of rows) {
|
||||
minColCount = Math.min(minColCount, row.querySelectorAll('td, th').length)
|
||||
}
|
||||
execTableCmdAtCell('deleteColumn', 'tbody tr:last-child td:last-child, tbody tr:last-child th:last-child')
|
||||
if (minColCount <= 1) return false
|
||||
return execTableCmdAtCell('deleteColumn', 'tbody tr:last-child td:last-child, tbody tr:last-child th:last-child')
|
||||
}
|
||||
|
||||
/** 删除最后一行(向上拖拽时使用) */
|
||||
|
||||
@ -197,6 +197,8 @@ function onAddColStripMouseDown(e: MouseEvent) {
|
||||
|
||||
/** 拖拽启动阈值(px),超过此距离才认为是在拖拽 */
|
||||
const DRAG_THRESHOLD = 5
|
||||
/** 单次 mousemove 最多增删数量,防止死循环 */
|
||||
const MAX_DRAG_ITERATIONS = 50
|
||||
|
||||
function onDragAddRow(e: MouseEvent) {
|
||||
if (!_isDragging.value && Math.abs(e.clientY - _dragStartY.value) < DRAG_THRESHOLD) return
|
||||
@ -204,15 +206,22 @@ function onDragAddRow(e: MouseEvent) {
|
||||
const deltaY = e.clientY - _dragStartY.value
|
||||
const targetCount = deltaY >= 0 ? Math.floor(deltaY / 28) : -Math.floor(-deltaY / 28)
|
||||
|
||||
// Add rows when target exceeds current net count
|
||||
while (targetCount > _netRowCount.value) {
|
||||
_netRowCount.value++
|
||||
addRowBelowSticky()
|
||||
// 只在操作成功时更新计数,防止静默失败导致计数漂移
|
||||
let safety = 0
|
||||
while (targetCount > _netRowCount.value && safety++ < MAX_DRAG_ITERATIONS) {
|
||||
if (addRowBelowSticky()) {
|
||||
_netRowCount.value++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Remove rows when target falls below current net count (undo additions or delete originals)
|
||||
while (targetCount < _netRowCount.value) {
|
||||
_netRowCount.value--
|
||||
deleteLastRow()
|
||||
safety = 0
|
||||
while (targetCount < _netRowCount.value && safety++ < MAX_DRAG_ITERATIONS) {
|
||||
if (deleteLastRow()) {
|
||||
_netRowCount.value--
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
updateOverlayRect()
|
||||
}
|
||||
@ -223,15 +232,22 @@ function onDragAddCol(e: MouseEvent) {
|
||||
const deltaX = e.clientX - _dragStartX.value
|
||||
const targetCount = deltaX >= 0 ? Math.floor(deltaX / 28) : -Math.floor(-deltaX / 28)
|
||||
|
||||
// Add columns when target exceeds current net count
|
||||
while (targetCount > _netColCount.value) {
|
||||
_netColCount.value++
|
||||
addColRightSticky()
|
||||
// 只在操作成功时更新计数,防止静默失败导致计数漂移
|
||||
let safety = 0
|
||||
while (targetCount > _netColCount.value && safety++ < MAX_DRAG_ITERATIONS) {
|
||||
if (addColRightSticky()) {
|
||||
_netColCount.value++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
// Remove columns when target falls below current net count (undo additions or delete originals)
|
||||
while (targetCount < _netColCount.value) {
|
||||
_netColCount.value--
|
||||
deleteLastCol()
|
||||
safety = 0
|
||||
while (targetCount < _netColCount.value && safety++ < MAX_DRAG_ITERATIONS) {
|
||||
if (deleteLastCol()) {
|
||||
_netColCount.value--
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
updateOverlayRect()
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user