您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Better moyenne experience
// ==UserScript== // @name Esprit Moyenne // @namespace http://tampermonkey.net/ // @version 2025-06-12 // @description Better moyenne experience // @author NotSoHealthy // @match https://esprit-tn.com/esponline/Etudiants/Resultat2021.aspx // @icon https://www.google.com/s2/favicons?sz=64&domain=esprit-tn.com // @grant none // @license MIT // ==/UserScript== (async function() { const style = document.createElement('style'); style.innerHTML = ` .row{ margin: 0; } .table-header { color: white; background-color: #A80000; font-weight: bold; } .moyenne-high { background-color: green; color: white; } .moyenne-low { background-color: red; color: white; } #ContentPlaceHolder1_GridView1 { width: 100%; border-collapse: collapse; } #ContentPlaceHolder1_GridView1 th, #ContentPlaceHolder1_GridView1 td { border: 1px solid #ddd; padding: 8px; } #ContentPlaceHolder1_GridView1 tr:nth-child(even) { background-color: #f2f2f2; } #ContentPlaceHolder1_GridView1 tr:hover { background-color: #ddd; } #ContentPlaceHolder1_GridView1 .table-header:hover { background-color: #A80000;; } #downloadButton { margin-bottom: 10px; padding: 10px 20px; font-size: 16px; cursor: pointer; background-color: #A80000; color: white; border: none; border-radius: 5px; transition: transform 0.2s ease; } #downloadButton:hover { transform: scale(1.05); background-color: #CC0000; } `; document.head.appendChild(style); function loadScript(src) { return new Promise(function(resolve, reject) { if (document.querySelector(`script[src="${src}"]`)) { resolve(); return; } const script = document.createElement('script'); script.src = src; script.onload = () => resolve(); script.onerror = () => reject(new Error(`Failed to load script ${src}`)); document.head.appendChild(script); }); } await loadScript('https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js'); await loadScript('https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js'); function getStudentDetails() { const nameElement = document.getElementById('Label2'); const classElement = document.getElementById('Label3'); const studentName = nameElement ? nameElement.textContent.trim() : 'Unknown Student'; const studentClass = classElement ? classElement.textContent.trim() : 'Unknown Class'; return { studentName, studentClass }; } function getLogoImage() { const logoElement = document.querySelector('.img-responsive img'); return logoElement ? logoElement.src : null; } function tableToJson(table) { const data = []; const headers = Array.from(table.rows[0].cells).map(cell => cell.innerText.toLowerCase().replace(/ /g, '') ); for (let i = 1; i < table.rows.length; i++) { const row = table.rows[i]; const rowData = {}; headers.forEach((header, index) => { rowData[header] = row.cells[index].innerText; }); data.push(rowData); } data.forEach(item => { item.coef = parseFloat(item.coef.replace(',', '.')); item.note_exam = parseFloat(item.note_exam.replace(',', '.')); item.note_cc = parseFloat(item.note_cc.replace(',', '.')); item.note_tp = parseFloat(item.note_tp.replace(',', '.')); }); return data; } const table = document.getElementById('ContentPlaceHolder1_GridView1'); const data = tableToJson(table); const sumCoef = data.reduce((sum, item) => sum + item.coef, 0); function calculMoyenne(dataSet, totalCoef) { let total = 0; dataSet.forEach(item => { const { note_exam, note_cc, note_tp, coef } = item; let moyenne = 0; if (isNaN(note_tp)) { if (isNaN(note_cc)) { moyenne = note_exam; } else { moyenne = note_exam * 0.6 + note_cc * 0.4; if (item.designation == 'Génie logiciel & atelier GL'){ moyenne = note_exam * 0.4 + note_cc * 0.6; } } } else if (isNaN(note_cc)) { moyenne = note_exam * 0.8 + note_tp * 0.2; } else { moyenne = note_exam * 0.5 + note_cc * 0.3 + note_tp * 0.2; } item.moyenne = moyenne; total += moyenne * coef; }); dataSet.push({ designation: 'Moyenne', coef: totalCoef, nom_ens: '', note_cc: '', note_tp: '', note_exam: '', moyenne: total / totalCoef, }); return dataSet; } const newData = calculMoyenne(data, sumCoef); function populateTable(dataSet) { let title = document.querySelector(".col-xs-10 > center > h1") ; title.innerHTML = title.innerHTML + ": " + (document.querySelectorAll("tr").length-1).toString(); document.querySelectorAll(".row ~ br").forEach((e)=>e.remove()); let tableContent = ` <tr class="table-header"> <th scope="col">DESIGNATION</th> <th scope="col">COEF</th> <th scope="col">NOM_ENS</th> <th scope="col">NOTE_CC</th> <th scope="col">NOTE_TP</th> <th scope="col">NOTE_EXAM</th> <th scope="col">Moyenne</th> </tr>`; dataSet.forEach(item => { const moyenneClass = !isNaN(item.moyenne) ? item.moyenne >= 8 ? 'moyenne-high' : 'moyenne-low' : ''; tableContent += ` <tr> <td>${item.designation}</td> <td>${item.coef}</td> <td>${item.nom_ens}</td> <td>${isNaN(item.note_cc) ? '' : item.note_cc}</td> <td>${isNaN(item.note_tp) ? '' : item.note_tp}</td> <td>${isNaN(item.note_exam) ? '' : item.note_exam}</td> <td class="${moyenneClass}">${!isNaN(item.moyenne) ? item.moyenne.toFixed(2) : ''}</td> </tr>`; }); const tbody = table.querySelector('tbody') || table; tbody.innerHTML = tableContent; addDownloadButton(); } function addDownloadButton() { const downloadButton = document.createElement('button'); downloadButton.textContent = 'Download as PDF'; downloadButton.id = 'downloadButton'; downloadButton.type = 'button'; table.parentNode.insertBefore(downloadButton, table); downloadButton.addEventListener('click', function(event) { event.preventDefault(); generatePDF(); }); } populateTable(newData); async function generatePDF() { try { const { studentName, studentClass } = getStudentDetails(); const logoSrc = getLogoImage(); const element = document.getElementById('ContentPlaceHolder1_GridView1'); const canvas = await html2canvas(element, { useCORS: true, allowTaint: true }); const imgData = canvas.toDataURL('image/png'); const pdf = new window.jspdf.jsPDF('p', 'pt', 'a4'); pdf.setFontSize(16); pdf.text(`Student Name: ${studentName}`, 20, 20); pdf.setTextColor(204, 0, 0); pdf.text(`Class: ${studentClass}`, 20, 40); if (logoSrc) { const logoImage = new Image(); logoImage.src = logoSrc; pdf.addImage(logoImage, 'PNG', pdf.internal.pageSize.getWidth() - 80, 10, 60, 60); } pdf.setTextColor(0, 0, 0); const pdfWidth = pdf.internal.pageSize.getWidth(); const pdfHeight = (canvas.height * pdfWidth) / canvas.width; pdf.addImage(imgData, 'PNG', 0, 70, pdfWidth, pdfHeight); pdf.save(`${studentName}_Grades.pdf`); } catch (error) { console.error('Could not generate PDF:', error); alert('Could not generate PDF: ' + error.message); } } function newDropCheck(dataset) { let tableList = Array.from(document.querySelectorAll('#ContentPlaceHolder1_GridView1 tr td:nth-child(1)')); tableList.pop() let oldDrop = JSON.parse(localStorage.getItem('oldDrop')) || []; dataset.pop(); let newDrop = dataset.map((e) => e.designation); localStorage.setItem('oldDrop', JSON.stringify(newDrop)); let newItems = newDrop.filter(n => !oldDrop.includes(n)) newItems.forEach((item)=>{ tableList.forEach((element)=>{ if (element.textContent === item){ element.textContent += ' 🔴' } }) }) } newDropCheck(newData); })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址