您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Panel filter ĐKLHP, tìm kiếm Inbox/CTĐT, hover modal xem nhanh (auto tiếng Việt, UX đẹp cho HUSC)
当前为
// ==UserScript== // @name Tiến cụt - HUSC // @namespace http://tampermonkey.net/ // @version 2.6 // @description Panel filter ĐKLHP, tìm kiếm Inbox/CTĐT, hover modal xem nhanh (auto tiếng Việt, UX đẹp cho HUSC) // @author TienCut // @license MIT // @match https://student.husc.edu.vn/Studying/Courses/* // @match https://student.husc.edu.vn/News* // @match https://student.husc.edu.vn/Message/Inbox* // @match https://student.husc.edu.vn/TrainingProgram* // @grant GM_xmlhttpRequest // @grant GM_addStyle // ==/UserScript== (function() { 'use strict'; // Xác định trang const isCourses = /\/Studying\/Courses\//.test(location.pathname); const isNews = /\/News/.test(location.pathname); const isInbox = /\/Message\/Inbox/.test(location.pathname); const isTraining = /\/TrainingProgram/.test(location.pathname); // Tạo panel Tiến cụt luôn xuất hiện, liệt kê chức năng theo từng trang let panel = document.createElement('div'); panel.id = 'tiencut-panel'; let panelHTML = ` <div style="padding:11px 16px 13px 16px; background:#fffbe9; border:1.7px solid #ecd9b6; position:fixed; top:18px; right:25px; z-index:10010; box-shadow:0 1px 8px #bbb5; border-radius:11px; min-width:170px; max-width:240px;font-size:14px;"> <div style="font-weight:bold; font-size:15.7px; text-align:center;"> Tiến cụt </div> <hr style="border:0; border-top:1.35px solid #f2c77d; margin:8px 0 10px 0;"> <div id="tiencut-courses" style="display:${isCourses?'':'none'}"> <div>- Ẩn lớp đã đầy bằng checkbox</div> </div> <div id="tiencut-training" style="display:${isTraining?'':'none'}"> <div>- Tìm kiếm tên học phần, học kỳ</div> <input id="searchMon" type="text" placeholder="Tên học phần..." style="width:97%;padding:2px 4px;font-size:12px;margin:7px 0 5px 0;border:1px solid #b1d18b;border-radius:4px;outline:none;box-sizing:border-box"> <input id="searchHK" type="text" placeholder="Học kỳ..." style="width:97%;padding:2px 4px;font-size:12px;margin-bottom:5px;border:1px solid #b1d18b;border-radius:4px;outline:none;box-sizing:border-box"> </div> <div id="tiencut-inbox" style="display:${isInbox?'':'none'}"> <div>- Di chuột vào tiêu đề để xem nhanh nội dung tin nhắn</div> <input id="searchInboxSender" type="text" placeholder="Tìm theo tên người gửi..." style="width:97%;padding:2px 4px;font-size:12px;margin:7px 0 5px 0;border:1px solid #b1d18b;border-radius:4px;outline:none;box-sizing:border-box"> </div> <div id="tiencut-news" style="display:${isNews?'':'none'}"> <div>- Di chuột vào link thông báo để xem nhanh nội dung</div> </div> <hr style="border:0; border-top:1.15px solid #efb35b; margin:10px 0 7px 0;"> <div style="text-align:center; font-size:13px;color:#666;"> Góp ý qua <a href="https://www.facebook.com/tiencut2711" target="_blank" style="display:inline-block; vertical-align:middle; margin-left:7px;"> <img src="https://upload.wikimedia.org/wikipedia/commons/6/6c/Facebook_Logo_2023.png" style="height:19px;width:19px;border-radius:3px;vertical-align:middle;margin-bottom:2px;" alt="fb"/> </a> </div> </div> `; panel.innerHTML = panelHTML; document.body.appendChild(panel); if (isInbox) { function filterInboxRows() { let table = document.querySelector('table'); if(!table) return; let ths = Array.from(table.querySelectorAll('thead th, tr:first-child th, tr:first-child td')); // Tìm chỉ số cột tên người gửi, thường là cột thứ 2 -> thử tìm "người gửi" hoặc "tên" hoặc cột thứ 1 nếu không có let senderIdx = ths.findIndex(th => /gửi|sender|tên/i.test(th.textContent)); if (senderIdx === -1) senderIdx = 1; // fallback nếu không tìm ra thì là cột 1 let key = document.getElementById('searchInboxSender').value.trim().toLowerCase(); table.querySelectorAll('tbody tr').forEach(tr => { let tds = tr.querySelectorAll('td'); if(!tds[senderIdx]) { tr.style.display=''; return; } let content = tds[senderIdx].textContent.toLowerCase(); tr.style.display = (!key || content.includes(key)) ? '' : 'none'; }); } document.getElementById('searchInboxSender').addEventListener('input', filterInboxRows); window.addEventListener('DOMContentLoaded', filterInboxRows); } // Nếu là Training Program: filter tìm kiếm if (isTraining) { function filterRowsCTDT() { let table = document.querySelector('table'); if(!table) return; let ths = Array.from(table.querySelectorAll('thead th, tr:first-child th, tr:first-child td')); let monIndex = ths.findIndex(th => th.textContent.replace(/\s+/g, ' ').toLowerCase().includes('tên học phần') || th.textContent.toLowerCase().includes('môn học')); let hkIndex = ths.findIndex(th => /học[\s_-]*kỳ|hk|dự kiến/i.test(th.textContent)); if(monIndex < 0 || hkIndex < 0) return; let nameValue = document.getElementById('searchMon').value.trim().toLowerCase(); let hkValue = document.getElementById('searchHK').value.trim().toLowerCase(); table.querySelectorAll('tbody tr').forEach(tr => { let tds = tr.querySelectorAll('td'); if(tds.length<=Math.max(monIndex,hkIndex)) { tr.style.display=''; return; } let match = true; if(nameValue && !tds[monIndex].textContent.toLowerCase().includes(nameValue)) match = false; if(hkValue && !tds[hkIndex].textContent.toLowerCase().includes(hkValue)) match = false; tr.style.display = match ? '' : 'none'; }); } document.getElementById('searchMon').addEventListener('input', filterRowsCTDT); document.getElementById('searchHK').addEventListener('input', filterRowsCTDT); window.addEventListener('DOMContentLoaded', filterRowsCTDT); } // PHẦN CHỨC NĂNG TÙY TRANG // -- Nếu Courses: thêm checkbox filter lớp đã đầy if (isCourses) { let label = document.createElement('label'); label.style = "display:block; margin:10px 0 5px 0;font-size:13.5px;"; label.innerHTML = `<input type="checkbox" id="hideFullRows" style="vertical-align:middle; margin-right:4px"> Ẩn lớp đã đầy`; panel.querySelector('#tiencut-courses').appendChild(label); function parseInfo(cell) { let html = cell.innerHTML; let matches = html.match(/<b>(\d+)<\/b>.*?\/.*?(\d+)\s*$/i); if(matches && matches.length === 3){ return {dk: parseInt(matches[1],10), td: parseInt(matches[2],10)}; } else { let nums = html.replace(/<[^>]*>/g,'').split('/').map(x=>parseInt(x)); if(nums.length >= 2){ return {dk: nums[0], td: nums[nums.length-1]}; } } return null; } function filterRowsByFullbox() { let table = document.querySelector('table.table-striped'); if (!table) return; let ths = Array.from(table.querySelectorAll('thead th')); let svIndex = ths.findIndex(th => th.textContent.replace(/\s+/g, ' ').toLowerCase().includes('số sv')); table.querySelectorAll('tbody tr').forEach(tr => { let tds = tr.querySelectorAll('td'); if(tds.length<=svIndex) { tr.style.display = ''; return; } let info = parseInfo(tds[svIndex]); if(document.getElementById('hideFullRows').checked && info && info.dk >= info.td) tr.style.display = 'none'; else tr.style.display = ''; }); } document.getElementById('hideFullRows').addEventListener('change', filterRowsByFullbox); window.addEventListener('DOMContentLoaded', filterRowsByFullbox); } // ===== CSS Modal dùng chung ===== GM_addStyle(` #husc-modal { position:fixed;top:60px;left:50%;transform:translateX(-50%); background:#fff;box-shadow:0 2px 22px #2227;padding:18px 22px 14px 22px; z-index:99999;max-width:520px;min-width:180px;max-height:75vh; overflow:auto;border-radius:10px;display:none;font-size:15.2px; line-height:1.58; transition: opacity 0.15s; animation:fade-in 0.13s; } #husc-modal-close { position:absolute;right:17px;top:7px;cursor:pointer;font-weight:bold;color:#e00;font-size:22px;z-index:100000; } @keyframes fade-in { from {opacity:0;} to {opacity:1;} } `); // ======= Modal dùng chung cho cả 2 chức năng ======= let modal = document.createElement('div'); modal.id = 'husc-modal'; modal.innerHTML = '<span id="husc-modal-close">×</span><div id="husc-modal-content"></div>'; document.body.appendChild(modal); const modalContent = document.getElementById('husc-modal-content'); let modalHideTimeout = null; document.getElementById('husc-modal-close').onclick = function() { modal.style.display='none'; }; modal.addEventListener('mouseenter', () => { clearTimeout(modalHideTimeout); modal.style.display='block'; }); modal.addEventListener('mouseleave', () => { modalHideTimeout = setTimeout(()=>{ modal.style.display='none'; }, 250); }); // ===== Hover News ===== if(location.pathname.startsWith('/News')) { document.addEventListener('mouseover', function(e){ let link = e.target.closest('a[href*="/News/Content/"]'); if(link && !link.dataset.huscPreviewed){ link.dataset.huscPreviewed = 1; link.addEventListener('mouseenter', function(){ clearTimeout(modalHideTimeout); modal.style.display='block'; modalContent.innerHTML = 'Đang tải nội dung...'; GM_xmlhttpRequest({ method: "GET", url: link.href, onload: function(resp){ let parser = new DOMParser(); let doc = parser.parseFromString(resp.responseText, 'text/html'); let result = null; let h2 = Array.from(doc.querySelectorAll('h2')).find(el => el.textContent.trim().toUpperCase().includes('THÔNG BÁO')); if(h2) { let next = h2.nextElementSibling; while (next && !(next.classList && next.classList.contains('container-fluid'))) next = next.nextElementSibling; if(next && next.classList.contains('container-fluid')) result = next; } if (!result) result = doc.querySelector('.panel-main-content .hitec-content .row > .col-xs-12'); modalContent.innerHTML = result ? result.innerHTML : 'Không tìm thấy nội dung thông báo!'; }, onerror: function(){ modalContent.innerHTML = 'Lỗi tải trang!'; } }); }); link.addEventListener('mouseleave', function(){ modalHideTimeout = setTimeout(()=>{ if(!modal.matches(':hover')) modal.style.display='none'; }, 200); }); } }); } // ===== Hover Inbox ===== if(location.pathname.startsWith('/Message/Inbox')) { function extractMessageBody(doc) { let bodyBlock = doc.querySelector('.panel-main-content .container-fluid:last-of-type') || doc.querySelector('.hitec-content .container-fluid:last-of-type') || doc.querySelector('.panel-main-content') || doc.querySelector('.hitec-content'); if (!bodyBlock) { let divs = doc.querySelectorAll('.container-fluid'); for (let i=divs.length-1; i>=0; i--) { if(divs[i].querySelector('p')) { bodyBlock = divs[i]; break; } } } return bodyBlock ? bodyBlock.innerHTML : '<i>Không đọc được nội dung</i>'; } document.addEventListener('mouseover', function(e){ let link = e.target.closest('a[href^="/Message/Details/"], a[href^="/Message/View/"]'); if(link && !link.dataset.huscPreviewed){ link.dataset.huscPreviewed = 1; link.addEventListener('mouseenter', function(){ let msgUrl = link.getAttribute('href'); if(!msgUrl) return; clearTimeout(modalHideTimeout); modal.style.display = 'block'; modalContent.innerHTML = '<i>Đang tải nội dung...</i>'; GM_xmlhttpRequest({ method: "GET", url: link.href, onload: function(resp){ let parser = new DOMParser(); let doc = parser.parseFromString(resp.responseText, 'text/html'); let content = extractMessageBody(doc); content = content.replace(/<footer[\s\S]*?footer>/gi,'').replace(/<script[\s\S]*?script>/gi,''); modalContent.innerHTML = content.slice(0,1800); }, onerror: function(){ modalContent.innerHTML = 'Lỗi tải trang!'; } }); }); link.addEventListener('mouseleave', function(){ modalHideTimeout = setTimeout(()=>{ if(!modal.matches(':hover')) modal.style.display='none'; }, 180); }); } }); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址