fix: 文件上传融合到graph.html(星图页面),删除冗余index.html

This commit is contained in:
root
2026-04-29 10:14:23 +08:00
parent 4fc8ca944b
commit df156ba840
3 changed files with 207 additions and 1412 deletions

View File

@ -149,8 +149,8 @@ def admin_required(f):
@app.route('/')
@login_required
def index():
"""返回聊天页面(默认首页)"""
return app.send_static_file('index.html')
"""默认首页 - 星图页面"""
return app.send_static_file('graph.html')
@app.route('/graph.html')
@ -159,13 +159,6 @@ def graph_html():
"""返回星图页面"""
return app.send_static_file('graph.html')
@app.route('/chat')
@login_required
def chat():
"""返回聊天页面"""
return app.send_static_file('index.html')
# 全局服务器和客户端实例
backend_server: BackendServer = None
backend_client: BackendClient = None

View File

@ -331,6 +331,104 @@
.chat-input-area button:hover {
background: rgba(68, 136, 255, 0.5);
}
.chat-input-area textarea {
flex: 1;
background: rgba(20, 20, 40, 0.9);
border: 1px solid rgba(100, 100, 255, 0.2);
color: #eee;
padding: 10px 14px;
border-radius: 6px;
font-family: 'Courier New', monospace;
font-size: 13px;
outline: none;
resize: none;
min-height: 40px;
max-height: 120px;
}
.chat-input-area textarea:focus {
border-color: rgba(68, 136, 255, 0.5);
}
.attach-btn {
background: rgba(68, 136, 255, 0.2);
border: 1px solid rgba(68, 136, 255, 0.3);
color: #aaf;
width: 40px;
height: 40px;
border-radius: 6px;
cursor: pointer;
font-size: 18px;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
flex-shrink: 0;
}
.attach-btn:hover {
background: rgba(68, 136, 255, 0.4);
}
.chat-files-container {
display: flex;
flex-wrap: wrap;
gap: 6px;
padding: 8px 16px;
border-top: 1px solid rgba(100, 100, 255, 0.1);
background: rgba(10, 10, 25, 0.5);
}
.chat-file-chip {
display: flex;
align-items: center;
gap: 6px;
background: rgba(40, 40, 80, 0.8);
border: 1px solid rgba(100, 100, 255, 0.25);
border-radius: 4px;
padding: 4px 8px;
font-size: 12px;
color: #dde;
max-width: 200px;
}
.chat-file-chip .file-icon {
color: #7af;
flex-shrink: 0;
}
.chat-file-chip .file-name {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
flex: 1;
}
.chat-file-chip .file-size {
color: #889;
font-size: 10px;
flex-shrink: 0;
}
.chat-file-chip .file-remove {
color: #f66;
cursor: pointer;
font-size: 14px;
line-height: 1;
flex-shrink: 0;
}
.chat-file-chip .file-remove:hover {
color: #f33;
}
.chat-messages.drag-over {
background: rgba(68, 136, 255, 0.15);
border: 2px dashed rgba(68, 136, 255, 0.6);
}
.chat-messages.drag-over::after {
content: '📄 松开以上传文件';
position: absolute;
top: 50%; left: 50%;
transform: translate(-50%, -50%);
background: rgba(10, 10, 40, 0.9);
border: 2px dashed rgba(68, 136, 255, 0.5);
color: #4488ff;
padding: 20px 40px;
border-radius: 12px;
font-size: 18px;
z-index: 10;
pointer-events: none;
}
.chat-status {
padding: 8px 16px;
border-top: 1px solid rgba(100, 100, 255, 0.1);
@ -435,9 +533,12 @@
<div class="chat-welcome">你好!我是 TrulyMEM你的图记忆助手~</div>
</div>
<div class="chat-input-area">
<input type="text" id="chatInput" placeholder="输入消息..." autocomplete="off">
<textarea id="chatInput" placeholder="输入消息..." autocomplete="off" rows="1"></textarea>
<button class="attach-btn" id="attachBtn" title="添加文件">📎</button>
<button id="chatSendBtn">发送</button>
</div>
<input type="file" id="fileInput" multiple style="display:none">
<div class="chat-files-container" id="chatFilesContainer"></div>
<div class="chat-status" id="chatStatus"><span class="status-dot" style="color:#22c55e"></span> 已连接</div>
</div>
<button id="toggle-chat"><i class="fas fa-thumbtack"></i></button>
@ -1775,6 +1876,73 @@ function smoothReposition() {
const chatCloseBtn = document.getElementById('chatCloseBtn');
const toggleChat = document.getElementById('toggle-chat');
const chatPanel = document.getElementById('chat-panel');
const attachBtn = document.getElementById('attachBtn');
const fileInput = document.getElementById('fileInput');
const chatFilesContainer = document.getElementById('chatFilesContainer');
let attachedFiles = [];
function formatFileSize(bytes) {
if (bytes < 1024) return bytes + 'B';
if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + 'KB';
return (bytes / (1024 * 1024)).toFixed(1) + 'MB';
}
function getFileKey(file) {
return file.name + '_' + file.size;
}
function addFileChip(file) {
const key = getFileKey(file);
if (attachedFiles.some(f => getFileKey(f) === key)) return;
attachedFiles.push(file);
renderFileChips();
}
function removeFileChip(file) {
const key = getFileKey(file);
attachedFiles = attachedFiles.filter(f => getFileKey(f) !== key);
renderFileChips();
}
function renderFileChips() {
chatFilesContainer.innerHTML = '';
attachedFiles.forEach(file => {
const chip = document.createElement('div');
chip.className = 'chat-file-chip';
chip.innerHTML = `<span class="file-icon">📄</span><span class="file-name" title="${file.name}">${file.name}</span><span class="file-size">${formatFileSize(file.size)}</span><span class="file-remove" title="删除">✕</span>`;
chip.querySelector('.file-remove').onclick = () => removeFileChip(file);
chatFilesContainer.appendChild(chip);
});
}
// 输入框自适应高度
chatInput.addEventListener('input', () => {
chatInput.style.height = 'auto';
chatInput.style.height = Math.min(chatInput.scrollHeight, 120) + 'px';
});
attachBtn.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', () => {
Array.from(fileInput.files).forEach(addFileChip);
fileInput.value = '';
});
chatMessages.addEventListener('dragover', e => {
e.preventDefault();
chatMessages.classList.add('drag-over');
});
chatMessages.addEventListener('dragleave', () => {
chatMessages.classList.remove('drag-over');
});
chatMessages.addEventListener('drop', e => {
e.preventDefault();
chatMessages.classList.remove('drag-over');
Array.from(e.dataTransfer.files).forEach(addFileChip);
});
let chatCollapsed = false;
toggleChat.addEventListener('click', () => {
@ -1836,11 +2004,44 @@ function smoothReposition() {
}
}
function buildFullMessage(text, files) {
if (!files || files.length === 0) return text;
let parts = [];
files.forEach(file => {
parts.push(`文件名:${file.name}`);
parts.push(`内容:`);
parts.push(file.content);
parts.push('---');
});
parts.push(text);
return parts.join('\n');
}
async function sendChatMessage() {
const files = attachedFiles.slice();
const msg = chatInput.value.trim();
if (!msg) return;
if (!msg && files.length === 0) return;
chatInput.value = '';
addChatMessage('user', msg);
// 读取文件内容
let fullMsg = msg;
if (files.length > 0) {
const fileReads = files.map(file => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => { file.content = reader.result; resolve(); };
reader.onerror = reject;
reader.readAsText(file);
}));
try {
await Promise.all(fileReads);
} catch(e) {
console.error('文件读取失败:', e);
}
fullMsg = buildFullMessage(msg, files);
// 清除文件芯片
attachedFiles = [];
renderFileChips();
}
addChatMessage('user', fullMsg);
chatInput.disabled = true;
chatSendBtn.disabled = true;
chatStatus.textContent = '⏳ 处理中...';
@ -1850,7 +2051,7 @@ function smoothReposition() {
const res = await fetch('/api/message', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({message: msg})
body: JSON.stringify({message: fullMsg})
});
const data = await res.json();
if (data.success) {

File diff suppressed because it is too large Load Diff