效果是将开启了换行的字段文本限制为仅显示前 3 行(这个数值可以改),如果文本超出 3 行,鼠标悬浮在单元格上时可以在悬浮提示中看到完整的文本
2025.02.01:重构逻辑,修复浮窗不生效的问题,实现了更通用且性能更高的方案
// 限制数据库换行文本最大行数 JS片段 - author: JeffreyChen // https://ld246.com/article/1716034408735 (function() { // TODO 1 需要与目标元素间隔 1px(跟原生的一起改) const showTooltip = (message, target) => { const targetRect = target.getBoundingClientRect(); if (targetRect.height === 0) { hideTooltip(); return; } const clonedTooltip = tooltipElement.cloneNode(true); clonedTooltip.id = "clonedAvCellTooltip"; clonedTooltip.removeAttribute("style"); clonedTooltip.className = "tooltip"; clonedTooltip.innerHTML = message; document.body.append(clonedTooltip); let top = targetRect.bottom; let left = targetRect.left; const topHeight = targetRect.top; const bottomHeight = window.innerHeight - top; clonedTooltip.style.maxHeight = Math.max(topHeight, bottomHeight) + "px"; if (top + clonedTooltip.clientHeight > window.innerHeight && topHeight > bottomHeight) { clonedTooltip.style.top = (targetRect.top - clonedTooltip.clientHeight) + "px"; } else { clonedTooltip.style.top = top + "px"; } if (left + clonedTooltip.clientWidth > window.innerWidth) { clonedTooltip.style.left = (window.innerWidth - 1 - clonedTooltip.clientWidth) + "px"; } else { clonedTooltip.style.left = Math.max(0, left) + "px"; } const cloneStyle = clonedTooltip.getAttribute("style"); if (tooltipElement.getAttribute("style") !== cloneStyle) { tooltipElement.setAttribute("style", cloneStyle); } if (tooltipElement.innerHTML !== clonedTooltip.innerHTML) { tooltipElement.innerHTML = clonedTooltip.innerHTML; } tooltipElement.classList.remove("fn__none"); clonedTooltip.remove(); }; const hideTooltip = () => { if (!tooltipElement.classList.contains("fn__none")) { tooltipElement.classList.add("fn__none"); } }; // 检查内容是否超出了单元格 const isCellOverflow = (cell) => { // 获取单元格的边界信息 const cellRect = cell.getBoundingClientRect(); // 获取单元格的所有子元素 const children = cell.querySelectorAll('.av__celltext'); // 遍历所有子元素 // 倒序,从最后一个元素开始检查 for (let i = children.length - 1; i >= 0; i--) { const child = children[i]; const childRect = child.getBoundingClientRect(); // 检查子元素是否超出单元格的边界(如果没有特殊情况,只检查底部就够了) if (childRect.bottom > cellRect.bottom) { return true; // 如果有任意一个子元素超出边界,返回 true } // if (childRect.top < cellRect.top || // childRect.bottom > cellRect.bottom || // childRect.left < cellRect.left || // childRect.right > cellRect.right) { // return true; // } } return false; // 如果没有子元素超出边界,返回 false }; const getMessage = (cell) => { // 将所有文本组合成一个字符串以用于显示 tooltip const textElements = Array.from(cell.querySelectorAll('.av__celltext')); // 特殊处理 .av__cell[data-dtype="relation"] 和 .av__cell[data-dtype="rollup"] 元素 if (cell.dataset.dtype === 'relation' || cell.dataset.dtype === 'rollup') { // 获取文本、去除每个子项内部的换行符、每个子项之间添加换行符 return textElements.map(textElement => textElement.textContent.replace(/\n+/g, ' ').trim()).join(',\n'); } else { // 获取文本,子项之间加上逗号分隔 return textElements.map(textElement => textElement.textContent.trim()).join(', '); } }; const showAvCellTooltip = (event) => { let cell = event.target; if (!cell || cell.nodeType === 9) return false; if (cell.classList.contains('av__cell')) { // 继续执行 } else if (cell.parentElement?.classList.contains('av__cell')) { cell = cell.parentElement; } else if (cell.parentElement?.parentElement?.classList.contains('av__cell')) { // 关联、汇总字段有三层元素 cell = cell.parentElement.parentElement; } else { // 不存在 return false; } // 不是换行 | 是字段标题 if (cell.getAttribute("data-wrap") !== "true" || cell.classList.contains('av__cell--header')) return false; // 内容超出了单元格才需要显示悬浮提示 if (!isCellOverflow(cell)) return false; // 获取 tooltip 显示的内容 const message = getMessage(cell); if (message) { showTooltip(message, cell); return true; } }; let tooltipElement = Object.assign(document.createElement("div"), { id: "avCellTooltip", className: "tooltip fn__none" }); (async () => { if (!!document.getElementById("sidebar")) return; // 手机界面不运行 document.body.insertAdjacentElement("beforeend", tooltipElement); const tryShowAvCellTooltip = (event) => { if (!showAvCellTooltip(event)) hideTooltip(); }; document.addEventListener('mouseover', tryShowAvCellTooltip); // 查找代码片段自身 let script; const keyword = "限制数据库换行文本最大行数-b6fb408a-d400-4874-b357-06fcdce67ca6"; // 根据这个关键词来查找 const foundScript = Array.from(document.head.querySelectorAll("script[id^=snippetJS]")).find(script => script.textContent.includes(keyword)); if (foundScript) { const scriptId = foundScript.id; script = document.getElementById(scriptId); } if (script) { // 监听 head,检查代码片段是否被移除 const observer = new MutationObserver(function (mutationsList, observer) { for (const mutation of mutationsList) { mutation.removedNodes.forEach(function (node) { if (node === script) { observer.disconnect(); // 移除监听 document.removeEventListener('mouseover', tryShowAvCellTooltip); // 移除监听 document.querySelector('#avCellStyle').remove(); // 移除样式 document.querySelector('#avCellTooltip').remove(); // 移除元素 } }); } }); observer.observe(document.head, { childList: true, subtree: true }); } })(); // 创建并添加 CSS 代码 const style = document.createElement('style'); style.id = 'avCellStyle'; style.textContent = `/* 限制数据库换行文本最大行数 CSS片段 */ .av__row:not(.av__row--header) .av__cell[data-wrap="true"]:not([data-dtype="mSelect"]):not([data-dtype="mAsset"]) { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; /* 最多3行 */ overflow: hidden; } /* 针对关联字段、汇总字段 */ .av__row:not(.av__row--header) .av__cell[data-wrap="true"][data-dtype="relation"], .av__row:not(.av__row--header) .av__cell[data-wrap="true"][data-dtype="rollup"] { white-space: normal; } /* 多选、资源字段变为滚动容器 */ .av__row:not(.av__row--header) .av__cell[data-wrap="true"][data-dtype="mSelect"], .av__row:not(.av__row--header) .av__cell[data-wrap="true"][data-dtype="mAsset"] { max-height: calc(1.625em * 3 + 10px); /* 3行文本的高度 */ overflow-y: auto; } #clonedAvCellTooltip { animation: unset; opacity: 0; pointer-events: none; }`; document.head.appendChild(style); })();
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于