393 lines
15 KiB
JavaScript
Executable File
393 lines
15 KiB
JavaScript
Executable File
// ==UserScript==
|
|
// @name LMSGuide辅助
|
|
// @version 1.3.2
|
|
// @description 要有远大的理想,也要有脚踏实地的本领
|
|
// @author 小钊
|
|
// @match *://10.90.53.11:5090/*
|
|
// @homepageURL https://www.zxqblog.cn
|
|
// @grant GM_registerMenuCommand
|
|
// @grant GM_unregisterMenuCommand
|
|
// @grant GM_setValue
|
|
// @grant GM_getValue
|
|
// @grant GM_deleteValue
|
|
// ==/UserScript==
|
|
|
|
(function() {
|
|
'use strict';
|
|
// 通用样式定义
|
|
// 复制到虚拟机的样式
|
|
const buttonStyle = `
|
|
.copy-vm-btn {
|
|
position: absolute;
|
|
right: 10px;
|
|
top: 10px;
|
|
padding: 5px 10px;
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 3px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
opacity: 0;
|
|
transition: opacity 0.3s ease;
|
|
z-index: 100;
|
|
}
|
|
.copy-vm-btn:hover {
|
|
background-color: #45a049;
|
|
}
|
|
/* pre标签容器样式 */
|
|
.pre-container {
|
|
position: relative;
|
|
}
|
|
/* 鼠标悬浮时显示按钮 */
|
|
.pre-container:hover .copy-vm-btn {
|
|
opacity: 1;
|
|
}
|
|
`;
|
|
const styleSheet = document.createElement("style");
|
|
styleSheet.textContent = buttonStyle;
|
|
document.head.appendChild(styleSheet);
|
|
// 设置页面的开关样式
|
|
const switchStyles = {
|
|
position: 'relative',
|
|
width: '50px',
|
|
height: '24px',
|
|
appearance: 'none',
|
|
outline: 'none',
|
|
borderRadius: '12px',
|
|
backgroundColor: '#ccc',
|
|
cursor: 'pointer',
|
|
verticalAlign: 'middle'
|
|
};
|
|
const sliderStyles = {
|
|
position: 'absolute',
|
|
top: '2px',
|
|
left: '2px',
|
|
width: '20px',
|
|
height: '20px',
|
|
borderRadius: '50%',
|
|
backgroundColor: '#fff',
|
|
transition: 'all 0.3s'
|
|
};
|
|
// -------------------------------------
|
|
// 注册脚本菜单
|
|
GM_registerMenuCommand("设置", showSettingsPopup);
|
|
// -------------------------------------
|
|
// 免责说明
|
|
window.addEventListener('load', function(event) {
|
|
if (!GM_getValue('mianzeshenming',false)){
|
|
// 如果检测到没有同意协议则渲染免责协议窗口
|
|
document.body.innerHTML = '';
|
|
const mzsf = document.createElement('div');
|
|
Object.assign(mzsf.style, {
|
|
position: 'fixed',
|
|
top: '50%',
|
|
left: '50%',
|
|
transform: 'translate(-50%, -50%)',
|
|
padding: '20px',
|
|
backgroundColor: '#fff',
|
|
borderRadius: '8px',
|
|
boxShadow: '0 4px 8px rgba(0,0,0,0.2)',
|
|
zIndex: '1000',
|
|
width: '300px'
|
|
});
|
|
|
|
// 标题与提示渲染
|
|
const title = document.createElement('h2');
|
|
title.textContent = '免责协议';
|
|
mzsf.appendChild(title);
|
|
const tips = document.createElement('p');
|
|
tips.textContent = "请合理使用此脚本,造成一切损失与作者无关!同意协议后点击刷新进行页面刷新,如果不同意协议请删除此脚本并刷新网页"
|
|
tips.style.marginTop = '10px';
|
|
tips.style.marginBottom = '10px'
|
|
mzsf.appendChild(tips);
|
|
|
|
// 开关渲染
|
|
// 复制到虚拟机开关
|
|
mzsf.appendChild(createSwitch('同意免责协议', 'mianzeshenming'));
|
|
|
|
// 刷新按钮渲染
|
|
const sxButton = document.createElement('button');
|
|
sxButton.textContent = '刷新';
|
|
Object.assign(sxButton.style, {
|
|
marginTop: '15px',
|
|
padding: '8px 16px',
|
|
backgroundColor: '#f44336',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '4px',
|
|
cursor: 'pointer'
|
|
});
|
|
sxButton.onclick = function() {
|
|
location.reload()
|
|
};
|
|
|
|
mzsf.appendChild(sxButton);
|
|
document.body.appendChild(mzsf);
|
|
}else {
|
|
// 否则渲染设置窗口
|
|
if (!GM_getValue("CopyToVM_Switch_Status",false) && !GM_getValue("Autoground_Switch_Status",false) && !GM_getValue("Select_Switch_Status",false) && !GM_getValue("NoOneShowsetting",false)) {
|
|
// 如果所有的配置项均未配置,则显示配置窗口
|
|
GM_setValue("NoOneShowsetting", true);
|
|
showSettingsPopup();
|
|
}
|
|
}
|
|
})
|
|
// -------------------------------------
|
|
// 函数部分
|
|
// 设置->创建开关 函数
|
|
function createSwitch(label, storageKey, onChange) {
|
|
const container = document.createElement('div');
|
|
container.style.marginBottom = '15px';
|
|
|
|
const switchLabel = document.createElement('label');
|
|
switchLabel.textContent = label;
|
|
switchLabel.style.marginRight = '10px';
|
|
switchLabel.style.fontWeight = 'normal';
|
|
|
|
const switchInput = document.createElement('input');
|
|
switchInput.type = 'checkbox';
|
|
Object.assign(switchInput.style, switchStyles);
|
|
|
|
const slider = document.createElement('span');
|
|
Object.assign(slider.style, sliderStyles);
|
|
switchInput.appendChild(slider);
|
|
|
|
// 初始状态
|
|
const isChecked = GM_getValue(storageKey, false);
|
|
switchInput.name = storageKey;
|
|
switchInput.checked = isChecked;
|
|
switchInput.style.backgroundColor = isChecked ? '#4CAF50' : '#ccc';
|
|
slider.style.transform = isChecked ? 'translateX(26px)' : 'translateX(0)';
|
|
|
|
// 事件处理
|
|
switchInput.addEventListener('change', function() {
|
|
const checked = this.checked;
|
|
this.style.backgroundColor = checked ? '#4CAF50' : '#ccc';
|
|
slider.style.transform = checked ? 'translateX(26px)' : 'translateX(0)';
|
|
GM_setValue(storageKey, checked);
|
|
if (onChange) onChange(checked);
|
|
});
|
|
|
|
container.appendChild(switchLabel);
|
|
container.appendChild(switchInput);
|
|
return container;
|
|
}
|
|
// 设置->主界面 函数
|
|
function showSettingsPopup() {
|
|
// 确保之前的弹窗被移除
|
|
const existingPopup = document.querySelector('div[style*="position: fixed; top: 50%; left: 50%;"]');
|
|
if (existingPopup) {
|
|
document.body.removeChild(existingPopup);
|
|
}
|
|
const popup = document.createElement('div');
|
|
Object.assign(popup.style, {
|
|
position: 'fixed',
|
|
top: '50%',
|
|
left: '50%',
|
|
transform: 'translate(-50%, -50%)',
|
|
padding: '20px',
|
|
backgroundColor: '#fff',
|
|
borderRadius: '8px',
|
|
boxShadow: '0 4px 8px rgba(0,0,0,0.2)',
|
|
zIndex: '1000',
|
|
width: '300px'
|
|
});
|
|
|
|
// 标题与提示渲染
|
|
const title = document.createElement('h2');
|
|
title.textContent = '设置';
|
|
popup.appendChild(title);
|
|
const tip_list = ["启动立马生效,关闭刷新生效","复制到虚拟机优先级高于复制到实体机"];
|
|
const tips = document.createElement('p');
|
|
tips.textContent = tip_list[0];
|
|
tips.id = "setting_tip";
|
|
tips.style.marginTop = '10px';
|
|
tips.style.marginBottom = '10px'
|
|
popup.appendChild(tips);
|
|
let tip_id = 1
|
|
const tip_initer = setInterval(() => {
|
|
tip_id = tip_id==1 ? 0 : 1;
|
|
document.getElementById("setting_tip").innerHTML = tip_list[tip_id];
|
|
}, 1000)
|
|
|
|
|
|
// 开关渲染
|
|
// 复制到虚拟机开关
|
|
popup.appendChild(createSwitch('复制到虚拟机', 'CopyToVM_Switch_Status'));
|
|
// 实验报告滚动
|
|
popup.appendChild(createSwitch('实验报告自动滚动到底', 'Autoground_Switch_Status'));
|
|
// 移除复制限制
|
|
popup.appendChild(createSwitch('移除移除选择、复制、剪切操作的限制', 'Select_Switch_Status'));
|
|
// 复制到实体机开关
|
|
popup.appendChild(createSwitch('复制到实体机', 'CopyToTrue_Switch_Status'));
|
|
|
|
// 关闭按钮渲染
|
|
const closeButton = document.createElement('button');
|
|
closeButton.textContent = '关闭';
|
|
Object.assign(closeButton.style, {
|
|
marginTop: '15px',
|
|
padding: '8px 16px',
|
|
backgroundColor: '#f44336',
|
|
color: 'white',
|
|
border: 'none',
|
|
borderRadius: '4px',
|
|
cursor: 'pointer'
|
|
});
|
|
closeButton.onclick = function() {
|
|
document.body.removeChild(popup);
|
|
clearInterval(tip_initer)
|
|
};
|
|
|
|
popup.appendChild(closeButton);
|
|
document.body.appendChild(popup);
|
|
}
|
|
// 主功能->弹窗函数
|
|
function notification(text) {
|
|
const notification = document.createElement('div');
|
|
notification.style.cssText = `
|
|
position: fixed;
|
|
top: 20px;
|
|
right: 20px;
|
|
padding: 10px 20px;
|
|
background-color: #4CAF50;
|
|
color: white;
|
|
border-radius: 5px;
|
|
z-index: 10000;
|
|
`;
|
|
notification.textContent = text;
|
|
document.body.appendChild(notification);
|
|
setTimeout(() => notification.remove(), 2000);
|
|
}
|
|
// 复制到虚拟机功能 -> 复制到虚拟机 函数
|
|
function sendToVirtualMachine(text) {
|
|
if (GM_getValue("CopyToVM_Switch_Status",false)){
|
|
console.log("text"+text)
|
|
const code = "code:"+text
|
|
document.getElementById("tool_content").contentWindow.postMessage(code, "*");
|
|
}else if (GM_getValue("CopyToTrue_Switch_Status",false)) {
|
|
mycopy(text);
|
|
}
|
|
return true
|
|
}
|
|
// 复制到实体机功能 -> 复制到实体机 函数
|
|
function mycopy(data) {
|
|
const TEXT_PLAIN = "text/plain";
|
|
const TEXT_HTML = "text/html";
|
|
const COPY = "copy";
|
|
const opt = Object.prototype.toString;
|
|
const execCopyCommand = (data) => {
|
|
const textarea = document.createElement("textarea");
|
|
const handler = (event) => {
|
|
event.preventDefault();
|
|
event.stopImmediatePropagation();
|
|
for (const [key, value] of Object.entries(data)) {
|
|
event.clipboardData && event.clipboardData.setData(key, value);
|
|
}
|
|
};
|
|
textarea.addEventListener(COPY, handler, true);
|
|
textarea.style.position = "fixed";
|
|
textarea.style.left = "-999999999px";
|
|
textarea.style.top = "-999999999px";
|
|
textarea.value = data[TEXT_PLAIN] || " ";
|
|
document.body.appendChild(textarea);
|
|
textarea.select();
|
|
document.execCommand("copy");
|
|
textarea.removeEventListener(COPY, handler);
|
|
document.body.removeChild(textarea);
|
|
}
|
|
function isString(value) {
|
|
return opt.call(value) === "[object String]";
|
|
}
|
|
const isEmptyContent = (data) => {
|
|
if (!data)
|
|
return true;
|
|
return isString(data) ? !data : !data[TEXT_PLAIN];
|
|
};
|
|
const params = isString(data) ? { [TEXT_PLAIN]: data } : data;
|
|
const plainText = params[TEXT_PLAIN];
|
|
if (!plainText)
|
|
return false;
|
|
if (navigator.clipboard && window.ClipboardItem) {
|
|
const dataItems = {};
|
|
for (const [key, value] of Object.entries(params)) {
|
|
const blob = new Blob([value], { type: key });
|
|
dataItems[key] = blob;
|
|
}
|
|
navigator.clipboard.write([new ClipboardItem(dataItems)]).catch(() => {
|
|
execCopyCommand(params);
|
|
});
|
|
} else {
|
|
execCopyCommand(params);
|
|
}
|
|
return true;
|
|
}
|
|
// -------------------------------------
|
|
// 定时器部分
|
|
// 页面加载时移除选择、复制、剪切操作的限制
|
|
setInterval(() => {
|
|
if (GM_getValue("Select_Switch_Status",false)) {
|
|
document.onselectstart = function(event) {return true;};
|
|
document.oncopy = function(event) {return true;};
|
|
document.oncut = function(event) {return true;};
|
|
var elements = document.querySelectorAll('[class^=" language-"]');
|
|
elements.forEach(function(element) {element.style.cssText = '';});
|
|
}
|
|
}, 1000)
|
|
// 复制到虚拟/虚拟机按钮渲染
|
|
setInterval(() => {
|
|
if (GM_getValue("CopyToVM_Switch_Status",false)||GM_getValue("CopyToTrue_Switch_Status",false)){
|
|
const btn_type = GM_getValue("CopyToVM_Switch_Status") ? ["虚拟",'Vm'] : ["实体","Tr"];
|
|
document.querySelectorAll('pre[class^=" language-"]').forEach(pre => {
|
|
// 元素存在且状态正确
|
|
if (pre.getAttribute('data-type-button')==btn_type[1]) return;
|
|
// 元素存在且状态不正确
|
|
if (pre.getAttribute('data-type-button') != null && pre.getAttribute('data-type-button')!=btn_type[1]) {
|
|
pre.setAttribute('data-type-button', btn_type[1]);
|
|
const btns = document.getElementsByClassName('copy-vm-btn')
|
|
Array.from(btns).forEach(btn=>{
|
|
btn.innerHTML = `复制到${btn_type[0]}机`;
|
|
btn.onclick = function() {
|
|
const success = sendToVirtualMachine(pre.textContent);
|
|
if (success) {notification(`已复制到${btn_type[0]}机!`);}
|
|
};
|
|
})
|
|
return
|
|
};
|
|
// 元素不存在
|
|
console.log("不正确")
|
|
const container = document.createElement('div');
|
|
container.className = 'pre-container';
|
|
pre.parentNode.insertBefore(container, pre);
|
|
container.appendChild(pre);
|
|
const button = document.createElement('button');
|
|
button.className = 'copy-vm-btn';
|
|
pre.setAttribute('data-type-button', btn_type[1]);
|
|
button.textContent = `复制到${btn_type[0]}机`
|
|
button.onclick = function() {
|
|
const success = sendToVirtualMachine(pre.textContent);
|
|
if (success) {notification(`已复制到${btn_type[0]}机!`);}
|
|
};
|
|
container.appendChild(button);
|
|
});
|
|
}
|
|
}, 1000);
|
|
// 点击实验报告滚动到最下面
|
|
setInterval(() => {
|
|
if (GM_getValue("Autoground_Switch_Status",false)) {
|
|
try {
|
|
document.querySelector("#assignment-report").addEventListener('click', function() {
|
|
const lastElement =document.getElementById("report_area_ifr").contentDocument.querySelector("#tinymce p:last-child")
|
|
if (lastElement) {
|
|
lastElement.scrollIntoView({
|
|
behavior: 'smooth',
|
|
block: 'center',
|
|
inline: 'nearest'
|
|
});
|
|
}
|
|
});
|
|
}catch {}
|
|
}
|
|
}, 1000)
|
|
})();
|