126 lines
5.9 KiB
HTML
126 lines
5.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover">
|
|
<title>萌小芽</title>
|
|
<link rel="icon" href="logo.png" type="image/png" sizes="any">
|
|
<link rel="apple-touch-icon" href="logo.png">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Noto+Sans+SC:wght@400;500;600;700&family=Source+Code+Pro:wght@400;600;700&display=swap" rel="stylesheet">
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css" crossorigin>
|
|
<link rel="stylesheet" href="style.css">
|
|
<script src="marked.umd.js"></script>
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js" crossorigin></script>
|
|
</head>
|
|
<body>
|
|
|
|
<div id="app">
|
|
<!-- 侧边栏 -->
|
|
<aside id="sidebar">
|
|
<div class="sidebar-header">
|
|
<div class="sidebar-brand">
|
|
<img class="sidebar-logo" src="logo.png" width="36" height="36" alt="" decoding="async">
|
|
<h2 class="sidebar-title">萌小芽</h2>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 会话列表 -->
|
|
<div class="sidebar-section">
|
|
<div class="section-header">
|
|
<span>历史会话</span>
|
|
<button class="section-refresh" onclick="loadSessions()" title="刷新">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 4v6h6M23 20v-6h-6"/><path d="M20.49 9A9 9 0 005.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 013.51 15"/></svg>
|
|
</button>
|
|
</div>
|
|
<div id="sessionList" class="session-list">
|
|
<div class="session-empty">加载中...</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="sidebar-actions">
|
|
<button onclick="newSession()">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 5v14M5 12h14"/></svg>
|
|
新会话
|
|
</button>
|
|
<button onclick="location.href='settings.html'">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 00.3 1.9l.1.1a2 2 0 01-2.8 2.8l-.1-.1a1.7 1.7 0 00-1.9-.3 1.7 1.7 0 00-1 1.5V21a2 2 0 01-4 0v-.1a1.7 1.7 0 00-1-1.5 1.7 1.7 0 00-1.9.3l-.1.1A2 2 0 014.2 17l.1-.1A1.7 1.7 0 004.6 15a1.7 1.7 0 00-1.5-1H3a2 2 0 010-4h.1a1.7 1.7 0 001.5-1 1.7 1.7 0 00-.3-1.9L4.2 7A2 2 0 017 4.2l.1.1A1.7 1.7 0 009 4.6a1.7 1.7 0 001-1.5V3a2 2 0 014 0v.1a1.7 1.7 0 001 1.5 1.7 1.7 0 001.9-.3l.1-.1A2 2 0 0119.8 7l-.1.1a1.7 1.7 0 00-.3 1.9 1.7 1.7 0 001.5 1h.1a2 2 0 010 4h-.1a1.7 1.7 0 00-1.5 1z"/></svg>
|
|
设置
|
|
</button>
|
|
</div>
|
|
|
|
<div class="sidebar-status">
|
|
<div class="status-row">
|
|
<span class="status-dot" id="statusDot"></span>
|
|
<span id="statusText">就绪</span>
|
|
</div>
|
|
<div class="status-model" id="statusModel"></div>
|
|
</div>
|
|
</aside>
|
|
|
|
<!-- 主区域 -->
|
|
<main id="main">
|
|
<!-- 顶部栏 -->
|
|
<header id="header">
|
|
<button id="menuBtn" class="menu-btn" onclick="toggleSidebar()" aria-label="切换菜单">
|
|
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 12h18M3 6h18M3 18h18"/></svg>
|
|
</button>
|
|
<div class="header-info">
|
|
<h1 id="headerTitle">聊天</h1>
|
|
<span class="header-meta" id="headerMeta"></span>
|
|
</div>
|
|
<div class="header-trailing">
|
|
<div class="model-controls" id="modelControls">
|
|
<select id="modelSelect" class="model-select" aria-label="选择模型" title="选择模型">
|
|
<option value="">加载模型...</option>
|
|
</select>
|
|
<select id="thinkingSelect" class="thinking-select" aria-label="选择推理强度" title="推理强度">
|
|
<option value="off">off</option>
|
|
<option value="minimal">minimal</option>
|
|
<option value="low">low</option>
|
|
<option value="medium">medium</option>
|
|
<option value="high">high</option>
|
|
<option value="xhigh">xhigh</option>
|
|
</select>
|
|
</div>
|
|
<div id="sessionContextBar" class="session-context-bar session-context-in-header" hidden>
|
|
<div class="session-context-primary-wrap" id="sessionContextPrimary"></div>
|
|
<div id="sessionContextSecondary"></div>
|
|
</div>
|
|
<button class="header-btn" onclick="abortStream()" id="abortBtn" title="中止回复" style="display:none">
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="6" y="6" width="12" height="12" rx="2"/></svg>
|
|
中止
|
|
</button>
|
|
</div>
|
|
</header>
|
|
|
|
<!-- 聊天消息 -->
|
|
<div id="chat">
|
|
<div class="empty-state">
|
|
<div class="empty-icon">
|
|
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z"/></svg>
|
|
</div>
|
|
<p>发送一条消息开始对话</p>
|
|
<p class="empty-hint">按 Enter 发送 · Shift+Enter 换行</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 输入区域 -->
|
|
<div id="inputArea">
|
|
<div class="input-wrapper">
|
|
<textarea id="input" rows="1" placeholder="输入消息..." aria-label="消息输入框" enterkeyhint="send" inputmode="text"></textarea>
|
|
<button id="sendBtn" type="button" onclick="send()" aria-label="发送">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<div id="sidebarOverlay" class="sidebar-overlay" onclick="toggleSidebar()"></div>
|
|
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html>
|