您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
A unified calculator tool with chat history and draggable UI.
当前为
// ==UserScript== // @name Advanced Calculator // @namespace https://greasyfork.org/en/users/1291009 // @version 6.1.0 // @description A unified calculator tool with chat history and draggable UI. // @author BadOrBest // @license MIT // @icon https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQE4akrlePwM0brye6bimtz0ziOengL_C9rhQ&s // @match *://*/* // @grant GM_addStyle // @grant GM_setValue // @grant GM_getValue // @grant GM_deleteValue // @grant GM_registerMenuCommand // @run-at document-end // ==/UserScript== (function() { 'use strict'; // Load external libraries const scriptLoad = url => new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = url; script.onload = resolve; script.onerror = reject; document.head.appendChild(script); }); Promise.all([ scriptLoad('https://cdnjs.cloudflare.com/ajax/libs/mathjs/13.1.1/math.min.js'), scriptLoad('https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js') ]).then(() => { console.log('Libraries loaded successfully.'); initCalculator(); }).catch(error => console.error('Error loading libraries:', error)); // General settings const settings = { theme: GM_getValue('theme', 'dark'), historyPageSize: GM_getValue('historyPageSize', 50), interpretXAsMultiply: GM_getValue('interpretXAsMultiply', true) // Default to true }; function applySettings() { document.body.style.backgroundColor = settings.theme === 'dark' ? '#333' : '#fff'; } applySettings(); // Calculator Initialization function initCalculator() { const MAX_MESSAGES = 400; const STORAGE_KEY = 'chatHistory'; const chatBox = document.createElement('div'); chatBox.id = 'calculator-chat-box'; Object.assign(chatBox.style, { position: 'fixed', bottom: '10vh', right: '5vw', width: 'calc(90vw - 10px)', maxWidth: '350px', backgroundColor: '#1f1f1f', borderRadius: '12px', padding: '10px', boxShadow: '0 0 15px rgba(0, 0, 0, 0.3)', zIndex: '9999', display: 'flex', flexDirection: 'column', fontFamily: 'Arial, sans-serif' }); const chatHeader = document.createElement('div'); chatHeader.style.display = 'flex'; chatHeader.style.justifyContent = 'space-between'; chatHeader.style.alignItems = 'center'; chatHeader.style.backgroundColor = '#333'; chatHeader.style.color = '#fff'; chatHeader.style.padding = '10px'; chatHeader.style.borderRadius = '10px 10px 0 0'; chatHeader.style.fontWeight = 'bold'; chatHeader.textContent = 'Advanced Calculator'; const collapseButton = document.createElement('button'); collapseButton.textContent = '▼'; collapseButton.style.padding = '5px 10px'; collapseButton.style.border = 'none'; collapseButton.style.backgroundColor = '#555'; collapseButton.style.color = '#fff'; collapseButton.style.cursor = 'pointer'; collapseButton.style.borderRadius = '5px'; collapseButton.addEventListener('click', toggleChatBox); chatHeader.appendChild(collapseButton); chatBox.appendChild(chatHeader); const chatHistory = document.createElement('div'); chatHistory.id = 'chat-history'; Object.assign(chatHistory.style, { height: '300px', overflowY: 'auto', backgroundColor: '#333', color: '#fff', padding: '10px', borderRadius: '8px' }); chatBox.appendChild(chatHistory); const chatInput = document.createElement('input'); chatInput.id = 'chat-input'; chatInput.type = 'text'; Object.assign(chatInput.style, { width: 'calc(100% - 20px)', padding: '10px', margin: '10px auto', borderRadius: '10px', border: 'none', backgroundColor: '#444', color: 'white' }); chatInput.placeholder = 'Type here...'; chatInput.addEventListener('keydown', event => { if (event.key === 'Enter') { event.preventDefault(); sendMessage(); } }); chatBox.appendChild(chatInput); // Draggable functionality let isDragging = false; let initialX, initialY; let offsetX = 0, offsetY = 0; chatBox.addEventListener('mousedown', startDragging); chatBox.addEventListener('touchstart', startDragging); document.addEventListener('mousemove', drag); document.addEventListener('touchmove', drag); document.addEventListener('mouseup', stopDragging); document.addEventListener('touchend', stopDragging); function startDragging(event) { if (event.target === chatInput) return; event.preventDefault(); initialX = event.clientX - offsetX; initialY = event.clientY - offsetY; isDragging = true; chatBox.classList.add('chat-dragging'); } function drag(event) { if (!isDragging) return; event.preventDefault(); const currentX = event.clientX - initialX; const currentY = event.clientY - initialY; offsetX = currentX; offsetY = currentY; chatBox.style.transform = `translate(${currentX}px, ${currentY}px)`; } function stopDragging() { isDragging = false; chatBox.classList.remove('chat-dragging'); } function toggleChatBox() { if (chatBox.style.height === '70px') { chatBox.style.height = 'auto'; collapseButton.textContent = '▼'; chatInput.style.display = 'block'; } else { chatBox.style.height = '70px'; collapseButton.textContent = '▲'; chatInput.style.display = 'none'; } } // Function to load messages from localStorage function loadMessagesFromStorage() { let messages = []; try { messages = JSON.parse(localStorage.getItem(STORAGE_KEY)) || []; } catch (error) { console.error('Error loading chat history from localStorage:', error); clearLocalStorage(); } return messages; } // Function to clear localStorage function clearLocalStorage() { try { localStorage.removeItem(STORAGE_KEY); } catch (error) { console.error('Error clearing localStorage:', error); } } // Function to add message to conversation and save to localStorage function addMessage(message, isInput) { const messageElement = document.createElement('div'); messageElement.className = 'message ' + (isInput ? 'input' : 'output'); messageElement.innerHTML = message; chatHistory.appendChild(messageElement); if (!isInput) { const line = document.createElement('hr'); line.style.borderTop = '1px solid white'; line.style.margin = '5px 0'; chatHistory.appendChild(line); } function scrollToBottom() { chatHistory.scrollTop = chatHistory.scrollHeight; } scrollToBottom(); let messages = loadMessagesFromStorage(); messages.push({ message: message, isInput: isInput }); if (messages.length > MAX_MESSAGES) { messages = messages.slice(-MAX_MESSAGES); } try { localStorage.setItem(STORAGE_KEY, JSON.stringify(messages)); } catch (error) { console.error('Error saving chat history to localStorage:', error); clearLocalStorage(); } } function sendMessage() { const expression = chatInput.value.trim(); if (expression !== '') { addMessage('<span class="user-label">(User):</span> ' + expression, true); evaluateExpression(expression); chatInput.value = ''; } } function evaluateExpression(expression) { try { if (settings.interpretXAsMultiply) { expression = expression.replace(/(\d)x(\d)/g, '$1*$2'); } const result = math.evaluate(expression); addMessage('<span class="result-label">(Result):</span> ' + result, false); } catch (error) { addMessage('<span class="result-label">(Result):</span> Error: ' + error.message, false); } } window.addEventListener('load', () => { loadMessagesFromStorage().forEach(msg => { addMessage(msg.message, msg.isInput); }); scrollToBottom(); }); GM_registerMenuCommand('Clear Chat History', clearLocalStorage); GM_registerMenuCommand('Toggle x as multiply/variable', () => { settings.interpretXAsMultiply = !settings.interpretXAsMultiply; GM_setValue('interpretXAsMultiply', settings.interpretXAsMultiply); alert(`x is now interpreted as ${settings.interpretXAsMultiply ? 'multiplication' : 'variable'}.`); }); GM_addStyle(` #calculator-chat-box { font-family: Arial, sans-serif; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); } .message { clear: both; padding: 5px 10px; color: white; } .input { text-align: left; } .result-label { float: left; margin-left: 5px; background-color: blue; color: white; border-radius: 10px; padding: 3px 6px; } .user-label { float: left; margin-left: 5px; background-color: green; color: white; border-radius: 10px; padding: 3px 6px; } hr { border-top: 1px solid white; margin: 5px 0; } .chat-dragging { cursor: move; } `); document.body.appendChild(chatBox); } })();