fix: 文件上传融合到graph.html(星图页面),删除冗余index.html
This commit is contained in:
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
1399
ui/static/index.html
1399
ui/static/index.html
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user