feat: AI 聊天面板多模态增强及交互优化
- 支持视频/音频/PDF/文档等多文件类型上传(最大20MB,最多4个) - 视频用 image_url 格式传递(兼容 Gemini OpenAI 兼容层) - 发送前自动生成图片/视频缩略图,聊天记录中显示预览 - 新增消息编辑、重新生成、复制功能 - 支持 reasoning_content 思考过程折叠显示 - 历史对话支持重命名 - 修复 localStorage 存储优化(strip 大文件数据,保留缩略图) - 新增删除历史记录 API 及重启按钮前端组件 Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import { app } from "../../../scripts/app.js";
|
||||
|
||||
app.registerExtension({
|
||||
name: "o1key.restartButton",
|
||||
async setup() {
|
||||
let injected = false;
|
||||
|
||||
function inject() {
|
||||
if (injected) return;
|
||||
if (document.querySelector("#o1k-restart-btn")) { injected = true; return; }
|
||||
|
||||
const allBtns = document.querySelectorAll("button, .p-togglebutton, .side-bar-button");
|
||||
let logBtn = null;
|
||||
for (const btn of allBtns) {
|
||||
const label = (btn.getAttribute("aria-label") || "") + (btn.textContent || "");
|
||||
if (label.includes("日志") || label.includes("Console") || label.includes("控制台") || label.includes("Logs")) {
|
||||
logBtn = btn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!logBtn || !logBtn.parentNode) return;
|
||||
|
||||
const btn = logBtn.cloneNode(false);
|
||||
btn.id = "o1k-restart-btn";
|
||||
btn.setAttribute("aria-label", "重启");
|
||||
btn.title = "重启 ComfyUI";
|
||||
|
||||
const logStyle = window.getComputedStyle(logBtn);
|
||||
btn.style.display = "flex";
|
||||
btn.style.flexDirection = "column";
|
||||
btn.style.alignItems = "center";
|
||||
btn.style.justifyContent = "center";
|
||||
btn.style.gap = logStyle.gap || "4px";
|
||||
|
||||
const iconSpan = document.createElement("span");
|
||||
iconSpan.innerHTML = `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 2v6h-6"/><path d="M3 12a9 9 0 0 1 15-6.7L21 8"/><path d="M3 22v-6h6"/><path d="M21 12a9 9 0 0 1-15 6.7L3 16"/></svg>`;
|
||||
const textSpan = document.createElement("span");
|
||||
textSpan.textContent = "重启";
|
||||
btn.appendChild(iconSpan);
|
||||
btn.appendChild(textSpan);
|
||||
|
||||
btn.addEventListener("click", async () => {
|
||||
if (!confirm("确定要重启 ComfyUI 吗?")) return;
|
||||
btn.style.opacity = "0.5";
|
||||
btn.style.pointerEvents = "none";
|
||||
try { await fetch("/o1key/restart", { method: "POST" }); } catch {}
|
||||
pollUntilReady();
|
||||
});
|
||||
|
||||
logBtn.parentNode.insertBefore(btn, logBtn);
|
||||
injected = true;
|
||||
}
|
||||
|
||||
function pollUntilReady() {
|
||||
let attempts = 0;
|
||||
const maxAttempts = 40;
|
||||
const interval = setInterval(async () => {
|
||||
attempts++;
|
||||
if (attempts > maxAttempts) { clearInterval(interval); location.reload(); return; }
|
||||
try {
|
||||
const r = await fetch("/api/system_stats", { signal: AbortSignal.timeout(2000) });
|
||||
if (r.ok) { clearInterval(interval); location.reload(); }
|
||||
} catch {}
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(inject);
|
||||
observer.observe(document.body, { childList: true, subtree: true });
|
||||
setTimeout(inject, 2000);
|
||||
setTimeout(inject, 4000);
|
||||
setTimeout(inject, 8000);
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user