页面解题不可用,新增出题助记 咽沙学习小助手测试版V0.93
// ==UserScript==
// @name 页面解题不可用,新增出题助记 咽沙学习小助手测试版V0.93
// @namespace http://tampermonkey.net/
// @version 0.93
// @description 页面答题功能不可用,新增出题助记功能
// @author YeansyAwa
// @match *://*/*
// @grant GM_addStyle
// @grant GM_xmlhttpRequest
// ==/UserScript==
(function() {
'use strict';
const API_SECRET_KEY = "sk-zkix22izlS26fVKhfAtHnRa2A8rT9xZyQqAu6Sf8NfiXPPtdYEYN";
const BASE_URL = "https://model-bridge.okeeper.com/v1/";
// 添加 CSS 样式 - 确保样式定义正确
GM_addStyle(`
/* 确保所有相关元素都有合适的样式 */
#button-container {
width: 250px;
height: 60px;
border-radius: 15px;
font-size: 18px;
position: fixed;
right: 20px;
bottom: 180px;
z-index: 10000;
cursor: pointer;
font-family: "STKaiti", "华文楷体", "Kaiti", serif;
overflow: visible;
color: black;
background: linear-gradient(135deg, #ffecb3, #ffdead);
transition: all 0.3s ease-in-out;
}
.option-button {
width: 250px;
height: 60px;
border-radius: 15px;
border: none;
background-color: #fff9db;
cursor: pointer;
font-family: "STKaiti", "华文楷体", "Kaiti", serif;
display: none;
text-align: left;
position: absolute;
left: 0;
top: -60px;
opacity: 0;
transition: all 0.3s ease-in-out;
}
#chat-window, #auto-answer-chat-window, #quiz-memory-chat-window {
width: 300px;
height: 400px;
background-color: #e6e6fa;
border: 1px solid #ccc;
position: fixed;
bottom: 60px;
right: 20px;
z-index: 9999;
box-shadow: 0 0 10px rgba(0,0,0,0.2);
padding: 10px;
border-radius: 5px;
overflow: hidden;
display: none;
}
#chat-content, #auto-answer-chat-content, #quiz-memory-chat-content {
height: calc(100% - 120px);
overflow-y: auto;
}
#input-container {
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: space-between;
align-items: center;
background-color: #fff;
border-top: 1px solid #ccc;
}
#chat-input {
width: calc(100% - 70px);
height: 30px;
margin: 5px;
box-sizing: border-box;
}
#send-button {
width: 50px;
height: 30px;
margin: 5px;
box-sizing: border-box;
}
.copy-button {
width: 100%;
height: 30px;
margin: 5px 0;
box-sizing: border-box;
background-color: #f0f0f0;
border: 1px solid #ccc;
cursor: pointer;
text-align: center;
line-height: 30px;
}
@keyframes gradientBG {
0% { background-color: #ffecb3; }
50% { background-color: #fffdd0; }
100% { background-color: #ffdead; }
}
button#show-hide-chat-button {
animation: gradientBG 5s infinite;
}
`);
function createButtonContainer() {
const buttonContainer = document.createElement('div');
buttonContainer.id = 'button-container';
return buttonContainer;
}
function createParentButton(buttonContainer) {
const parentButton = document.createElement('button');
parentButton.textContent = '咽沙学习小助手测试版 V0.93';
parentButton.style.width = '100%';
parentButton.style.height = '100%';
parentButton.style.border = 'none';
parentButton.style.backgroundColor = 'transparent';
parentButton.style.cursor = 'pointer';
parentButton.style.fontFamily = '"STKaiti", "华文楷体", "Kaiti", serif';
parentButton.style.fontSize = '18px';
buttonContainer.appendChild(parentButton);
return parentButton;
}
function createOptionButtons(buttonContainer) {
for (let i = 0; i < 5; i++) {
const optionButton = document.createElement('button');
optionButton.className = 'option-button';
if (i === 4) { // 对话GPT按钮
optionButton.textContent = '-对话GPT 【本按钮可切换窗口显示、隐藏】';
optionButton.onclick = () => toggleChatWindowVisibility('chat-window');
} else if (i === 1) { // 获取页面自动解答按钮
optionButton.textContent = '-获取页面自动解答';
optionButton.onclick = () => {
toggleChatWindowVisibility('auto-answer-chat-window');
generateAutoAnswer();
};
} else if (i === 2) { // 出题助记按钮
optionButton.textContent = '-出题助记【共18题】';
optionButton.onclick = () => toggleChatWindowVisibility('quiz-memory-chat-window');
} else {
optionButton.onclick = () => parentButton.click(); // 收起子容器
}
buttonContainer.appendChild(optionButton);
}
}
function toggleChatWindowVisibility(chatWindowId) {
const chatWindow = document.getElementById(chatWindowId);
chatWindow.style.display = chatWindow.style.display === 'none' ? 'block' : 'none';
}
function getPageText() {
let allText = '';
const texts = [];
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, null, false);
while (walker.nextNode()) {
const node = walker.currentNode;
if (node.parentElement.tagName !== 'SCRIPT' && node.parentElement.tagName !== 'STYLE') {
texts.push(node.nodeValue.trim());
}
}
return texts.filter(text => text).join('\n');
}
async function sendMessageToAI(message, isQuizMemory = false) {
try {
const response = await fetch(`${BASE_URL}chat/completions`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_SECRET_KEY}`
},
body: JSON.stringify({
model: "gpt-3.5-turbo",
messages: [
{"role": "system", "content": "您是一位乐于助人的助手。"},
{"role": "user", "content": message},
...(isQuizMemory ? [{"role": "assistant", "content": "请根据以上信息生成18道选择题,帮助我更好地记住这些知识点。"}] : [])
]
})
});
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const data = await response.json();
if (!data.choices || !data.choices.length) throw new Error('来自AI服务的回答无效。');
return data;
} catch (error) {
console.error("获取AI回答时出错:", error);
throw error;
}
}
function createChatWindow(isAutoAnswer, isQuizMemory) {
const chatWindowId = isQuizMemory ? 'quiz-memory-chat-window' : (isAutoAnswer ? 'auto-answer-chat-window' : 'chat-window');
const chatWindow = document.createElement('div');
chatWindow.id = chatWindowId;
const chatContentId = `${chatWindowId}-content`;
const chatContent = document.createElement('div');
chatContent.id = chatContentId;
chatContent.className = 'chat-content';
chatWindow.appendChild(chatContent);
if (isQuizMemory) {
// 出题助记专属逻辑
const inputContainer = document.createElement('div');
inputContainer.id = 'input-container';
const userInput = document.createElement('input');
userInput.type = 'text';
userInput.placeholder = '在此输入你想记忆的知识...';
inputContainer.appendChild(userInput);
const sendButton = document.createElement('button');
sendButton.textContent = '发送';
sendButton.onclick = async function() {
const userMessage = userInput.value.trim();
if (userMessage) {
userInput.value = '';
const loadingMessage = document.createElement('div');
loadingMessage.textContent = '正在加载中…请耐心等待';
chatContent.appendChild(loadingMessage);
chatContent.scrollTop = chatContent.scrollHeight;
try {
const apiResponse = await sendMessageToAI(userMessage, true); // 在这里指定这是出题助记请求
appendChatMessage(chatContent, apiResponse.choices[0].message.content);
addCopyButton(chatContent, apiResponse.choices[0].message.content);
setTimeout(() => chatContent.removeChild(loadingMessage), 0);
} catch (error) {
const errorMessage = document.createElement('div');
errorMessage.textContent = '获取解答时出错,请稍后再试。';
chatContent.appendChild(errorMessage);
chatContent.scrollTop = chatContent.scrollHeight;
setTimeout(() => chatContent.removeChild(loadingMessage), 0);
}
}
};
inputContainer.appendChild(sendButton);
chatWindow.appendChild(inputContainer);
} else {
// 对话GPT窗口逻辑保持不变...
const inputContainer = document.createElement('div');
inputContainer.id = 'input-container';
const userInput = document.createElement('input');
userInput.type = 'text';
userInput.placeholder = '在这里输入你的问题...';
inputContainer.appendChild(userInput);
const sendButton = document.createElement('button');
sendButton.textContent = '发送';
sendButton.onclick = async function() {
const userMessage = userInput.value.trim();
if (userMessage) {
userInput.value = '';
const loadingMessage = document.createElement('div');
loadingMessage.textContent = '正在加载中…请耐心等待';
chatContent.appendChild(loadingMessage);
chatContent.scrollTop = chatContent.scrollHeight;
try {
const apiResponse = await sendMessageToAI(userMessage);
appendChatMessage(chatContent, apiResponse.choices[0].message.content);
addCopyButton(chatContent, apiResponse.choices[0].message.content);
setTimeout(() => chatContent.removeChild(loadingMessage), 0);
} catch (error) {
const errorMessage = document.createElement('div');
errorMessage.textContent = '获取解答时出错,请稍后再试。';
chatContent.appendChild(errorMessage);
chatContent.scrollTop = chatContent.scrollHeight;
setTimeout(() => chatContent.removeChild(loadingMessage), 0);
}
}
};
inputContainer.appendChild(sendButton);
chatWindow.appendChild(inputContainer);
}
document.body.appendChild(chatWindow);
}
function appendChatMessage(container, message) {
const messageDiv = document.createElement('div');
messageDiv.innerHTML = message.replace(/\n/g, '<br>');
container.appendChild(messageDiv);
container.scrollTop = container.scrollHeight; // 自动滚动到最底部
}
function addCopyButton(container, content) {
// 移除旧的复制按钮(如果有)
const oldCopyButton = container.querySelector('.copy-button');
if (oldCopyButton) {
container.removeChild(oldCopyButton);
}
// 创建新的复制按钮
const copyButton = document.createElement('div');
copyButton.className = 'copy-button';
copyButton.textContent = '点击复制此次回答';
copyButton.onclick = () => navigator.clipboard.writeText(content)
.then(() => console.log('回答已复制到剪贴板'))
.catch(err => console.error('无法复制回答:', err));
container.insertBefore(copyButton, container.lastElementChild); // 插入到输入框的上方
container.scrollTop = container.scrollHeight; // 再次确保滚动到最底部
}
function generateAutoAnswer() {
const pageText = getPageText();
const loadingMessage = document.createElement('div');
loadingMessage.textContent = '正在生成页面解答...';
const chatContent = document.getElementById('auto-answer-chat-content');
chatContent.appendChild(loadingMessage);
chatContent.scrollTop = chatContent.scrollHeight;
sendMessageToAI(pageText)
.then(response => {
appendChatMessage(chatContent, response.choices[0].message.content);
addCopyButton(chatContent, response.choices[0].message.content);
})
.catch(error => {
const errorMessage = document.createElement('div');
errorMessage.textContent = '生成页面解答时出错,请稍后再试。';
chatContent.appendChild(errorMessage);
})
.finally(() => {
setTimeout(() => chatContent.removeChild(loadingMessage), 0);
});
}
const buttonContainer = createButtonContainer();
document.body.insertBefore(buttonContainer, document.body.firstChild);
const parentButton = createParentButton(buttonContainer);
let isExpanded = false;
parentButton.onclick = function(event) {
if (isExpanded) {
hideButtons();
} else {
showButtons();
}
isExpanded = !isExpanded;
};
function forceRedraw(element) {
element.style.zIndex = 1;
void element.offsetWidth;
element.style.zIndex = '';
}
function showButtons() {
const buttons = Array.from(buttonContainer.querySelectorAll('.option-button'));
const initialTopOffset = -60;
buttons.forEach((button, index) => {
setTimeout(() => {
button.style.display = 'block';
button.style.top = `${initialTopOffset - index * 60}px`;
button.style.opacity = '1';
forceRedraw(button);
}, index * 200);
});
}
function hideButtons() {
const buttons = Array.from(buttonContainer.querySelectorAll('.option-button')).reverse();
buttons.forEach((button, index) => {
setTimeout(() => {
button.style.opacity = '0';
setTimeout(() => {
button.style.display = 'none';
button.style.top = '';
forceRedraw(button);
}, 200);
}, index * 200);
});
}
createOptionButtons(buttonContainer);
createChatWindow(false); // 对话GPT窗口
createChatWindow(true); // 获取页面自动解答窗口
createChatWindow(false, true); // 出题助记专属聊天窗口
})();