MistralApp / templates /index.html
chenzerong
change some tips
0c23af4
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>知微小智</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
padding: 0;
background-color: #f5f8fa;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.sidebar {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
padding: 20px;
margin-bottom: 20px;
}
.chat-container {
display: flex;
height: calc(100vh - 200px);
min-height: 500px;
gap: 20px;
}
.chat-box {
flex: 1;
background-color: #fff;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
display: flex;
flex-direction: column;
overflow: hidden;
}
.chat-messages {
flex: 1;
overflow-y: auto;
padding: 20px;
}
.message {
margin-bottom: 16px;
display: flex;
align-items: flex-start;
}
.user-message {
justify-content: flex-end;
}
.assistant-message {
justify-content: flex-start;
}
.message-content {
max-width: 80%;
padding: 12px 16px;
border-radius: 18px;
overflow-wrap: break-word;
}
.user-message .message-content {
background-color: #0084ff;
color: white;
border-bottom-right-radius: 4px;
}
.assistant-message .message-content {
background-color: #f1f0f0;
color: #333;
border-bottom-left-radius: 4px;
}
.message-image {
max-width: 100%;
max-height: 300px;
border-radius: 8px;
margin-bottom: 8px;
}
.input-area {
background-color: #fff;
border-top: 1px solid #e6ecf0;
padding: 15px;
display: flex;
align-items: center;
gap: 10px;
}
.image-preview {
display: flex;
gap: 10px;
margin-bottom: 10px;
flex-wrap: wrap;
}
.image-preview img {
max-width: 100px;
max-height: 100px;
border-radius: 4px;
object-fit: cover;
}
.preview-container {
position: relative;
display: inline-block;
}
.remove-image {
position: absolute;
top: -5px;
right: -5px;
background-color: rgba(255, 255, 255, 0.8);
border-radius: 50%;
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
font-size: 12px;
border: 1px solid #ddd;
}
textarea {
flex: 1;
border: 1px solid #e6ecf0;
border-radius: 20px;
padding: 10px 15px;
resize: none;
height: 48px;
font-size: 16px;
line-height: 1.5;
outline: none;
}
.send-button {
border: none;
background-color: #0084ff;
color: white;
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
}
.send-button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.clear-button {
background-color: #f7f7f7;
border: 1px solid #ddd;
color: #666;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
margin-bottom: 15px;
}
.clear-button:hover {
background-color: #ebebeb;
}
.system-prompt {
width: 100%;
padding: 10px;
border: 1px solid #e6ecf0;
border-radius: 4px;
margin-bottom: 15px;
min-height: 100px;
resize: vertical;
}
.thinking {
font-style: italic;
color: #666;
margin-bottom: 15px;
padding: 10px;
border-radius: 8px;
background-color: #f9f9f9;
display: inline-block;
}
</style>
</head>
<body>
<div class="container">
<h1 class="mb-4">知微小智</h1>
<div class="chat-container">
<div class="chat-box">
<div class="chat-messages" id="chat-messages">
<!-- 聊天消息将在这里动态添加 -->
</div>
<div class="input-area-container">
<div class="image-preview" id="image-preview"></div>
<div class="input-area">
<textarea id="message-input" placeholder="输入消息或按Ctrl+V粘贴图片..." onkeydown="handleKeyDown(event)"></textarea>
<button class="send-button" id="send-button" onclick="sendMessage()" disabled>
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M22 2L11 13" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M22 2L15 22L11 13L2 9L22 2Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
</div>
</div>
<div class="sidebar" style="width: 300px;">
<h5>设置</h5>
<label for="system-prompt">系统提示</label>
<textarea id="system-prompt" class="system-prompt">你是一个AI度量专家助手。你可以分析文本和图像的内容。能根据用户的需求给出度量建议和洞察</textarea>
<button class="clear-button" onclick="clearChat()">清除聊天记录</button>
<div class="mt-4">
<p><strong>使用说明</strong></p>
<ul>
<li>输入文字直接提问</li>
<li>使用Ctrl+V粘贴图片</li>
<li>图片和文字可以一起发送</li>
</ul>
</div>
</div>
</div>
</div>
<script>
// 全局变量
let chatHistory = [];
let currentImageData = null;
// 页面加载时初始化
document.addEventListener('DOMContentLoaded', function() {
// 监听粘贴事件
document.addEventListener('paste', handlePaste);
// 监听输入框变化
const messageInput = document.getElementById('message-input');
messageInput.addEventListener('input', function() {
document.getElementById('send-button').disabled = !messageInput.value.trim() && !currentImageData;
});
});
// 处理粘贴事件
function handlePaste(event) {
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
for (let i = 0; i < items.length; i++) {
if (items[i].type.indexOf('image') !== -1) {
const blob = items[i].getAsFile();
const reader = new FileReader();
reader.onload = function(e) {
// 设置当前图片数据
currentImageData = e.target.result;
// 显示图片预览
const imagePreview = document.getElementById('image-preview');
imagePreview.innerHTML = `
<div class="preview-container">
<img src="${e.target.result}" alt="粘贴的图片">
<div class="remove-image" onclick="removeImage()">×</div>
</div>
`;
// 启用发送按钮
document.getElementById('send-button').disabled = false;
// 发送图片到服务器保存
saveImageToServer(currentImageData);
};
reader.readAsDataURL(blob);
}
}
}
// 移除图片
function removeImage() {
currentImageData = null;
document.getElementById('image-preview').innerHTML = '';
// 如果消息输入框也是空的,禁用发送按钮
const messageInput = document.getElementById('message-input');
document.getElementById('send-button').disabled = !messageInput.value.trim();
}
// 保存图片到服务器
function saveImageToServer(imageData) {
fetch('/api/paste_image', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ image_data: imageData })
})
.then(response => response.json())
.then(data => {
if (data.status === 'success') {
// 成功保存,可以在这里做一些处理,比如更新图片预览的src为服务器返回的URL
console.log('图片已保存到服务器:', data.image_url);
} else {
console.error('保存图片错误:', data.message);
}
})
.catch(error => {
console.error('保存图片请求错误:', error);
});
}
// 发送消息的键盘处理
function handleKeyDown(event) {
if (event.key === 'Enter' && !event.shiftKey) {
event.preventDefault();
sendMessage();
}
}
// 发送消息
function sendMessage() {
const messageInput = document.getElementById('message-input');
const message = messageInput.value.trim();
// 如果没有消息文本也没有图片,不发送
if (!message && !currentImageData) {
return;
}
// 添加用户消息到聊天窗口
addMessageToChat('user', message, currentImageData);
// 准备请求数据
const systemPrompt = document.getElementById('system-prompt').value.trim();
let history = [...chatHistory];
// 确保历史记录中有系统提示
const hasSystemPrompt = history.some(msg => msg.role === 'system');
if (!hasSystemPrompt && systemPrompt) {
history.unshift({
role: 'system',
content: systemPrompt
});
}
// 显示思考中状态
const thinkingEl = document.createElement('div');
thinkingEl.className = 'message assistant-message';
thinkingEl.innerHTML = '<div class="thinking">思考中...</div>';
document.getElementById('chat-messages').appendChild(thinkingEl);
// 发送请求到后端
fetch('/api/chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: message,
image: currentImageData,
history: history
})
})
.then(response => response.json())
.then(data => {
// 移除思考中状态
document.getElementById('chat-messages').removeChild(thinkingEl);
if (data.status === 'success') {
// 添加助手响应到聊天窗口
addMessageToChat('assistant', data.response);
} else {
// 显示错误消息
addMessageToChat('assistant', `错误: ${data.message}`);
}
})
.catch(error => {
// 移除思考中状态
document.getElementById('chat-messages').removeChild(thinkingEl);
// 显示错误消息
addMessageToChat('assistant', `请求错误: ${error}`);
});
// 清空输入
messageInput.value = '';
removeImage();
// 禁用发送按钮
document.getElementById('send-button').disabled = true;
}
// 添加消息到聊天窗口和历史记录
function addMessageToChat(role, content, image = null) {
const chatMessages = document.getElementById('chat-messages');
// 创建消息元素
const messageEl = document.createElement('div');
messageEl.className = `message ${role}-message`;
let messageContent = '';
// 如果有图片,添加图片
if (image) {
messageContent += `<img src="${image}" alt="用户上传的图片" class="message-image"><br>`;
}
// 添加文本内容
if (content) {
messageContent += content.replace(/\n/g, '<br>');
}
messageEl.innerHTML = `<div class="message-content">${messageContent}</div>`;
chatMessages.appendChild(messageEl);
// 滚动到底部
chatMessages.scrollTop = chatMessages.scrollHeight;
// 添加到历史记录
chatHistory.push({
role: role,
content: content
});
}
// 清除聊天记录
function clearChat() {
chatHistory = [];
document.getElementById('chat-messages').innerHTML = '';
removeImage();
}
</script>
</body>
</html>