@@ -268,6 +266,11 @@ export default {
var oDiv = el;
var tbBodyDiv=oDiv.getElementsByClassName("el-table__body-wrapper")[0];
+ var startCell=null;
+ var endCell=null;
+ var selectedCells=[];
+ var selDiv=null;
+
// 鼠标按下事件
tbBodyDiv.onmousedown = function (ev) {
var evt = window.event || arguments[0];
@@ -288,10 +291,6 @@ export default {
const currentCellInfo=getCellPosition(evt.target);
vnode.context.currentCellInfo=currentCellInfo;
-
- // 绑定右键菜单
- bindRightContextMenu(evt);
-
}
return;
}
@@ -303,16 +302,26 @@ export default {
selNodes[i].classList.remove("seled")
}
}
+ // 清除粘贴板
+ vnode.context.clearBatchSelect();
+
+ // 获取鼠标按下的单元格
+ const cell = evt.target.closest('td');
+ if (!cell || cell.classList.contains('el-table__expanded-cell')) return;
+
+ // 获取单元格位置信息
+ const cellInfo = getCellInfo(cell);
+ if (!cellInfo) return;
+ startCell = cellInfo;
+ // console.log("===>startCell===>",startCell);
vnode.context.contextVisible=false;
- // 增加图层
- var xdTableObj = document.getElementById(vnode.context.tableId);
- var tbBody1=xdTableObj.getElementsByClassName("el-table__body-wrapper")[0];
+ // 增加图层
var selDiv = document.createElement("div");
selDiv.style.cssText = "position:absolute;width:0px;height:0px;font-size:0px;margin:0px;padding:0px;border:2px solid #409eff;background-color:#d9ecff;z-index:1000;filter:alpha(opacity:60);opacity:0.6;display:none;";
selDiv.id = "selectDiv-"+vnode.context.tableId;
- tbBody1.appendChild(selDiv);
+ tbBodyDiv.appendChild(selDiv);
// 表格对象
const refTableObj=vnode.context.getInstance();
@@ -350,15 +359,9 @@ export default {
){
vnode.context.isTableFocused=false;
vnode.context.mouseInScope=false;
- // cancelRightContextMenu();
return;
}
-
- // if(!tbBodyDiv.contains(document.activeElement)){
- // vnode.context.isTableFocused=false;
- // vnode.context.mouseInScope=false;
- // return;
- // }
+
vnode.context.isTableFocused=true;
vnode.context.mouseInScope=true;
@@ -367,7 +370,20 @@ export default {
// setMouseRowSelect(evt.target);
return;
}
- //
+
+ // 获取鼠标当前所在的单元格
+ const cell = evt.target.closest('td');
+ if (!cell || cell.classList.contains('el-table__expanded-cell')) return;
+
+ // 获取单元格位置信息
+ const cellInfo = getCellInfo(cell);
+ if (!cellInfo) return;
+
+ // 记录结束单元格
+ endCell = cellInfo;
+ // console.log("===>startCell==endCell=>",startCell,endCell);
+ // updateSelectionRange();
+
if(flag&&vnode.context.mouseflag){
vnode.context.multipleSelection=[];
@@ -402,7 +418,6 @@ export default {
var tbBody2=oDiv.getElementsByClassName("el-table__body-wrapper")[0];
var tbHeader2=oDiv.getElementsByClassName("el-table__header-wrapper")[0];
-
selDiv.style.left = Math.min(_x, startX)-tbPosRect2.left+tbBody2.scrollLeft + "px";
//表头的高度
selDiv.style.top = Math.min(_y, startY)-tbPosRect2.top - tbHeader2.offsetHeight+tbBody2.scrollTop+ "px";
@@ -465,15 +480,6 @@ export default {
vnode.context.clearEventBubble(evt);
};
- function bindRightContextMenu(evt){
- var xdTableObj = document.getElementById(vnode.context.tableId);
- xdTableObj.addEventListener("contextmenu", vnode.context.handleOnContextMenu);
- }
- function cancelRightContextMenu() {
- var xdTableObj = document.getElementById(vnode.context.tableId);
- xdTableObj.removeEventListener('contextmenu',vnode.context.handleOnContextMenu)
- // document.oncontextmenu = new Function("event.returnValue=true");
- }
// 获取el-table元素的位置信息
function getTablePosition(tbDom) {
const tableRect = tbDom.getBoundingClientRect();
@@ -494,6 +500,136 @@ export default {
}
}
+ // 获取单元格信息 ------------------
+ function getCellInfo(cell) {
+ if (!cell) return null;
+
+ // 获取行索引(排除表头)
+ const row = Array.from(cell.closest('tbody').children).indexOf(cell.parentElement);
+ if (row === -1) return null;
+
+ // 获取列索引
+ const column = Array.from(cell.parentElement.children).indexOf(cell);
+ if (column === -1) return null;
+
+ // 获取单元格内容
+ const content = cell.textContent.trim();
+
+ // 获取对应的属性名
+ // const table = vnode.context.$refs.table;
+ // const columnProperty = table.columns[column].property;
+ return { row:row, col:column, text:content,element: cell };
+ }
+
+ // 根据行列位置获取单元格元素
+ function getCellByPosition(rowIndex, columnIndex) {
+ // const table = vnode.context.$refs.table.elTable;
+ // const table=vnode.context.$refs.table.$refs.elTable;
+ // const rows = table.$el.querySelectorAll('tbody tr');
+
+ // console.log("===>tbBodyDiv===>",tbBodyDiv);
+ const rows = tbBodyDiv.querySelectorAll('tr');
+
+ if (rowIndex >= 0 && rowIndex < rows.length) {
+ const row = rows[rowIndex];
+ const cells = row.querySelectorAll('td');
+
+ if (columnIndex >= 0 && columnIndex < cells.length) {
+ return cells[columnIndex];
+ }
+ }
+
+ return null;
+ }
+
+ // 更新选择范围
+ function updateSelectionRange(finalize = false) {
+ if (!startCell || !endCell) return;
+
+ // 计算选择范围
+ const startRow = Math.min(startCell.row, endCell.row);
+ const endRow = Math.max(startCell.row, endCell.row);
+ const startColumn = Math.min(startCell.column, endCell.column);
+ const endColumn = Math.max(startCell.column, endCell.column);
+
+ if (finalize) {
+ // 最终确定选择范围
+ clearSelection();
+
+ // 选择范围内的所有单元格
+ for (let row = startRow; row <= endRow; row++) {
+ for (let col = startColumn; col <= endColumn; col++) {
+ const cell = getCellByPosition(row, col);
+ if (cell) {
+ const cellInfo = getCellInfo(cell);
+ selectCell(cellInfo);
+ }
+ }
+ }
+ } else {
+ // 实时显示选择范围指示器
+ const startCell = getCellByPosition(startRow, startColumn);
+ const endCell = getCellByPosition(endRow, endColumn);
+
+ if (startCell && endCell) {
+ const startRect = startCell.getBoundingClientRect();
+ const endRect = endCell.getBoundingClientRect();
+ const tableDom=vnode.context.$refs.table.$refs.elTable.$el;
+ const tableRect = tableDom.getBoundingClientRect();
+
+ // console.log("====>updateSelectionRange===>",tableRect,tableDom)
+
+ selDiv.style.left = `${startRect.left - tableRect.left}px`;
+ selDiv.style.top = `${startRect.top - tableRect.top}px`;
+ selDiv.style.width = `${endRect.right - startRect.left}px`;
+ selDiv.style.height = `${endRect.bottom - startRect.top}px`;
+ selDiv.style.display = 'block';
+ }
+ }
+ }
+
+ // 检查单元格是否已选中
+ function isCellSelected(cellInfo) {
+ if (!cellInfo) return false;
+
+ return selectedCells.some(cell =>
+ cell.row === cellInfo.row && cell.column === cellInfo.column
+ );
+ }
+
+ // 清除所有选择
+ function clearSelection() {
+ // 移除所有选中样式
+ selectedCells.forEach(cell => {
+ if (cell.element) {
+ cell.element.classList.remove('seled');
+ }
+ });
+
+ // 清空选中列表
+ selectedCells = [];
+
+ // 重置起始和结束单元格
+ startCell = null;
+ endCell = null;
+
+ }
+
+ // 选择单元格
+ function selectCell(cellInfo) {
+ if (!cellInfo || isCellSelected(cellInfo)) return;
+
+ // 添加到选中列表
+ selectedCells.push(cellInfo);
+
+ // console.log("===>selectedCells===>",selectedCells);
+
+ // 添加选中样式
+ if (cellInfo.element) {
+ cellInfo.element.classList.add('seled');
+ }
+ }
+
function setMouseCellSelect(cell,selRowList) {
try{
while(cell.tagName !== 'TD'){
@@ -547,6 +683,12 @@ export default {
}
//在鼠标抬起后做的重置
document.onmouseup = function () {
+
+ // 如果有结束单元格,更新选择范围
+ // if (endCell) {
+ // updateSelectionRange(true);
+ // }
+
//把鼠标移动事初始化
// document.onmousemove=null;
var xdTableObj = document.getElementById(vnode.context.tableId);
@@ -686,11 +828,6 @@ export default {
this.isNeedDbSaveTpl=false;
}
- // 监听全局焦点变化事件
- // document.addEventListener('focusin', this.handleGlobalFocusIn);
- // document.addEventListener('focusout', this.handleGlobalFocusOut);
-
- this.initKeyDownEvent();
// 初始化默认模版到本地
this.initDefaultTplList();
this.initStorage()
@@ -708,28 +845,6 @@ export default {
getUUID() {
return Math.random().toString(36).substring(3,10);
},
-
- // 处理全局焦点进入事件
- handleGlobalFocusIn(event) {
- // var tableEl = document.getElementById(this.tableId);
- // const hasFocus = tableEl.contains(event.target);
- // console.log("===>hasFocus===>",hasFocus,tableEl,event.target);
- // 表格获得焦点
- // if (hasFocus && !this.isTableFocused) {
- // this.tableHasFocus = true;
- // this.$message({
- // message: '表格已获得焦点',
- // type: 'success',
- // duration: 1500
- // });
- // }
- },
-
- handleXdTableBlur(){
- this.isTableFocused=false;
- console.log("===>handleXdTableBlur===>",this.isTableFocused);
- },
-
// 全局键盘事件处理
handleGlobalKeydown(event) {
// 检查是否按下了Ctrl+C组合键
@@ -742,18 +857,21 @@ export default {
}
}
},
+
handleOnContextMenu(event){
// vnode.context.clearEventBubble(event)
- var xdTableObj = document.getElementById(this.tableId);
- this.clearEventBubble(event)
- var menu = xdTableObj.querySelector("#contextMenu");
- let tbPosRect=this.getTablePosition(xdTableObj);
- menu.style.left = (event.clientX-tbPosRect.left+5) + "px";
- menu.style.top = (event.clientY-tbPosRect.top-35) + "px";
- menu.style.display = "block";
- menu.style.zIndex = 3000;
- this.contextVisible=true;
- event.preventDefault();
+ if(this.isTableFocused){
+ var xdTableObj = document.getElementById(this.tableId);
+ this.clearEventBubble(event)
+ var menu = xdTableObj.querySelector("#contextMenu");
+ let tbPosRect=this.getTablePosition(xdTableObj);
+ menu.style.left = (event.clientX-tbPosRect.left+5) + "px";
+ menu.style.top = (event.clientY-tbPosRect.top-35) + "px";
+ menu.style.display = "block";
+ menu.style.zIndex = 3000;
+ this.contextVisible=true;
+ event.preventDefault();
+ }
},
clearSelection(){
this.$nextTick(()=>{
@@ -763,9 +881,15 @@ export default {
initKeyDownEvent(){
document.addEventListener('keydown', this.handleGlobalKeydown );
+
+ var xdTableObj = document.getElementById(this.tableId);
+ xdTableObj.addEventListener("contextmenu", this.handleOnContextMenu);
},
removeKeyDownEvent(){
document.removeEventListener('keydown', this.handleGlobalKeydown );
+
+ var xdTableObj = document.getElementById(this.tableId);
+ xdTableObj.removeEventListener("contextmenu", this.handleOnContextMenu);
},
onTplSelectInputBlur(e) {
@@ -929,6 +1053,11 @@ export default {
}
return params;
},
+ clearBatchSelect(){
+ this.multipleSelection=[];
+ this.currentSelectStr=null;
+ this.clearClipboard();
+ },
// 鼠标框选----------
//当批量选中结束调用
handleBatchSelect(){
@@ -988,14 +1117,15 @@ export default {
handleCopySelect(event) {
this.contextVisible=false;
if(this.currentSelectStr){
+ let cpStr=this.currentSelectStr;
if (navigator.clipboard && window.isSecureContext) {
- // navigator clipboard 向剪贴板写文本
- this.$modal.msgSuccess('复制成功')
- return navigator.clipboard.writeText(this.currentSelectStr)
+ // navigator clipboard 向剪贴板写文本
+ this.$modal.msgSuccess('复制成功')
+ return navigator.clipboard.writeText(cpStr)
} else {
// 创建text area
const textArea = document.createElement('textarea')
- textArea.value = this.currentSelectStr
+ textArea.value = cpStr
// 使text area不在viewport,同时设置不可见
document.body.appendChild(textArea)
textArea.focus()
@@ -1009,6 +1139,27 @@ export default {
}
}
},
+ // 清除剪切板
+ clearClipboard() {
+ let cpStr='';
+ if (navigator.clipboard && window.isSecureContext) {
+ return navigator.clipboard.writeText(cpStr)
+ } else {
+ // 创建text area
+ const textArea = document.createElement('textarea')
+ textArea.value = cpStr
+ // 使text area不在viewport,同时设置不可见
+ document.body.appendChild(textArea)
+ textArea.focus()
+ textArea.select()
+ // this.$modal.msgSuccess('复制成功')
+ return new Promise((res, rej) => {
+ // 执行复制命令并移除文本框
+ document.execCommand('copy') ? res() : rej()
+ textArea.remove()
+ })
+ }
+ },
// 选择整行
handleSelectCurrentRow(evt){
this.contextVisible=false;
@@ -1085,7 +1236,6 @@ export default {
let that=this;
this.$nextTick(function () {
const wrapperTr = document.querySelector('#'+that.tableId+' .el-table__header-wrapper > table > thead > tr');
- // // console.log("===>wrapperTr==>",wrapperTr);
if(wrapperTr){
Sortable.create(wrapperTr, {
animation: 100,
@@ -1103,7 +1253,7 @@ export default {
that.storageList = arr;
- console.log("====>setHeaderSortable===>",that.storageList)
+ // console.log("====>setHeaderSortable===>",that.storageList)
this.storeTplToLocal(that.storageList)
this.initStorage()
this.updateTable()
@@ -1314,6 +1464,7 @@ export default {
this.config.attrs = this.$attrs
this.config.listeners = this.$listeners;
+
// 通过key值触发表格刷新,避免拖拽由于数组长度一致导致diff算法无法识别
// this.config.key = Math.random() + ''
// 控制下表格重新刷新
diff --git a/src/components/XdTable/indexNew.vue b/src/components/XdTable/indexNew.vue
index 9f387b1e..1e1ca387 100644
--- a/src/components/XdTable/indexNew.vue
+++ b/src/components/XdTable/indexNew.vue
@@ -311,12 +311,11 @@ export default {
}
}
- // 获取鼠标按下的单元格
+ // 获取鼠标按下的单元格
const cell = evt.target.closest('td');
if (!cell || cell.classList.contains('el-table__expanded-cell')) return;
// 获取单元格位置信息
-
const cellInfo = getCellInfo(cell);
if (!cellInfo) return;
startCell = cellInfo;