Files
Snap-Solver/templates/index.html
2025-03-29 15:23:05 +08:00

349 lines
18 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="en" data-theme="light">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<title>Snap Solver</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.js"></script>
</head>
<body class="app-container">
<header class="app-header">
<div class="header-content">
<h1>Snap Solver</h1>
<div id="connectionStatus" class="status disconnected">未连接</div>
<div class="header-buttons">
<button id="themeToggle" class="btn-icon" title="切换主题">
<i class="fas fa-moon"></i>
</button>
<button id="settingsToggle" class="btn-icon" title="设置">
<i class="fas fa-cog"></i>
</button>
</div>
</div>
</header>
<!-- 更新通知条 -->
<div id="updateNotice" class="update-notice hidden">
<div class="update-notice-content">
<i class="fas fa-arrow-alt-circle-up"></i>
<span>发现新版本: <span id="updateVersion"></span></span>
<a id="updateLink" href="#" target="_blank" class="update-link">查看更新</a>
<button id="closeUpdateNotice" class="btn-icon">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<main class="app-main">
<div class="content-panel">
<div class="capture-section">
<div class="toolbar">
<div class="toolbar-buttons">
<div class="button-group">
<button id="captureBtn" class="btn-primary" disabled>
<i class="fas fa-camera"></i>
<span>截图</span>
</button>
<button id="cropBtn" class="btn-secondary hidden">
<i class="fas fa-crop"></i>
<span>裁剪</span>
</button>
</div>
</div>
</div>
<div id="emptyState" class="empty-state">
<i class="fas fa-camera-retro"></i>
<h3>准备好开始了吗?</h3>
<p>点击"截图"按钮捕获屏幕然后使用AI分析图像或提取文本。您可以截取数学题、代码或任何需要帮助的内容。</p>
<p class="star-prompt">如果觉得好用,别忘了给项目点个 Star ⭐</p>
</div>
<div id="imagePreview" class="image-preview hidden">
<div class="image-container">
<img id="screenshotImg" src="" alt="截图预览">
</div>
<div class="analysis-button">
<div class="button-group">
<button id="sendToClaude" class="btn-primary hidden">
<i class="fas fa-robot"></i>
<span>发送图片至AI</span>
</button>
<button id="extractText" class="btn-primary hidden">
<i class="fas fa-font"></i>
<span>提取图中文本</span>
</button>
</div>
</div>
<div id="textEditor" class="text-editor hidden">
<textarea id="extractedText" rows="4" placeholder="提取的文本将显示在这里..."></textarea>
<button id="sendExtractedText" class="btn-primary">
<i class="fas fa-paper-plane"></i>
<span>发送文本至AI</span>
</button>
</div>
</div>
</div>
<div id="claudePanel" class="claude-panel hidden">
<div class="panel-header">
<div class="header-title">
<h2>分析结果</h2>
<div class="analysis-status">
<div class="status-light"></div>
</div>
</div>
<button class="btn-icon" id="closeClaudePanel">
<i class="fas fa-times"></i>
</button>
</div>
<div id="thinkingSection" class="thinking-section hidden">
<div class="thinking-header" id="thinkingToggle">
<div class="thinking-title">
<i class="fas fa-brain"></i>
<h3>AI思考过程 <span class="thinking-hint">(点击展开/折叠)</span></h3>
</div>
<button class="toggle-btn">
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div id="thinkingContent" class="thinking-content collapsed"></div>
</div>
<div id="responseContent" class="response-content"></div>
</div>
</div>
<aside id="settingsPanel" class="settings-panel hidden">
<div class="panel-header">
<h2>设置</h2>
<button class="btn-icon" id="closeSettings">
<i class="fas fa-times"></i>
</button>
</div>
<div class="settings-content">
<!-- 1. 首先是最常用的AI模型选择部分 -->
<div class="settings-section">
<h3><i class="fas fa-robot"></i> 模型设置</h3>
<div class="setting-group">
<label for="modelSelect"><i class="fas fa-microchip"></i> 选择模型</label>
<select id="modelSelect" class="select-styled">
<!-- 选项将通过JavaScript动态加载 -->
</select>
<div id="modelVersionInfo" class="model-version-info">
<i class="fas fa-info-circle"></i> 版本: <span id="modelVersionText">-</span>
</div>
</div>
<div class="setting-group">
<label for="maxTokens"><i class="fas fa-text-width"></i> 最大输出Token</label>
<input type="number" id="maxTokens" min="1000" max="128000" step="1000" value="8192" class="input-styled">
</div>
<div class="setting-group reasoning-setting-group">
<label for="reasoningDepth"><i class="fas fa-brain"></i> 推理深度</label>
<select id="reasoningDepth" class="select-styled">
<option value="standard">标准模式 (快速响应)</option>
<option value="extended">深度思考 (更详细分析)</option>
</select>
</div>
<div class="setting-group think-budget-group">
<label for="thinkBudgetPercent"><i class="fas fa-hourglass-half"></i> 思考预算占比</label>
<div class="range-group">
<input type="range" id="thinkBudgetPercent" min="10" max="80" step="5" value="50">
<span id="thinkBudgetPercentValue">50%</span>
</div>
</div>
<div class="setting-group">
<label for="temperature"><i class="fas fa-thermometer-half"></i> 温度</label>
<div class="range-group">
<input type="range" id="temperature" min="0" max="1" step="0.1" value="0.7">
<span id="temperatureValue">0.7</span>
</div>
</div>
<div class="setting-group">
<label for="systemPrompt"><i class="fas fa-comment-alt"></i> 系统提示词</label>
<textarea id="systemPrompt" rows="3">您是一位专业的问题解决专家。请逐步分析问题,找出问题所在,并提供详细的解决方案。始终使用用户偏好的语言回答。</textarea>
</div>
</div>
<!-- 2. 所有API密钥集中在一个区域 -->
<div class="settings-section">
<div class="collapsible-header" id="apiKeysCollapseToggle">
<h3><i class="fas fa-key"></i> API密钥设置</h3>
<button class="toggle-btn">
<i class="fas fa-chevron-down"></i>
</button>
</div>
<div class="collapsible-content collapsed" id="apiKeysContent">
<div class="setting-group api-key-group">
<label for="AnthropicApiKey">Anthropic API Key</label>
<div class="input-group">
<input type="password" id="AnthropicApiKey" placeholder="输入 Anthropic API key">
<button class="btn-icon toggle-api-key">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="setting-group api-key-group">
<label for="OpenaiApiKey">OpenAI API Key</label>
<div class="input-group">
<input type="password" id="OpenaiApiKey" placeholder="输入 OpenAI API key">
<button class="btn-icon toggle-api-key">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="setting-group api-key-group">
<label for="DeepseekApiKey">DeepSeek API Key</label>
<div class="input-group">
<input type="password" id="DeepseekApiKey" placeholder="输入 DeepSeek API key">
<button class="btn-icon toggle-api-key">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="setting-group api-key-group">
<label for="mathpixAppId">Mathpix App ID</label>
<div class="input-group">
<input type="password" id="mathpixAppId" placeholder="输入 Mathpix App ID">
<button class="btn-icon toggle-api-key">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
<div class="setting-group api-key-group">
<label for="mathpixAppKey">Mathpix App Key</label>
<div class="input-group">
<input type="password" id="mathpixAppKey" placeholder="输入 Mathpix App Key">
<button class="btn-icon toggle-api-key">
<i class="fas fa-eye"></i>
</button>
</div>
</div>
</div>
</div>
<!-- 3. 不常用的其他设置放在后面 -->
<div class="settings-section">
<h3><i class="fas fa-cog"></i> 其他设置</h3>
<div class="setting-group">
<label for="language"><i class="fas fa-language"></i> 语言</label>
<input type="text" id="language" value="中文" placeholder="输入首选语言">
</div>
<div class="setting-group">
<label class="checkbox-label">
<input type="checkbox" id="proxyEnabled">
<span>启用 VPN 代理</span>
</label>
</div>
<div id="proxySettings" class="proxy-settings">
<div class="setting-group">
<label for="proxyHost"><i class="fas fa-server"></i> 代理主机</label>
<input type="text" id="proxyHost" value="127.0.0.1" placeholder="输入代理主机">
</div>
<div class="setting-group">
<label for="proxyPort"><i class="fas fa-plug"></i> 代理端口</label>
<input type="number" id="proxyPort" value="4780" placeholder="输入代理端口">
</div>
</div>
</div>
</div>
</aside>
</main>
<div id="cropContainer" class="crop-container hidden">
<div class="crop-wrapper">
<div class="crop-area"></div>
</div>
<div class="crop-actions">
<button id="cropCancel" class="btn-secondary">
<i class="fas fa-times"></i>
<span>取消</span>
</button>
<button id="cropConfirm" class="btn-primary">
<i class="fas fa-check"></i>
<span>确认</span>
</button>
</div>
</div>
<div id="toastContainer" class="toast-container"></div>
<footer class="app-footer">
<div class="footer-content">
<div class="footer-text">
<span>© 2024 Snap-Solver <span class="version-badge">v<span id="currentVersion">{{ update_info.current_version }}</span></span></span>
</div>
<div class="footer-links">
<a href="https://github.com/Zippland/Snap-Solver/" target="_blank" class="footer-link">
<span class="star-icon"></span>
<span>GitHub</span>
</a>
<a href="https://www.xiaohongshu.com/user/profile/623e8b080000000010007721?xsec_token=YBdeHZTp_aVwi1Ijmras5CgQC6pxlpd4RmozT8Hr_-NCA%3D&xsec_source=app_share&xhsshare=CopyLink&appuid=623e8b080000000010007721&apptime=1742201089&share_id=a2704ab48e2c4e1aa321ce63168811b5&share_channel=copy_link" target="_blank" class="footer-link xiaohongshu-link">
<i class="fas fa-book"></i>
<span>小红书</span>
</a>
</div>
</div>
</footer>
<script src="{{ url_for('static', filename='js/ui.js') }}"></script>
<script src="{{ url_for('static', filename='js/settings.js') }}"></script>
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
<!-- 更新检查初始化 -->
<script>
document.addEventListener('DOMContentLoaded', function() {
// 初始化更新检查
const updateInfo = {{ update_info|tojson|safe }};
if (updateInfo && updateInfo.has_update) {
showUpdateNotice(updateInfo);
}
// 24小时后再次检查更新
setTimeout(checkForUpdates, 24 * 60 * 60 * 1000);
});
function showUpdateNotice(updateInfo) {
const updateNotice = document.getElementById('updateNotice');
const updateVersion = document.getElementById('updateVersion');
const updateLink = document.getElementById('updateLink');
if (updateInfo.latest_version) {
updateVersion.textContent = updateInfo.latest_version;
}
if (updateInfo.release_url) {
updateLink.href = updateInfo.release_url;
} else {
updateLink.href = 'https://github.com/Zippland/Snap-Solver/releases/latest';
}
updateNotice.classList.remove('hidden');
// 绑定关闭按钮事件
document.getElementById('closeUpdateNotice').addEventListener('click', function() {
updateNotice.classList.add('hidden');
// 记住用户已关闭此版本的通知
localStorage.setItem('dismissedUpdate', updateInfo.latest_version);
});
}
function checkForUpdates() {
fetch('/api/check-update')
.then(response => response.json())
.then(updateInfo => {
const dismissedVersion = localStorage.getItem('dismissedUpdate');
// 只有当有更新且用户没有关闭过此版本的通知时才显示
if (updateInfo.has_update && dismissedVersion !== updateInfo.latest_version) {
showUpdateNotice(updateInfo);
}
})
.catch(error => console.error('检查更新失败:', error));
}
</script>
</body>
</html>