From 89d802cf076c06f07667c01413b792ced8922c9f Mon Sep 17 00:00:00 2001
From: geyun <1556375442@qq.com>
Date: Sun, 25 Jan 2026 21:19:50 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=B1=E5=BA=A6=E6=80=9D=E8=80=83finish?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
index.html | 179 +++++++++++++++++++++++++++++++++++++++++++++--------
server2.js | 26 ++++++--
2 files changed, 174 insertions(+), 31 deletions(-)
diff --git a/index.html b/index.html
index b07c5d0..469153b 100755
--- a/index.html
+++ b/index.html
@@ -1046,6 +1046,11 @@
align-items: center;
height: 100vh;
}
+ .no-after::after {
+ content: none !important;
+ display: none !important;
+}
+
.popbgc {
background-color: rgba(0, 0, 0, 0.4);
@@ -1189,7 +1194,7 @@
.thinking-loading::after {
content: '';
- animation: dots 1.5s infinite;
+ animation: dots 0.8s infinite;
}
@keyframes dots {
@@ -1701,14 +1706,14 @@
document.querySelectorAll('.logout1').forEach(el => {
el.style.display = 'none';
});
- console.log(3)
+
document.querySelectorAll('.username').forEach((e) => {
e.textContent = params.get("nickname") || getcookie("nickname");
})
document.querySelector(".userinfo-wrapper img").src = getcookie("headimgurl") || params.get("headingimg");
userId = decodeURIComponent(Number(escape(atob(encodedUserId))));
- console.log(4)
+
} else {
userId = decodeURIComponent(Number(escape(atob(encodedUserId))));
@@ -1929,7 +1934,7 @@
}
isPre = true;//s是否预设题目
- console.log(isUpload, 88)
+
if (!sendParam.imageBase64 && !fileInput.files.length) {
// if (!isUpload[activeChatId]) {
if (!hasImage) {
@@ -2081,7 +2086,7 @@
}
document.addEventListener('click', (e) => {
- console.log(toggleButton.contains(e.target), panel.contains(e.target))
+
if (!toggleButton.contains(e.target) && !panel.contains(e.target)) {
panel.classList.remove('show');
}
@@ -2119,7 +2124,7 @@
sendParam.sessionId = activeChatId;
getHistory();
sessIdList.forEach((item, index) => {
- console.log(item, activeChatId);
+
const item1 = document.createElement("div");
item1.setAttribute("data-sessionid", item.sessId);
@@ -2160,7 +2165,8 @@
if (msg.image_base64) {
hasImage = true; // 只要有一个不为空,就置为 true
}
- addMessage(msg.content, msg.role, msg.image_base64,msg.thinking);
+
+ addMessage(msg.content, msg.role, msg.image_base64,'',msg.thinking);
});
scrollToBottom();
}
@@ -2185,7 +2191,8 @@
}
}
// 内容 角色 图片 创造时间
- function addMessage(content = '', role = "assistant", imgUrl = null, time = null,thinking='') {
+ function addMessage(content = '', role = "assistant", imgUrl = null, time = null,thinking) {
+
const msg = document.createElement("div");
msg.className = `message ${role}`;
@@ -2205,8 +2212,8 @@
// 思考过程(历史:已完成)
// =========================
let thinkingContentDiv = null;
-
- if (role === "assistant" && thinking) {
+ if (thinking) {
+
const thinkingBox = document.createElement("div");
thinkingBox.className = "thinking-box";
@@ -2232,7 +2239,7 @@
header.onclick = () => {
thinkingContentDiv.classList.toggle("collapsed");
toggle.textContent =
- thinkingContentDiv.classList.contains("collapsed") ? "▶" : "⌄";
+ thinkingContentDiv.classList.contains("collapsed") ? "▶" : "";
};
header.appendChild(title);
@@ -2276,7 +2283,9 @@
shareSpan.style.opacity = "0.75";
shareSpan.title = "分享";
- shareSpan.innerHTML = ``;
+ shareSpan.innerHTML = `
+
+ `;
shareSpan.onclick = () => {
generatePoster(content, imgUrl);
};
@@ -2289,7 +2298,9 @@
copySpan.style.opacity = "0.75";
copySpan.title = "复制内容";
- copySpan.innerHTML = ``;
+ copySpan.innerHTML = `
+
+ `;
copySpan.onclick = async () => {
await navigator.clipboard.writeText(content);
showToast("复制成功");
@@ -2372,7 +2383,7 @@
function sendMessage(isPre) {
- console.log("发送消息1122");
+
if (controller) {
showToast("请先停止对话");
return;
@@ -2504,7 +2515,7 @@ const getAiResponse = async (img) => {
thinkingToggleSpan = document.createElement("span");
thinkingToggleSpan.className = "thinking-toggle";
- thinkingToggleSpan.textContent = "⌄";
+ thinkingToggleSpan.textContent = "";
thinkingContentDiv = document.createElement("div");
thinkingContentDiv.className = "thinking-content";
@@ -2582,11 +2593,111 @@ const getAiResponse = async (img) => {
if (!line.startsWith("data:")) continue;
const data = line.slice(5).trim();
- if (data === "[DONE]") {
- scrollToBottom();
- controller = null;
- return;
- }
+ if (data == "[DONE]") {
+ console.log("完成回答");
+ controller = null;
+ // 更新聊天滚动条
+
+ sendBtnImg.classList.remove('none');
+ stopBtn.forEach(e => {
+ e.classList.add('none')
+
+ })
+ // renderChatList();
+ // msgDiv.innerHTML = marked.parse(aiMsg.content);
+ // const shareSpan = document.createElement("span");
+ // shareSpan.style.display = "inline-flex";
+ // shareSpan.style.alignItems = "center";
+ // shareSpan.style.cursor = "pointer";
+ // shareSpan.style.marginTop = "8px";
+ // shareSpan.style.opacity = "0.75";
+ // shareSpan.style.transition = "opacity .2s";
+ // shareSpan.title = "分享";
+
+ // shareSpan.onmouseenter = () => shareSpan.style.opacity = "1";
+ // shareSpan.onmouseleave = () => shareSpan.style.opacity = "0.75";
+
+ // shareSpan.innerHTML = `
+ //
+ // `;
+
+ // shareSpan.onclick = () => {
+ // generatePoster(aiMsg.content);
+ // };
+
+ // if (role === "assistant") {
+ // 分享按钮
+ const shareSpan = document.createElement("span");
+ shareSpan.style.display = "inline-flex";
+ shareSpan.style.alignItems = "center";
+ shareSpan.style.cursor = "pointer";
+ shareSpan.style.marginTop = "8px";
+ shareSpan.style.opacity = "0.75";
+ shareSpan.style.transition = "opacity .2s";
+ shareSpan.title = "分享";
+
+ shareSpan.onmouseenter = () => shareSpan.style.opacity = "1";
+ shareSpan.onmouseleave = () => shareSpan.style.opacity = "0.75";
+
+ shareSpan.innerHTML = `
+
+ `;
+
+
+ shareSpan.onclick = () => {
+ generatePoster(answerContentDiv.innerHTML, img);
+ };
+
+ // msg.appendChild(shareSpan);
+
+ // ======================
+ // ✅ 复制按钮(新增)
+ // ======================
+ const copySpan = document.createElement("span");
+ copySpan.style.display = "inline-flex";
+ copySpan.style.alignItems = "center";
+ copySpan.style.cursor = "pointer";
+ copySpan.style.marginTop = "8px";
+ copySpan.style.marginLeft = "10px";
+ copySpan.style.opacity = "0.75";
+ copySpan.style.transition = "opacity .2s";
+ copySpan.title = "复制内容";
+
+ copySpan.onmouseenter = () => copySpan.style.opacity = "1";
+ copySpan.onmouseleave = () => copySpan.style.opacity = "0.75";
+
+ copySpan.innerHTML = `
+
+ `;
+
+ copySpan.onclick = async () => {
+ try {
+ await navigator.clipboard.writeText(answerBuffer);
+ copySpan.style.opacity = "1";
+ showToast("复制成功")
+ copySpan.title = "复制成功";
+ setTimeout(() => { copySpan.title = "复制内容"; }, 1200);
+ } catch (err) {
+ alert("复制失败,可能不支持 HTTPS 环境以外复制。");
+ }
+ };
+
+ // }
+
+ setTimeout(() => {
+ msgDiv.appendChild(shareSpan);
+ msgDiv.appendChild(copySpan);
+ }, 1000)
+
+
+ console.log("shareSpan appended?", msgDiv.contains(shareSpan));
+
+
+ scrollToBottom();
+
+
+ return;
+ }
let obj;
try {
@@ -2886,12 +2997,12 @@ const getAiResponse = async (img) => {
function uploadFile(file) {
if (file) {
- console.log("上传文件:", file.name, URL.createObjectURL(file));
+
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = async function () {
- console.log(reader.result)
+
sendParam.imageBase64 = reader.result;
document.querySelectorAll(".img-row").forEach(e => {
e.classList.remove("none");
@@ -3073,7 +3184,7 @@ const getAiResponse = async (img) => {
// }
function getSessionList() {
- console.log(userId, "huoqu");
+
sendParam.userId = userId;
fetch(`https://serviceai.satabot.com/sessions?userId=${sendParam.userId}`, {
@@ -3128,8 +3239,10 @@ const getAiResponse = async (img) => {
}
}
document.getElementById("stopBtn").addEventListener("click", () => {
-
+ document.querySelectorAll('.thinking-loading').forEach(el=>el.classList.add('no-after'));
console.log(controller, '暂停消息');
+ debugger;
+
isStopped = true;
if (reader) {
@@ -3141,6 +3254,7 @@ const getAiResponse = async (img) => {
controller.abort();
controller = null;
}
+
if (sendBtnImg.classList.contains('none')) {
sendBtnImg.classList.remove('none');
@@ -3149,8 +3263,17 @@ const getAiResponse = async (img) => {
})
}
+
+ fetch("https://serviceai.satabot.com/stop", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(sendParam),
+
+ });
+
});
document.getElementById("stopBtn1").addEventListener("click", () => {
+ document.querySelectorAll('.thinking-loading').forEach(el=>el.classList.add('no-after'));
console.log(controller, '暂停消息');
isStopped = true;
@@ -3172,6 +3295,12 @@ const getAiResponse = async (img) => {
})
}
+ fetch("https://serviceai.satabot.com/stop", {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(sendParam),
+
+ });
});
// DOM 加载完成后执行
console.log('DOM Ready');
@@ -3238,7 +3367,7 @@ const getAiResponse = async (img) => {
showToast("请选择场景");
return;
}
- console.log(data, "收集信息")
+
// 发送POST请求到后端
const res = await fetch('https://serviceai.satabot.com/submit', {
diff --git a/server2.js b/server2.js
index 8ab7e88..395a482 100755
--- a/server2.js
+++ b/server2.js
@@ -892,7 +892,7 @@ app.get("/history", async (req, res) => {
// 查询数据库
const [rows] = await pool.query(
- "SELECT user_id, role, content, image_base64, created_at,title FROM ai_chat_messages WHERE session_id = ? ORDER BY id ASC",
+ "SELECT user_id, role, content, image_base64, created_at,title,thinking FROM ai_chat_messages WHERE session_id = ? ORDER BY id ASC",
[sessionId]
);
@@ -1391,6 +1391,8 @@ app.post("/analyze", upload.single("file"), async (req, res) => {
return res.status(400).json({ error: "对话次数已用完,请完成账号注册" });
}
}
+
+ console.log("====== 开始图像分析11... ======");
const { requestId } = req.body;
@@ -1401,6 +1403,7 @@ app.post("/analyze", upload.single("file"), async (req, res) => {
"X-Accel-Buffering": "no",
});
res.flushHeaders?.();
+ res.socket.setNoDelay(true); // 禁用缓冲,实时推送
let aborted = false;
req.on("close", () => {
console.log("🔴 前端断开连接,停止整个分析流程");
@@ -1442,6 +1445,8 @@ app.post("/analyze", upload.single("file"), async (req, res) => {
"SELECT role, content, image_base64 FROM ai_chat_messages WHERE session_id = ? AND user_id = ? ORDER BY created_at ASC",
[sessId, userId || null]
);
+
+ console.log("====== 开始图像分析22... ======");
// 构建历史消息数组
const historyMessages = historyRows.slice(-MAX_HISTORY).map(row => {
@@ -1469,6 +1474,8 @@ app.post("/analyze", upload.single("file"), async (req, res) => {
return message;
});
+
+ console.log("====== 开始图像分析33... ======");
// ------------------ 保存用户提问 ------------------
await pool.query(
@@ -1478,6 +1485,8 @@ app.post("/analyze", upload.single("file"), async (req, res) => {
// ------------------ 图像分析 ------------------
let sceneText = "";
+
+ console.log("====== 开始图像分析55... ======");
// If an image is uploaded, start with image analysis
if (imageBase64) {
@@ -1530,9 +1539,11 @@ app.post("/analyze", upload.single("file"), async (req, res) => {
].filter(Boolean),
},
];
+
+ console.log("====== 开始图像分析666... ======");
const completion = await client.chat.completions.create({
- model: "gpt-4.1-mini",
+ model: "gpt-4.1",
stream: true,
messages: imageAnalysisMessages
});
@@ -1687,10 +1698,12 @@ app.post("/analyze", upload.single("file"), async (req, res) => {
console.log("====== 最终分析结束 ======");
// ------------------ Save Results to Database ------------------
+
+ sceneText += thinkingText;
if (existingTitle) {
await pool.query(
- "INSERT INTO ai_chat_messages (session_id, user_id, role, content) VALUES (?, ?, 'assistant', ?)",
- [sessId, userId || null, llmText]
+ "INSERT INTO ai_chat_messages (session_id, user_id, role, content,thinking) VALUES (?, ?, 'assistant', ?,?)",
+ [sessId, userId || null, llmText,sceneText]
);
} else {
try {
@@ -1709,9 +1722,10 @@ app.post("/analyze", upload.single("file"), async (req, res) => {
);
console.log("生成的标题:", title);
+
await pool.query(
- "INSERT INTO ai_chat_messages (session_id, user_id, role, content, title) VALUES (?, ?, 'assistant', ?, ?)",
- [sessId, userId || null, llmText, title]
+ "INSERT INTO ai_chat_messages (session_id, user_id, role, content, title,thinking) VALUES (?, ?, 'assistant', ?, ?,?)",
+ [sessId, userId || null, llmText, title,sceneText]
);
} catch (err) {
console.error("生成标题失败:", err.message);