ChatGPT-Tailwind/index.html
2023-09-13 16:40:16 +08:00

329 lines
17 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-cn">
<head>
<meta charset="utf-8">
<title>ChatGPT-Tailwind</title>
<meta name="viewport"
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="shortcut icon" href="https://cdn-img-qiniu.czl.net/2023/08/03/64cb6db97b0bf.png">
<link href="https://cdnjs.cloudflare.com/ajax/libs/daisyui/3.6.4/full.min.css" rel="stylesheet" type="text/css" />
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/13.0.1/markdown-it.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/vs2015.min.css" />
<style>
body {
font-family: system-ui, -apple-system, "Microsoft YaHei", Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif !important;
}
</style>
<link href="https://cdn.czl.net/frame/tailwind/typography.css" rel="stylesheet" type="text/css">
</head>
<body class="pb-72 pt-20 h-full">
<!-- 头部展示 -->
<div class="w-full fixed top-0 bg-gray-700 text-center py-5 z-50">
<h1 class="text-white text-lg font-bold">ChatGPT-Tailwind</h1>
</div>
<!-- 填写地址和密钥 -->
<div class="container mx-auto bg-blue-300 px-4 py-5 shadow-md hover:shadow-blue-500/50 -mt-5">
<div class="flex flex-wrap items-center justify-evenly ">
<div class="w-full md:w-1/3 mb-4 px-4">
<div class="flex flex-col">
<div class="flex items-center mb-1">
<b>网址:</b>
<input
class="border-2 border-gray-300 bg-white h-10 px-2 rounded-lg text-sm flex-grow focus:outline-none"
placeholder="api.openai.com" type="text" id="proxyurl" required value="oapi.czl.net" />
</div>
<p class="text-xs italics ">*代理域名,无需"https://"</p>
</div>
</div>
<div class="w-full md:w-1/3 mb-4 px-4">
<div class="flex flex-col">
<div class="flex items-center mb-1">
<b>Key</b>
<input
class="border-2 border-gray-300 bg-white h-10 px-2 rounded-lg text-sm flex-grow focus:outline-none"
placeholder="sk-xxxxxxxxxxx" type="text" id="key" required />
</div>
<div class="text-xs italics">*填写你的key<a href="https://oapi.czl.net" target="_blank"
class="link link-error">获取国内可用key</a></div>
</div>
</div>
<div class="w-full md:w-1/3 mb-4 px-4">
<div class="flex flex-col">
<div class="flex items-center mb-1">
<b>模型:</b>
<select
class="border-2 border-gray-300 bg-white h-10 px-2 rounded-lg text-sm flex-grow focus:outline-none select-primary"
id="model">
<!-- your options here -->
<option value="gpt-3.5-turbo">gpt-3.5-turbo</option>
<option value="gpt-3.5-turbo-0301">gpt-3.5-turbo-0301</option>
<option value="gpt-3.5-turbo-0613">gpt-3.5-turbo-0613</option>
<option value="gpt-3.5-turbo-16k">gpt-3.5-turbo-16k</option>
<option value="gpt-3.5-turbo-16k-0613">gpt-3.5-turbo-16k-0613</option>
<option value="gpt-4">gpt-4</option>
<option value="gpt-4-0301">gpt-4-0301</option>
<option value="gpt-4-0613">gpt-4-0613</option>
<option value="gpt-4-32k">gpt-4-32k</option>
<option value="gpt-4-32k-0613">gpt-4-32k-0613</option>
<option value="PaLM-2">PaLM-2</option>
<option value="ERINIE-Bot">ERNIE-Bot</option>
<option value="ERNIE-Bot-turbo">ERNIE-Bot-turbo</option>
<option value="BLOOMZ-7B">BLOOMZ-7B</option>
<option value="Embedding-V1">Embedding-V1</option>
<option value="chatglm_std">chatglm_std</option>
<option value="chatglm_lite">chatglm_lite</option>
<option value="chatglm_pro">chatglm_pro</option>
<option value="qwen-v1">qwen-v1</option>
<option value="qwen-plus-v1">qwen-plus-v1</option>
<option value="SparkDesk">SparkDesk</option>
<option value="360GPT_S2_V9">360GPT_S2_V9</option>
<option value="embedding-bert-512-v1">embedding-bert-512-v1</option>
<option value="embedding_s1_v1">embedding_s1_v1</option>
<option value="semantic_similarity_s1_v1">semantic_similarity_s1_v1</option>
<option value="360GPT_S2_V9.4">360GPT_S2_V9.4</option>
</select>
</div>
<div class="text-xs italics">*选择模型</div>
</div>
</div>
<div class="w-full ">
<div class="flex items-center">
</div>
</div>
</div>
<div class="text-center py-2 bg-blue-100">
本项目由<a href="https://woodchen.ink" target="_blank" class="link link-accent">woodchen</a>开源于<a
class="link link-accent" href="https://github.com/woodchen-ink/ChatGPT-Tailwind"
target="_blank">Github</a>, 欢迎给个star
</div>
</div>
<!-- 对话展示 -->
<div class="container mx-auto" id="chatbox">
</div>
<!-- 底部固定 -->
<div class="w-full fixed bottom-0 bg-gray-700 py-4">
<div class="container mx-auto">
<textarea id="userInput" class="w-full textarea textarea-inf" type="text" rows="3"
placeholder="在这里输入问题...换行请按Shift+Enter"></textarea>
<button id="sendButton" class="btn btn-info btn-block">询问</button>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.11/clipboard.min.js"></script>
<script>
const url = new URL(window.location.href);
const chatbox = $("#chatbox");
const userInput = $("#userInput");
const sendButton = $("#sendButton");
$(document).ready(function () {
const messages = [];
sendButton.on("click", () => {
const message = userInput.val();
if (message) {
messages.push({
"role": "user",
"content": message
});
chatbox.append(`<div class="chat chat-end"><div class="chat-image avatar">
<div class="w-10 rounded-full">
<img src="https://cdn-img.czl.net/2023/08/10/64d3b992cf86e.png" />
</div>
</div>
<div class="chat-header">You</div><div class="chat-bubble chat-bubble-info">${message}</div><div>`);
userInput.val("");
sendButton.html('<span class="loading loading-infinity loading-lg"></span>');
sendButton.removeClass('btn-info').addClass('btn-error');
// sendButton.prop("disabled", true);
fetchMessages();
}
});
userInput.on("keydown", (event) => {
if (event.keyCode === 13 && !event.ctrlKey && !event.shiftKey) {
event.preventDefault();
sendButton.click();
} else if (event.keyCode === 13 && (event.ctrlKey || event.shiftKey)) {
event.preventDefault();
const cursorPosition = userInput.prop("selectionStart");
const currentValue = userInput.val();
userInput.val(
currentValue.slice(0, cursorPosition) +
"\n" +
currentValue.slice(cursorPosition)
);
userInput.prop("selectionStart", cursorPosition + 1);
userInput.prop("selectionEnd", cursorPosition + 1);
}
});
function fetchMessages() {
let proxyurl = document.getElementById("proxyurl").value;
let key = document.getElementById("key").value;
let modelElement = document.getElementById("model");
let model = modelElement.options[modelElement.selectedIndex].value;
$("#proxyurl").val();
$("#key").val();
try {
var settings = {
"url": "https://" + proxyurl + "/v1/chat/completions",
"method": "POST",
"timeout": 0,
"headers": {
"Authorization": "Bearer " + key,
"Content-Type": "application/json"
},
"data": JSON.stringify({
"model": model,
"messages": messages
}),
};
$.ajax(settings).done(function (response) {
console.log(response)
const message = response.choices[0].message
messages.push({
role: message.role,
content: message.content,
})
let htmlText = window.markdownit().render(message.content);
htmlText = htmlText.replace(/<pre>/g, '<pre class="pre-with-button">');
const chatBubbleClass =
message.role === 'user'
? 'chat-bubble-info'
: 'chat-bubble-accent'
const avatarURL =
message.role === 'user'
? 'https://cdn-img.czl.net/2023/08/10/64d3b992cf86e.png'
: 'https://cdn-img.czl.net/2023/08/10/64d3b8c9819c7.png'
const chatHeader = message.role === 'user' ? 'You' : 'AI'
let myID = 'codeSnippet-' + Date.now()
let preID = 'pre-' + Date.now()
if (htmlText.includes('<code')) {
htmlText = htmlText.replace('<pre', '<pre id="' + preID + '"')
htmlText = htmlText.replace('<code', '<code id="' + myID + '"')
}
console.log('htmlText', htmlText)
const chatHTML = `
<div class="chat chat-start">
<div class="chat-image avatar">
<div class="w-10 rounded-full">
<img src="${avatarURL}" />
</div>
</div>
<div class="chat-header">${chatHeader}</div>
<div class="chat-bubble ${chatBubbleClass} prose prose-slate">${htmlText}</div>
</div>`
$('#chatbox').append(chatHTML);
$('.pre-with-button').each(function (index) {
if ($(this).find('code').length > 0) {
let preElement = $(this);
let codeElement = $(this).find('code')[0];
var copyButton = document.createElement('button');
copyButton.classList.add('absolute', 'right-5', 'mt-[-20px]', 'mr-1', 'btn', 'btn-active', 'btn-xs');
copyButton.innerText = 'COPY';
var clipboard = new ClipboardJS(copyButton, {
text: function () {
return codeElement.innerText;
},
});
clipboard.on('success', function (e) {
console.log('Success');
let alertBox = document.createElement('div');
alertBox.classList.add('fixed', 'top-20', 'left-1/2', 'transform', '-translate-x-1/2', 'z-50');
alertBox.innerHTML = `
<div class="alert alert-success">
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>Success! Your text has been copied.</span>
</div>`;
document.body.appendChild(alertBox);
setTimeout(function () {
document.body.removeChild(alertBox);
}, 500);
});
clipboard.on('error', function (e) {
console.log('Failed');
let alertBox = document.createElement('div');
alertBox.classList.add('fixed', 'top-20', 'left-1/2', 'transform', '-translate-x-1/2', 'z-50');
alertBox.innerHTML = `
<div class="alert alert-error">
<svg xmlns="http://www.w3.org/2000/svg" class="stroke-current shrink-0 h-6 w-6" fill="none" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
<span>Error! Copy failed.</span>
</div>`;
document.body.appendChild(alertBox);
setTimeout(function () {
document.body.removeChild(alertBox);
}, 500);
})
preElement.append(copyButton);
}
});
hljs.highlightAll();
sendButton.html('<span>询问</span>')
sendButton.removeClass('btn-error').addClass('btn-info')
}).fail(function (jqXHR, textStatus, errorThrown) {
sendButton.html('<span>询问</span>');
sendButton.removeClass('btn-error').addClass('btn-info');
var errorMessage;
if (jqXHR.status === 0) {
errorMessage = "Network error, please check your internet connection.";
} else {
var response = JSON.parse(jqXHR.responseText);
errorMessage = response.error.message;
}
chatbox.append(`<div class="chat chat-start"><div class="chat-image avatar">
<div class="w-10 rounded-full">
<img src="https://cdn-img.czl.net/2023/08/10/64d3b8c9819c7.png" />
</div>
</div>
<div class="chat-header">AI</div><div class="chat-bubble chat-bubble-error prose prose-slate">Error: ${errorMessage}</div><div>`);
});
} catch (error) {
sendButton.html('<span>询问</span>');
sendButton.removeClass('btn-error').addClass('btn-info');
chatbox.append(`<div class="chat chat-start"><div class="chat-image avatar">
<div class="w-10 rounded-full">
<img src="https://cdn-img.czl.net/2023/08/10/64d3b8c9819c7.png" />
</div>
</div>
<div class="chat-header">AI</div><div class="chat-bubble chat-bubble-error prose prose-slate">Error: ${error.message}</div><div>`);
}
}
});
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js" defer></script>
</body>
</html>