From 0b67bbe885ce8f6c1af774789a3de2f3063b90ae Mon Sep 17 00:00:00 2001 From: hubian <908234780@qq.com> Date: Wed, 29 Apr 2026 22:59:39 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E6=94=B9=E8=BF=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 文件上传后显示标记(文件名标签),不填充输入框 - 用户正常输入问题,发送时文件内容自动附加 - 文件内容作为系统消息提交给AI - 界面显示'已上传文件'标记,可点击移除 - 发送后自动清除文件标记 --- www/app.js | 94 +++++++++++++++++++++++++++++++++++++++++---------- www/style.css | 44 ++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 17 deletions(-) diff --git a/www/app.js b/www/app.js index 8f9a6ea..e612281 100644 --- a/www/app.js +++ b/www/app.js @@ -25,6 +25,9 @@ let systemAgents = []; // 用户智能体界面显示的智能体 let agents = []; +// 上传的文件(临时存储) +let uploadedFile = null; // { name: string, content: string } + // 用户添加的智能体(按类别分组) let myAgents = { basic: [], @@ -3997,8 +4000,26 @@ async function sendMessage() { // 隐藏欢迎界面 welcome.style.display = 'none'; - // 添加用户消息 - currentConversation.messages.push({ role: 'user', content: text }); + // 构建用户消息内容 + let userContent = text; + let fileContent = null; + + // 如果有上传的文件,附加文件内容 + if (uploadedFile) { + fileContent = uploadedFile; + userContent = text; // 用户输入的问题 + + // 发送后清除上传文件标记 + uploadedFile = null; + const fileTagArea = document.getElementById('fileTagArea'); + if (fileTagArea) fileTagArea.innerHTML = ''; + } + + // 添加用户消息(界面显示) + const displayContent = fileContent + ? `${text}\n\n📎 已上传文件: ${fileContent.name}` + : text; + currentConversation.messages.push({ role: 'user', content: displayContent }); // 更新对话标题(第一条用户消息) if (currentConversation.title === '新对话') { @@ -4033,11 +4054,11 @@ async function sendMessage() { autoResize(userInput); // 调用流式生成 - await streamGenerate(currentConversation.messages.length - 1); + await streamGenerate(currentConversation.messages.length - 1, fileContent); } // 流式生成 AI 回复 -async function streamGenerate(userMsgIndex) { +async function streamGenerate(userMsgIndex, fileContent = null) { isLoading = true; sendBtn.disabled = true; @@ -4082,6 +4103,14 @@ async function streamGenerate(userMsgIndex) { content: m.content })); + // 如果有上传的文件,添加文件内容作为系统消息 + if (fileContent) { + messagesToSend.push({ + role: 'system', + content: `用户上传了文件 "${fileContent.name}",以下是文件内容:\n\n${fileContent.content}` + }); + } + // 如果有搜索结果,将搜索内容添加到消息中 if (searchResults) { const searchContext = formatSearchResultsForLLM(searchResults); @@ -5327,24 +5356,19 @@ async function handleFileUpload(e) { // 限制最多 10000 字符 if (content.length > 10000) { content = content.slice(0, 10000); - showToast(`文件内容已截取前 10000 字符`); } - // 把文件内容附加到输入框,让用户可以添加额外说明 - const currentText = userInput.value.trim(); - const filePrefix = `【文件:${file.name}】\n内容如下:\n`; + // 存储上传的文件 + uploadedFile = { + name: file.name, + content: content + }; - if (currentText) { - userInput.value = `${currentText}\n\n${filePrefix}${content}`; - } else { - userInput.value = `${filePrefix}${content}`; - } + // 显示文件标记 + showUploadedFileTag(); - // 自动调整输入框高度 - autoResize(userInput); + showToast(`已上传: ${file.name}`); userInput.focus(); - - showToast('文件内容已添加到输入框'); }; reader.onerror = () => { @@ -5355,6 +5379,42 @@ async function handleFileUpload(e) { e.target.value = ''; } +// 显示上传文件标记 +function showUploadedFileTag() { + if (!uploadedFile) return; + + // 查找或创建文件标记区域 + let fileTagArea = document.getElementById('fileTagArea'); + if (!fileTagArea) { + fileTagArea = document.createElement('div'); + fileTagArea.id = 'fileTagArea'; + fileTagArea.className = 'file-tag-area'; + // 插入到输入区域前面 + const inputArea = document.querySelector('.input-area'); + if (inputArea) { + inputArea.insertBefore(fileTagArea, inputArea.firstChild); + } + } + + fileTagArea.innerHTML = ` +
+ 📄 + ${uploadedFile.name} + +
+ `; +} + +// 移除上传的文件 +function removeUploadedFile() { + uploadedFile = null; + const fileTagArea = document.getElementById('fileTagArea'); + if (fileTagArea) { + fileTagArea.innerHTML = ''; + } + showToast('已移除文件'); +} + // 带图片的流式生成 async function streamGenerateWithImage(base64, imageName) { isLoading = true; diff --git a/www/style.css b/www/style.css index 8292495..cc25775 100644 --- a/www/style.css +++ b/www/style.css @@ -3198,6 +3198,50 @@ body { color: var(--text-color); } +/* 文件标记区域 */ +.file-tag-area { + padding: 8px 12px; + background: rgba(102, 126, 234, 0.05); + border-radius: 8px; + margin-bottom: 8px; +} + +.file-tag { + display: inline-flex; + align-items: center; + gap: 6px; + padding: 6px 12px; + background: var(--primary); + color: white; + border-radius: 20px; + font-size: 13px; +} + +.file-tag-icon { + font-size: 16px; +} + +.file-tag-name { + max-width: 150px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.file-tag-remove { + background: none; + border: none; + color: white; + font-size: 14px; + cursor: pointer; + padding: 0 4px; + opacity: 0.8; +} + +.file-tag-remove:hover { + opacity: 1; +} + #userInput { flex: 1; padding: 12px 16px;