// ==UserScript== // @name 任务隐藏 // @namespace https://scriptcat.org/ // @version 1.0.2 // @description 隐藏不需要看见的任务。悬浮球可拖拽、贴边半隐藏;点击展开胶囊与面板;长时间无操作自动收回为球。 // @author CC // @match *://*/* // @grant none // @run-at document-idle // @noframes // ==/UserScript== /* * 使用说明: * 1. 功能: * - 每行“操作”列末尾有 ✕ 按钮,点击即隐藏该任务(按“任务key”记录) * - 悬浮球:显示已隐藏数量;可任意拖动;贴近左/右边缘释放会吸附并半隐藏, * 鼠标悬停自动弹出;位置按域名持久化 * - 单击悬浮球展开为胶囊,再次单击打开/关闭管理面板(恢复/清空/临时显示) * - 约 6 秒无操作自动收回到悬浮球状态 */ (function () { 'use strict'; var ROOT_SEL = '.TaskManageTable'; var STORE_KEY = 'sctaskhide:' + location.host; var POS_KEY = 'sctaskhide:pos:' + location.host; var COL_NAME = 'el-table_1_column_2'; var COL_KEY = 'el-table_1_column_3'; var BALL_SIZE = 44; var SNAP_PX = 80; // 距边缘多少像素内吸附 var DRAG_TH = 6; // 位移超过该值视为拖拽而非点击 var IDLE_MS = 6000; // 无操作多久后收回成球 var hiddenMap = load(); var ghostMode = false; var pendingTimer = null; /* 悬浮球状态 */ var mode = 'ball'; // 'ball' | 'cap' var panelOpen = false; var hovering = false; var dragging = false; var idleTimer = null; var pos = loadPos(); /* ---------------- 存储 ---------------- */ function load() { try { var v = JSON.parse(localStorage.getItem(STORE_KEY)); return v && typeof v === 'object' ? v : {}; } catch (e) { return {}; } } function persist() { try { localStorage.setItem(STORE_KEY, JSON.stringify(hiddenMap)); } catch (e) {} updateCountUI(); } function loadPos() { try { var v = JSON.parse(localStorage.getItem(POS_KEY)); if (v && typeof v.x === 'number') { return { x: v.x, y: v.y, tuck: v.tuck === 'left' || v.tuck === 'right' ? v.tuck : 'none' }; } } catch (e) {} return null; } function savePos() { try { localStorage.setItem(POS_KEY, JSON.stringify(pos)); } catch (e) {} } /* ---------------- 工具 ---------------- */ function esc(s) { return String(s).replace(/[&<>"']/g, function (c) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]; }); } function cellText(row, colClass, idxFallback) { var td = row.querySelector('td.' + colClass); if (!td) td = row.children[idxFallback]; if (!td) return ''; var cell = td.querySelector('.cell') || td; return (cell.textContent || '').trim(); } function rowKey(row) { return cellText(row, COL_KEY, 2); } function rowName(row) { return cellText(row, COL_NAME, 1); } /* ---------------- 样式 ---------------- */ var css = [ '.sct-hide-btn{color:#f56c6c;cursor:pointer;font-size:15px;font-weight:700;line-height:1;', 'background:none;border:none;padding:0 2px;flex:none;}', '.sct-hide-btn:hover{transform:scale(1.25);}', // 注意:sct-op-cell 就加在 .cell 元素自身上,必须用复合选择器 .cell.sct-op-cell 'div.cell.sct-op-cell{display:flex !important;align-items:center;flex-wrap:nowrap !important;', 'gap:6px;overflow:visible !important;}', 'div.cell.sct-op-cell .el-button{margin:0 !important;padding:0 !important;font-size:13px !important;', 'white-space:nowrap;flex:none;}', 'div.cell.sct-op-cell i.iconfont{font-size:15px;}', /* ---- 悬浮球容器 ---- */ '#sct-widget{position:fixed;z-index:99999;left:0;top:0;cursor:grab;', 'touch-action:none;user-select:none;-webkit-user-select:none;', 'transition:transform .25s ease;will-change:left,top;}', '#sct-widget.sct-dragging{cursor:grabbing;transition:none;}', '#sct-widget.sct-tuck-l{transform:translateX(-52%) !important;}', '#sct-widget.sct-tuck-r{transform:translateX(52%) !important;}', '#sct-widget:not(.sct-dragging):hover{transform:none !important;}', /* 球态 */ '#sct-ball{width:44px;height:44px;border-radius:50%;border:none;color:#fff;font-size:15px;', 'font-weight:700;display:flex;align-items:center;justify-content:center;cursor:inherit;', 'background:radial-gradient(circle at 30% 30%,#79bbff,#409eff 60%,#2f7cd6);', 'box-shadow:0 3px 12px rgba(64,158,255,.45);padding:0;font-family:inherit;}', '#sct-ball .sct-n{background:#f56c6c;border-radius:9px;min-width:18px;height:18px;line-height:18px;', 'font-size:11px;padding:0 4px;margin-top:20px;margin-left:20px;box-shadow:0 1px 4px rgba(0,0,0,.35);}', /* 胶囊态(展开) */ '#sct-cap{display:none;border:none;border-radius:22px;background:#409eff;color:#fff;', 'padding:11px 16px;font-size:13px;cursor:inherit;white-space:nowrap;', 'box-shadow:0 3px 12px rgba(64,158,255,.45);font-family:inherit;}', '#sct-widget.sct-mode-cap #sct-ball{display:none;}', '#sct-widget.sct-mode-cap #sct-cap{display:block;}', '#sct-widget.sct-mode-cap{filter:drop-shadow(0 0 0 transparent);}', /* ---- 管理面板 ---- */ '#sct-panel{position:fixed;z-index:99998;width:320px;max-height:60vh;', 'background:#fff;color:#303133;border-radius:10px;box-shadow:0 4px 20px rgba(0,0,0,.25);', 'display:none;flex-direction:column;overflow:hidden;font-size:13px;font-family:inherit;}', '#sct-panel .sct-head{display:flex;align-items:center;gap:8px;padding:10px 12px;', 'border-bottom:1px solid #ebeef5;font-weight:600;}', '#sct-panel .sct-head label{margin-left:auto;font-weight:400;display:flex;align-items:center;gap:4px;cursor:pointer;}', '#sct-panel .sct-list{overflow:auto;padding:6px 0;}', '#sct-panel .sct-item{display:flex;align-items:center;gap:6px;padding:6px 12px;}', '#sct-panel .sct-item span{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}', '#sct-panel .sct-item i{color:#909399;font-style:normal;font-size:11px;}', '#sct-panel .sct-item button{background:#f56c6c;border:none;color:#fff;border-radius:4px;', 'padding:2px 8px;cursor:pointer;font-size:12px;}', '#sct-panel .sct-empty{padding:16px;text-align:center;color:#909399;}', '#sct-panel .sct-foot{padding:8px 12px;border-top:1px solid #ebeef5;text-align:right;}', '#sct-panel .sct-foot button{background:#909399;border:none;color:#fff;border-radius:4px;', 'padding:4px 10px;cursor:pointer;font-size:12px;}', '.sct-toast{position:fixed;top:18px;left:50%;transform:translateX(-50%);z-index:100001;', 'background:#67c23a;color:#fff;padding:8px 16px;border-radius:6px;font-size:13px;', 'box-shadow:0 2px 10px rgba(0,0,0,.2);}' ].join(''); var styleEl = document.createElement('style'); styleEl.textContent = css; document.head.appendChild(styleEl); /* ---------------- Toast ---------------- */ var toastTimer = null; function toast(msg) { var old = document.querySelector('.sct-toast'); if (old) old.remove(); var d = document.createElement('div'); d.className = 'sct-toast'; d.textContent = msg; document.body.appendChild(d); clearTimeout(toastTimer); toastTimer = setTimeout(function () { d.remove(); }, 1800); } /* ---------------- 行处理 ---------------- */ function ensureHideBtn(row) { if (row.querySelector('.sct-hide-btn')) return; var tds = row.querySelectorAll('td'); var last = tds[tds.length - 1]; if (!last) return; var cell = last.querySelector('.cell'); if (!cell) return; cell.classList.add('sct-op-cell'); var btn = document.createElement('button'); btn.className = 'sct-hide-btn'; btn.type = 'button'; btn.textContent = '\u2715'; btn.title = '隐藏此任务'; btn.addEventListener('click', function (e) { e.stopPropagation(); e.preventDefault(); var key = rowKey(row); if (!key) return; hiddenMap[key] = rowName(row) || key; persist(); applyAll(); toast('已隐藏:' + hiddenMap[key]); }); cell.appendChild(btn); } var FIXED_EXTRA = 36; function widenFixedColumn() { var root = document.querySelector(ROOT_SEL); if (!root) return; root.querySelectorAll('.el-table__fixed-right').forEach(function (fix) { if (fix.dataset.sctWidened) return; fix.dataset.sctWidened = '1'; fix.querySelectorAll('colgroup col').forEach(function (col) { var w = parseInt(col.getAttribute('width'), 10); if (w === 220) col.setAttribute('width', String(w + FIXED_EXTRA)); }); fix.style.width = (parseInt(fix.style.width, 10) || 220) + FIXED_EXTRA + 'px'; var patch = root.querySelector('.el-table__fixed-right-patch'); if (patch) { var pw = parseInt(patch.style.width, 10) || 0; if (pw > 0) patch.style.width = (pw + FIXED_EXTRA) + 'px'; } }); } function applyAll() { var root = document.querySelector(ROOT_SEL); if (!root) return; root.querySelectorAll('.el-table__body-wrapper tbody tr').forEach(function (row) { var key = rowKey(row); if (!key) return; ensureHideBtn(row); row.style.display = (!!hiddenMap[key] && !ghostMode) ? 'none' : ''; }); root.querySelectorAll('.el-table__fixed-body-wrapper tbody tr').forEach(function (row) { var key = rowKey(row); if (!key) return; ensureHideBtn(row); row.style.display = (!!hiddenMap[key] && !ghostMode) ? 'none' : ''; }); widenFixedColumn(); } /* ---------------- 悬浮球 ---------------- */ var widget, ballBtn, capBtn, panel, listBox; function buildUI() { widget = document.createElement('div'); widget.id = 'sct-widget'; widget.innerHTML = '' + ''; document.body.appendChild(widget); ballBtn = widget.querySelector('#sct-ball'); capBtn = widget.querySelector('#sct-cap'); panel = document.createElement('div'); panel.id = 'sct-panel'; panel.innerHTML = '