微件:Wiki AI
来自EaseCation Wiki
更多操作
<!DOCTYPE html> <html lang="zh-CN"> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wiki AI</title>
<style>
/* MW AI Chat Widget - 带前缀的样式,避免与 MediaWiki 冲突 */
.mwai-chat {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Liberation Sans", "Nimbus Sans L", "Helvetica Neue", Helvetica, Arial, sans-serif;
background: #f6f6f6;
color: #202122;
line-height: 1.6;
min-height: 500px;
display: flex;
flex-direction: column;
border: 1px solid #a2a9b1;
}
.mwai-chat-content {
flex: 1;
display: flex;
flex-direction: column;
background: #fff;
overflow: hidden;
}
.mwai-chat-messages {
flex: 1;
overflow-y: auto;
padding: 1rem;
}
.mwai-chat-message {
margin-bottom: 0.75rem;
padding: 0.625rem 0.875rem;
border-radius: 2px;
font-size: 0.875rem;
}
.mwai-chat-message-user {
background: #eaf3ff;
border: 1px solid #a3caff;
margin-left: 2rem;
}
.mwai-chat-message-assistant {
background: #f8f9fa;
border: 1px solid #eaecf0;
margin-right: 2rem;
}
.mwai-chat-message-system {
background: #fff3cd;
border: 1px solid #ffeaa7;
text-align: center;
margin: 0 2rem;
color: #856404;
}
.mwai-chat-message-error {
background: #fee7e6;
border: 1px solid #ffc8c8;
text-align: center;
margin: 0 2rem;
color: #d33;
}
.mwai-chat-message-content {
white-space: pre-wrap;
word-wrap: break-word;
}
.mwai-chat-input-area {
border-top: 1px solid #a2a9b1;
padding: 0.75rem 1rem;
background: #f8f9fa;
}
.mwai-chat-input-wrapper {
display: flex;
gap: 0.5rem;
}
.mwai-chat-input {
flex: 1;
padding: 0.375rem 0.625rem;
border: 1px solid #a2a9b1;
border-radius: 2px;
font-size: 0.8125rem;
font-family: inherit;
}
.mwai-chat-input:focus {
outline: none;
border-color: #3366cc;
box-shadow: 0 0 0 1px #3366cc;
}
.mwai-chat-button {
padding: 0.375rem 1rem;
background: #3366cc;
color: #fff;
border: 1px solid #3366cc;
border-radius: 2px;
font-size: 0.8125rem;
cursor: pointer;
}
.mwai-chat-button:hover {
background: #2a4b8d;
border-color: #2a4b8d;
}
.mwai-chat-button:disabled {
background: #c8ccd1;
border-color: #c8ccd1;
cursor: not-allowed;
}
.mwai-chat-status {
font-size: 0.75rem;
color: #72777d;
margin-top: 0.375rem;
}
@media (max-width: 768px) {
.mwai-chat-message-user {
margin-left: 0.5rem;
}
.mwai-chat-message-assistant {
margin-right: 0.5rem;
}
}
</style>
</head> <body>
<input type="text" class="mwai-chat-input" id="mwai-chat-input" placeholder="输入您的问题..." autocomplete="off">
<button class="mwai-chat-button" id="mwai-chat-button" onclick="mwaiSendMessage()">发送</button>
<script>
(function() {
const API_URL = 'https://api.wiki.easecation.net/ai/v1/responses';
let sessionId = 'mw-' + crypto.randomUUID();
let isStreaming = false;
const inputEl = document.getElementById('mwai-chat-input');
const buttonEl = document.getElementById('mwai-chat-button');
const messagesEl = document.getElementById('mwai-chat-messages');
const statusEl = document.getElementById('mwai-chat-status');
inputEl.addEventListener('keypress', function(e) {
if (e.key === 'Enter' && !isStreaming) {
mwaiSendMessage();
}
});
function addMessage(content, role) {
const div = document.createElement('div');
div.className = 'mwai-chat-message mwai-chat-message-' + role;
const contentDiv = document.createElement('div');
contentDiv.className = 'mwai-chat-message-content';
contentDiv.textContent = content;
div.appendChild(contentDiv);
messagesEl.appendChild(div);
messagesEl.scrollTop = messagesEl.scrollHeight;
return div;
}
function updateMessage(element, content) {
element.querySelector('.mwai-chat-message-content').textContent = content;
messagesEl.scrollTop = messagesEl.scrollHeight;
}
function setStatus(text) {
statusEl.textContent = text;
}
window.mwaiSendMessage = function() {
const message = inputEl.value.trim();
if (!message || isStreaming) return;
addMessage(message, 'user');
inputEl.value = ;
const aiMessageEl = addMessage('...', 'assistant');
isStreaming = true;
buttonEl.disabled = true;
setStatus('连接中...');
let fullResponse = ;
fetch(API_URL, {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
input: message,
session_id: sessionId,
stream: true
})
}).then(function(response) {
if (response.status === 401) {
updateMessage(aiMessageEl, '请先登录 Wiki');
aiMessageEl.className = 'mwai-chat-message mwai-chat-message-error';
setStatus();
isStreaming = false;
buttonEl.disabled = false;
return;
}
if (response.status === 429) {
return response.json().then(function(data) {
updateMessage(aiMessageEl, data.message || '今日使用次数已达上限');
aiMessageEl.className = 'mwai-chat-message mwai-chat-message-system';
setStatus();
isStreaming = false;
buttonEl.disabled = false;
});
}
if (!response.ok) {
throw new Error('HTTP ' + response.status);
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
setStatus('生成中...');
function readStream() {
return reader.read().then(function(result) {
if (result.done) {
setStatus();
isStreaming = false;
buttonEl.disabled = false;
return;
}
const chunk = decoder.decode(result.value, { stream: true });
const lines = chunk.split('\n');
lines.forEach(function(line) {
if (!line.startsWith('data: ')) return;
const data = line.slice(6);
if (data === '[DONE]') return;
try {
const event = JSON.parse(data);
if (event.type === 'response.output_text.delta') {
fullResponse += event.delta;
updateMessage(aiMessageEl, fullResponse);
} else if (event.type === 'response.completed') {
if (event.response && event.response.output &&
event.response.output[0] && event.response.output[0].content &&
event.response.output[0].content[0] && event.response.output[0].content[0].text) {
fullResponse = event.response.output[0].content[0].text;
updateMessage(aiMessageEl, fullResponse);
}
setStatus();
} else if (event.type === 'response.error') {
updateMessage(aiMessageEl, '错误: ' + event.error);
aiMessageEl.className = 'mwai-chat-message mwai-chat-message-error';
setStatus();
}
} catch (e) {}
});
return readStream();
});
}
return readStream();
}).catch(function(error) {
console.error(error);
updateMessage(aiMessageEl, '连接失败,请稍后重试');
aiMessageEl.className = 'mwai-chat-message mwai-chat-message-error';
setStatus();
isStreaming = false;
buttonEl.disabled = false;
});
};
})();
</script>
</body> </html>