您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
自动计算综合测评总分并显示在页面上
// ==UserScript== // @name 综测总分计算器 // @namespace https://github.com/MuonChaser/ZongceCalculator // @version 1.0 // @author MuonChaser // @description 自动计算综合测评总分并显示在页面上 // @license MIT // @match *://i.cufe.edu.cn/xsfw/sys/zhcpapp_cufe* // @grant none // ==/UserScript== (function() { 'use strict'; // 计算综测总分的函数 function calculateTotalScore() { // 获取表格数据 const table = document.querySelector('#tablewdzpTreeTable'); if (!table) { console.log('未找到综测表格'); return; } const scores = {}; const rows = table.querySelectorAll('tr'); let currentCategory = ''; // 遍历表格行,提取分数数据 rows.forEach(row => { const cells = row.querySelectorAll('td'); if (cells.length >= 4) { const titleCell = cells[0]; const scoreCell = cells[2]; // 学生自评得分列 const bonusCell = cells[3]; // 学生自评加分列 if (titleCell && scoreCell) { const titleSpan = titleCell.querySelector('.jqx-tree-grid-title'); if (titleSpan) { const title = titleSpan.textContent.trim(); const scoreText = scoreCell.textContent.trim(); const bonusText = bonusCell ? bonusCell.textContent.trim() : '0'; // 识别当前所属的大类别 const indentSpans = titleCell.querySelectorAll('.jqx-tree-grid-indent'); const indentLevel = indentSpans.length; // 如果是顶级类别(缩进少),更新当前类别 if (indentLevel <= 2) { if (title.includes('德育')) currentCategory = '德育'; else if (title.includes('智育')) currentCategory = '智育'; else if (title.includes('体质健康') || title.includes('体育')) currentCategory = '体育'; else if (title.includes('学术科研') || title.includes('科研')) currentCategory = '学术科研'; else if (title.includes('组织管理')) currentCategory = '组织管理'; else if (title.includes('劳动实践')) currentCategory = '劳动实践'; else if (title.includes('美育') || title.includes('美术')) currentCategory = '美育'; } // 提取数字,忽略"--" const score = (scoreText !== '--' && scoreText !== '') ? (parseFloat(scoreText) || 0) : 0; const bonus = (bonusText !== '--' && bonusText !== '') ? (parseFloat(bonusText) || 0) : 0; if (score > 0 || bonus > 0) { // 为重复的项目名添加类别前缀 let uniqueTitle = title; if (title === '基本分' || title === '加分') { uniqueTitle = `${currentCategory}_${title}`; } scores[uniqueTitle] = { score, bonus, total: score + bonus, category: currentCategory, originalTitle: title }; console.log(`${uniqueTitle}: 基础分${score}, 加分${bonus}, 小计${score + bonus} [类别:${currentCategory}]`); } } } } }); // 根据实际页面数据,重新定义分类映射 const categories = { 德育: { items: ['政治思想', '道德品质', '法纪观念', '学习态度', '集体意识', '生活修养'], weight: 0.3, maxScore: 100, description: '德育基础分数' }, 智育: { items: ['学习成绩'], weight: 0.6, maxScore: 100, description: '智育基础分数(学习成绩)' }, 体育锻炼: { items: ['日常体育锻炼', '体质与健康测试', '体育_基础分', '体育_加分'], weight: 0.1, maxScore: 100, description: '体质健康与锻炼' }, 学术科研与创新: { items: ['学术科研_基本分', '学科竞赛类', '科研项目类', '发表文章类', '学术科研与创新类荣誉称号'], weight: 0.1, maxScore: 200, description: '学术科研与创新能力' }, 组织管理能力: { items: ['组织管理_基本分', '业绩能力分', '组织管理_加分'], weight: 0.1, maxScore: 100, description: '组织管理能力' }, 劳动实践: { items: ['劳动实践_基本分', '劳动实践_加分'], weight: 0.1, maxScore: 100, description: '劳动实践评价' }, 美育素养: { items: ['美育_基本分', '参加文化、艺术类竞赛活动', '发表文学、艺术类作品'], weight: 0.1, maxScore: 100, description: '美育素质评价' } }; // 处理智育加分项 const zhiyuBonus = (scores['通用知识课程选修']?.total || 0) + (scores['书籍阅读情况']?.total || 0); if (zhiyuBonus > 0) { // 如果智育有加分项,加到智育总分中 const zhiyuBase = scores['学习成绩']?.total || 0; scores['智育总分'] = { score: zhiyuBase, bonus: zhiyuBonus, total: zhiyuBase * 0.9 + zhiyuBonus *0.1 }; categories.智育.items = ['智育总分']; } const categoryScores = {}; // 计算各类别分数 Object.entries(categories).forEach(([categoryName, category]) => { let categoryTotal = 0; let foundItems = []; let originalTotal = 0; // 记录原始总分 let isLimited = false; // 记录是否被限制 category.items.forEach(item => { if (scores[item]) { originalTotal += scores[item].total; const displayName = scores[item].originalTitle || item; foundItems.push(`${displayName}(${scores[item].total})`); } }); // 应用最大值限制 categoryTotal = Math.min(originalTotal, category.maxScore); isLimited = originalTotal > category.maxScore; categoryScores[categoryName] = { total: categoryTotal, originalTotal: originalTotal, maxScore: category.maxScore, isLimited: isLimited, weighted: categoryTotal * category.weight, items: foundItems, description: category.description }; if (isLimited) { console.log(`${categoryName}: ${originalTotal}分 (超限,取${category.maxScore}分) × ${category.weight} = ${(categoryTotal * category.weight).toFixed(2)}分 ⚠️`); } else { console.log(`${categoryName}: ${categoryTotal}分 × ${category.weight} = ${(categoryTotal * category.weight).toFixed(2)}分`); } }); // 计算总分 const totalScore = Object.values(categoryScores).reduce((sum, cat) => sum + cat.weighted, 0); return { categoryScores, totalScore, scores }; } // 创建显示结果的界面 function createScoreDisplay(result) { // 移除已存在的显示框 const existingDisplay = document.getElementById('scoreDisplay'); if (existingDisplay) { existingDisplay.remove(); } // 创建显示容器 const displayDiv = document.createElement('div'); displayDiv.id = 'scoreDisplay'; displayDiv.style.cssText = ` position: fixed; top: 20px; right: 20px; width: 400px; max-height: 80vh; background: #fff; border: 2px solid #007cba; border-radius: 10px; padding: 20px; box-shadow: 0 4px 20px rgba(0,0,0,0.3); z-index: 10000; font-family: "Microsoft YaHei", Arial, sans-serif; font-size: 14px; overflow-y: auto; `; let html = ` <div style="text-align: center; margin-bottom: 15px;"> <h3 style="margin: 0; color: #007cba; font-size: 18px;">📊 综测总分计算结果</h3> </div> <div style="background: #f0f8ff; padding: 15px; border-radius: 8px; margin-bottom: 15px; text-align: center;"> <div style="font-size: 24px; font-weight: bold; color: #d32f2f;"> 总分: ${result.totalScore.toFixed(2)} </div> </div> `; html += '<div style="margin-bottom: 15px;"><strong>📋 各项评价详情:</strong></div>'; // 显示各类别得分 Object.entries(result.categoryScores).forEach(([categoryName, categoryData]) => { const percentage = result.totalScore > 0 ? (categoryData.weighted / result.totalScore * 100).toFixed(1) : '0.0'; const weightPercentage = (categoryData.total > 0 ? categoryData.weighted / categoryData.total : 0) * 100; // 构建显示内容 let statusColor = '#007cba'; let statusIcon = ''; let limitInfo = ''; if (categoryData.isLimited) { statusColor = '#ff6b6b'; statusIcon = ' ⚠️'; limitInfo = `<div style="font-size: 11px; color: #ff6b6b; margin-top: 3px;"> ⚠️ 原始分${categoryData.originalTotal}分,超出上限${categoryData.maxScore}分,已限制 </div>`; } else { limitInfo = `<div style="font-size: 11px; color: #28a745; margin-top: 3px;"> ✅ 未超限 (上限${categoryData.maxScore}分) </div>`; } html += ` <div style="margin-bottom: 12px; padding: 10px; background: #f8f9fa; border-radius: 5px; border-left: 4px solid ${statusColor};"> <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 5px;"> <strong style="color: #333;">${categoryName}${statusIcon}</strong> <span style="color: ${statusColor}; font-weight: bold;">${categoryData.weighted.toFixed(2)}分</span> </div> <div style="font-size: 12px; color: #666;"> 计算分: ${categoryData.total}分 × 权重${weightPercentage.toFixed(0)}% (占总分${percentage}%) </div> ${limitInfo} ${categoryData.items.length > 0 ? `<div style="font-size: 11px; color: #888; margin-top: 3px;"> 包含: ${categoryData.items.join(', ')} </div>` : '' } ${categoryData.description ? `<div style="font-size: 10px; color: #999; margin-top: 2px; font-style: italic;"> ${categoryData.description} </div>` : '' } </div> `; }); // 添加计算公式说明 html += ` <div style="margin-top: 15px; padding: 10px; background: #fff3cd; border-radius: 5px; border: 1px solid #ffeaa7;"> <div style="font-size: 12px; color: #856404;"> <strong>💡 计算公式:</strong><br> 总分 = 德育×30% + 智育×60% + 体育锻炼×10% + 学术科研×10% + 组织管理×10% + 劳动实践×10% + 美育素养×10% </div> </div> `; // 添加关闭按钮 html += ` <div style="text-align: center; margin-top: 15px;"> <button id="closeScoreDisplay" style=" background: #007cba; color: white; border: none; padding: 8px 20px; border-radius: 5px; cursor: pointer; font-size: 14px; ">关闭</button> <button id="refreshScore" style=" background: #28a745; color: white; border: none; padding: 8px 20px; border-radius: 5px; cursor: pointer; font-size: 14px; margin-left: 10px; ">刷新计算</button> </div> `; displayDiv.innerHTML = html; document.body.appendChild(displayDiv); // 添加关闭按钮事件 document.getElementById('closeScoreDisplay').onclick = () => { displayDiv.remove(); }; // 添加刷新按钮事件 document.getElementById('refreshScore').onclick = () => { const newResult = calculateTotalScore(); if (newResult) { createScoreDisplay(newResult); } }; // 添加拖拽功能 let isDragging = false; let dragOffset = { x: 0, y: 0 }; displayDiv.onmousedown = (e) => { if (e.target.tagName === 'BUTTON') return; isDragging = true; dragOffset.x = e.clientX - displayDiv.offsetLeft; dragOffset.y = e.clientY - displayDiv.offsetTop; displayDiv.style.cursor = 'move'; }; document.onmousemove = (e) => { if (isDragging) { displayDiv.style.left = (e.clientX - dragOffset.x) + 'px'; displayDiv.style.top = (e.clientY - dragOffset.y) + 'px'; displayDiv.style.right = 'auto'; } }; document.onmouseup = () => { isDragging = false; displayDiv.style.cursor = 'default'; }; } // 创建计算按钮 function createCalculateButton() { const button = document.createElement('button'); button.id = 'calculateScoreBtn'; button.innerHTML = '🧮 计算综测总分'; button.style.cssText = ` position: fixed; top: 20px; left: 20px; background: #007cba; color: white; border: none; padding: 12px 20px; border-radius: 25px; cursor: pointer; font-size: 16px; font-weight: bold; box-shadow: 0 2px 10px rgba(0,0,0,0.2); z-index: 9999; transition: all 0.3s ease; `; button.onmouseover = () => { button.style.background = '#005a8b'; button.style.transform = 'scale(1.05)'; }; button.onmouseout = () => { button.style.background = '#007cba'; button.style.transform = 'scale(1)'; }; button.onclick = () => { const result = calculateTotalScore(); if (result) { createScoreDisplay(result); } else { alert('无法计算分数,请确保页面已加载完成且包含综测数据'); } }; document.body.appendChild(button); } // 等待页面加载完成 function init() { if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); return; } // 延迟执行,确保动态内容加载完成 setTimeout(() => { createCalculateButton(); // 自动计算一次(可选) const result = calculateTotalScore(); if (result) { console.log('综测总分:', result.totalScore.toFixed(2)); } }, 2000); } init(); })();