Files
Haocode/ui/web/index.html
T
sorrow404null ef00f64435 feat(web): incremental render-window batch rendering engine
Add render_window.js: Python-driven incremental pagination with id+chainIndex state, anchor restore, batch guard and streaming auto-detect; wired through chat_bridge and the page shell.
2026-09-17 16:40:04 +08:00

86 lines
3.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- Markdown 库 -->
<script src="marked.min.js"></script>
<!-- 代码高亮 -->
<link rel="stylesheet" href="highlight/atom-one-dark.min.css">
<script src="highlight/highlight.min.js"></script>
<!-- 🌟 HTML 消毒(防 XSS / 防 HTML 穿透的纵深防御) -->
<script src="dompurify.min.js"></script>
<!-- 🌟 KaTeX 公式渲染(本地离线资产;须在 app.js 之前) -->
<link rel="stylesheet" href="katex/katex.min.css">
<script src="katex/katex.min.js"></script>
<!-- 自定义样式 -->
<link rel="stylesheet" href="style.css">
<!-- 🌟 Qt WebChannel 支持(用于前端与 Python 通信) -->
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
</head>
<body>
<!--🌟 会话加载界面(进入新会话时的统一加载:居中图标 + 从左到右扫描条) -->
<div class="session-loading" id="session-loading" style="display:none;">
<div class="session-loading-box">
<img class="session-loading-icon" src="../../svg/main.svg" alt="haocode">
<div class="session-loading-bar">
<div class="session-loading-bar-fill"></div>
</div>
</div>
</div>
<!--🌟 欢迎界面 -->
<div class="welcome-screen">
<div class="welcome-content">
<img class="welcome-icon" src="../../svg/main.svg" alt="haocode">
<h1 class="brand-name">haocode</h1>
<p class="brand-tagline">探索未至之境</p>
</div>
</div>
<!-- 聊天容器(🆕 P1-01:顶部/底部加载入口由 app.js 按需插入 chat-container 首/尾) -->
<div id="chat-container"></div>
<div id="scroll-anchor" style="height: 1px; margin-bottom: 150px;"></div>
<!-- 🌟 桥接初始化脚本(必须在 app.js 之前执行)
双协议:WebView2window.chrome.webview.postMessage/ QtWebEngineQWebChannel -->
<script>
document.addEventListener("DOMContentLoaded", function () {
if (window.chrome && window.chrome.webview) {
// ---- WebView2 路径:JSON 消息协议,方法名与 QWebChannel slot 一一对应 ----
const post = (m, a) => {
try { window.chrome.webview.postMessage({ m: m, a: a }); } catch (e) { console.warn("[JS] postMessage 失败:", e); }
};
window.bridge = {
onRegenerateClicked: (x) => post("onRegenerateClicked", [x]),
onBranchSwitch: (x, d) => post("onBranchSwitch", [x, d]),
onDeleteMessageClicked: (x) => post("onDeleteMessageClicked", [x]),
onAttachmentClicked: (x) => post("onAttachmentClicked", [x]),
onScrollChanged: (y, h, c) => post("onScrollChanged", [y, h, c]),
onRequestWindowPage: (s, d, b, g) => post("onRequestWindowPage", [s, d, b, g])
};
console.log("[JS] WebView2 桥接就绪,window.bridge 可用");
} else {
// ---- QtWebEngine 路径:原有 QWebChannel ----
new QWebChannel(qt.webChannelTransport, function (channel) {
window.bridge = channel.objects.bridge;
console.log("[JS] QWebChannel 已连接,window.bridge 就绪");
});
}
});
</script>
<!-- 🌟 主逻辑脚本 -->
<!-- 🆕 P1-01 渲染窗口状态机(DOM 无关;须在 app.js 之前) -->
<script src="render_window.js"></script>
<script src="app.js"></script>
</body>
</html>