Init commit.
This commit is contained in:
commit
2af23e7757
8 files changed
+1298
No files matched your search
@@ -0,0 +1,158 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>ChatBot</title>
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body { font-family: -apple-system, system-ui, sans-serif; background: #111; color: #eee; height: 100dvh; display: flex; flex-direction: column; }
|
||||
header { padding: 12px 16px; border-bottom: 1px solid #333; display: flex; align-items: center; gap: 8px; }
|
||||
header h1 { font-size: 16px; font-weight: 600; }
|
||||
header .config-btn { margin-left: auto; background: #333; border: none; color: #eee; padding: 4px 12px; border-radius: 6px; cursor: pointer; font-size: 13px; }
|
||||
.config-panel { display: none; padding: 12px 16px; border-bottom: 1px solid #333; background: #1a1a1a; gap: 8px; flex-wrap: wrap; align-items: center; }
|
||||
.config-panel.open { display: flex; }
|
||||
.config-panel label { font-size: 12px; color: #888; white-space: nowrap; }
|
||||
.config-panel input { background: #222; border: 1px solid #444; color: #eee; padding: 6px 10px; border-radius: 6px; font-size: 13px; min-width: 140px; flex: 1; }
|
||||
main { flex: 1; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px; }
|
||||
.msg { max-width: 80%; padding: 10px 14px; border-radius: 12px; line-height: 1.5; font-size: 14px; white-space: pre-wrap; word-break: break-word; }
|
||||
.msg.user { align-self: flex-end; background: #2563eb; }
|
||||
.msg.assistant { align-self: flex-start; background: #333; }
|
||||
.msg.system { align-self: center; font-size: 12px; color: #888; background: transparent; }
|
||||
footer { padding: 12px 16px; border-top: 1px solid #333; display: flex; gap: 8px; }
|
||||
footer textarea { flex: 1; resize: none; background: #222; border: 1px solid #444; color: #eee; padding: 10px; border-radius: 10px; font-size: 14px; font-family: inherit; min-height: 44px; max-height: 120px; }
|
||||
footer button { background: #2563eb; border: none; color: #fff; padding: 10px 20px; border-radius: 10px; cursor: pointer; font-size: 14px; font-weight: 500; white-space: nowrap; }
|
||||
footer button:disabled { opacity: 0.5; cursor: not-allowed; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<h1>ChatBot</h1>
|
||||
<button class="config-btn" onclick="toggleConfig()">Settings</button>
|
||||
</header>
|
||||
|
||||
<div class="config-panel" id="configPanel">
|
||||
<label>Model</label>
|
||||
<input id="modelInput" placeholder="gpt-5.4-nano" />
|
||||
<label>API Key</label>
|
||||
<input id="keyInput" type="password" placeholder="sk-ABCD" />
|
||||
<label>User ID</label>
|
||||
<input id="userIdInput" placeholder="65535" style="min-width:80px;flex:0.5" />
|
||||
</div>
|
||||
|
||||
<main id="chatBox"></main>
|
||||
|
||||
<footer>
|
||||
<textarea id="input" rows="1" placeholder="Type a message..." onkeydown="onKeyDown(event)"></textarea>
|
||||
<button id="sendBtn" onclick="send()">Send</button>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
let messages = []
|
||||
|
||||
function toggleConfig() {
|
||||
document.getElementById('configPanel').classList.toggle('open')
|
||||
loadConfig()
|
||||
}
|
||||
|
||||
function loadConfig() {
|
||||
const m = localStorage.getItem('chat_model') || 'gpt-5.4-nano'
|
||||
const k = localStorage.getItem('chat_key') || 'sk-ABCD'
|
||||
const u = localStorage.getItem('chat_userid') || '65535'
|
||||
document.getElementById('modelInput').value = m
|
||||
document.getElementById('keyInput').value = k
|
||||
document.getElementById('userIdInput').value = u
|
||||
}
|
||||
|
||||
function saveConfig() {
|
||||
const m = document.getElementById('modelInput').value.trim()
|
||||
const k = document.getElementById('keyInput').value.trim()
|
||||
const u = document.getElementById('userIdInput').value.trim()
|
||||
if (m) localStorage.setItem('chat_model', m)
|
||||
if (k) localStorage.setItem('chat_key', k)
|
||||
if (u) localStorage.setItem('chat_userid', u)
|
||||
}
|
||||
|
||||
function getConfig() {
|
||||
return {
|
||||
model: localStorage.getItem('chat_model') || '',
|
||||
key: localStorage.getItem('chat_key') || '',
|
||||
userId: localStorage.getItem('chat_userid') || '',
|
||||
}
|
||||
}
|
||||
|
||||
loadConfig()
|
||||
document.getElementById('modelInput').addEventListener('input', saveConfig)
|
||||
document.getElementById('keyInput').addEventListener('input', saveConfig)
|
||||
document.getElementById('userIdInput').addEventListener('input', saveConfig)
|
||||
|
||||
function addMsg(role, text) {
|
||||
const div = document.createElement('div')
|
||||
div.className = 'msg ' + role
|
||||
div.textContent = text
|
||||
document.getElementById('chatBox').appendChild(div)
|
||||
div.scrollIntoView({ behavior: 'smooth' })
|
||||
}
|
||||
|
||||
function onKeyDown(e) {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault()
|
||||
send()
|
||||
}
|
||||
}
|
||||
|
||||
async function send() {
|
||||
const input = document.getElementById('input')
|
||||
const btn = document.getElementById('sendBtn')
|
||||
const text = input.value.trim()
|
||||
if (!text) return
|
||||
|
||||
input.value = ''
|
||||
input.disabled = true
|
||||
btn.disabled = true
|
||||
|
||||
messages.push({ role: 'user', content: text, name: 'ClawBot' })
|
||||
addMsg('user', text)
|
||||
|
||||
const { model, key, userId } = getConfig()
|
||||
|
||||
const payload = {
|
||||
user_id: userId || undefined,
|
||||
model: model || undefined,
|
||||
messages,
|
||||
temperature: 0.7,
|
||||
max_tokens: 0,
|
||||
top_p: 1,
|
||||
frequency_penalty: 0,
|
||||
presence_penalty: 0,
|
||||
stream: false,
|
||||
}
|
||||
|
||||
try {
|
||||
const headers = { 'Content-Type': 'application/json' }
|
||||
if (key) headers['X-API-Key'] = key
|
||||
|
||||
const resp = await fetch('/api/chat', {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify(payload),
|
||||
})
|
||||
|
||||
const data = await resp.json()
|
||||
if (data.error) {
|
||||
addMsg('system', 'Error: ' + data.error)
|
||||
} else {
|
||||
messages.push({ role: 'assistant', content: data.reply })
|
||||
addMsg('assistant', data.reply)
|
||||
}
|
||||
} catch (err) {
|
||||
addMsg('system', 'Network error: ' + err.message)
|
||||
} finally {
|
||||
input.disabled = false
|
||||
btn.disabled = false
|
||||
input.focus()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user