Snap-Solver / templates /index.html
renxsh
init
f1b4581
<!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">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Safari兼容性设置 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
<meta name="mobile-web-app-capable" content="yes">
<title>Snap Solver</title>
<link rel="icon" href="/static/favicon.ico">
<link rel="stylesheet" href="/static/style.css">
<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">
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
<script>
// 帮助Safari调试
window.onerror = function(message, source, lineno, colno, error) {
console.error("Error caught: ", message, "at", source, ":", lineno, ":", colno, error);
return false;
};
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cropperjs/1.5.13/cropper.min.js"></script>
<!-- 添加Markdown解析库 -->
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<!-- 添加代码高亮库 -->
<link rel="stylesheet" href="https://unpkg.com/@highlightjs/cdn-assets@11.8.0/styles/github.min.css">
<script src="https://unpkg.com/@highlightjs/cdn-assets@11.8.0/highlight.min.js"></script>
</head>
<body class="app-container">
<header class="app-header">
<div class="header-content">
<h1>Snap Solver <span class="version-badge">v<span id="currentVersion">{{ update_info.current_version }}</span></span></h1>
<div class="header-middle">
<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 id="connectionStatus" class="status disconnected">未连接</div>
</div>
<div class="header-buttons">
<button id="captureBtn" class="btn-icon capture-btn-highlight" title="截图" disabled>
<i class="fas fa-camera"></i>
<span>开始截图</span>
</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 id="claudePanel" class="claude-panel hidden">
<div class="panel-header">
<div class="header-title">
<h2><i class="fas fa-chart-bar"></i> 分析结果</h2>
<div class="analysis-indicator">
<div class="progress-line"></div>
<div class="status-text">准备中</div>
</div>
<button id="stopGenerationBtn" class="btn-stop-generation" title="停止生成">
<i class="fas fa-stop"></i>
</button>
</div>
<button class="btn-icon" id="closeClaudePanel" title="关闭分析结果">
<i class="fas fa-times"></i>
</button>
</div>
<div id="thinkingSection" class="thinking-section hidden">
<div class="thinking-header" id="thinkingToggle" title="点击查看AI思考过程">
<div class="thinking-title">
<i class="fas fa-brain"></i>
<h3>思考过程<span class="dots-animation"></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 id="claudePanel" class="claude-panel hidden">
<div class="panel-header">
<div class="header-title">
<h2><i class="fas fa-chart-bar"></i> 分析结果</h2>
<div class="analysis-indicator">
<div class="progress-line"></div>
<div class="status-text">准备中</div>
</div>
<button id="stopGenerationBtn" class="btn-stop-generation" title="停止生成">
<i class="fas fa-stop"></i>
</button>
</div>
<button class="btn-icon" id="closeClaudePanel" title="关闭分析结果">
<i class="fas fa-times"></i>
</button>
</div>
<div id="thinkingSection" class="thinking-section hidden">
<div class="thinking-header" id="thinkingToggle" title="点击查看AI思考过程">
<div class="thinking-title">
<i class="fas fa-brain"></i>
<h3>思考过程<span class="dots-animation"></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 class="capture-section">
<div id="emptyState" class="empty-state">
<i class="fas fa-camera-retro"></i>
<h3>准备好开始了吗?</h3>
<p>点击顶部状态栏的"相机"图标捕获屏幕,然后使用AI分析图像或提取文本。您可以截取数学题、代码或任何需要帮助的内容。</p>
<p class="star-prompt">如果觉得好用,别忘了给Github点个 Star ⭐</p>
<div class="empty-state-social">
<a href="https://github.com/Zippland/Snap-Solver/" target="_blank" class="social-link github-link">
<span>GitHub</span>
</a>
<a href="https://www.xiaohongshu.com/user/profile/623e8b080000000010007721" target="_blank" class="social-link xiaohongshu-link">
<span>小红书</span>
</a>
</div>
</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-action hidden">
<i class="fas fa-robot"></i>
<span>发送至AI</span>
</button>
<button id="extractText" class="btn-action hidden">
<i class="fas fa-font"></i>
<span>提取文本</span>
</button>
</div>
</div>
<textarea id="extractedText" class="extracted-text-area hidden" rows="6" placeholder="提取的文本将显示在这里..."></textarea>
<button id="sendExtractedText" class="btn-action send-text-btn hidden">
<i class="fas fa-paper-plane"></i>
<span>发送文本至AI</span>
</button>
</div>
</div>
<div class="clipboard-panel">
<div class="clipboard-header">
<h3><i class="fas fa-clipboard"></i> 剪贴板操作</h3>
<p class="clipboard-hint">读取宿主机剪贴板内容或发送内容到服务端剪贴板</p>
</div>
<textarea id="clipboardText" rows="4" placeholder="剪贴板内容将显示在这里,也可以手动输入内容"></textarea>
<div class="clipboard-actions">
<button id="clipboardRead" class="btn-action clipboard-read-btn" type="button">
<i class="fas fa-download"></i>
<span>读取剪贴板</span>
</button>
<button id="clipboardSend" class="btn-action clipboard-send-btn" type="button">
<i class="fas fa-clipboard-check"></i>
<span>发送至剪贴板</span>
</button>
<span id="clipboardStatus" class="clipboard-status" aria-live="polite"></span>
</div>
</div>
</div>
<aside id="settingsPanel" class="settings-panel">
<div class="settings-header">
<h2><i class="fas fa-cog"></i> 设置</h2>
<button id="closeSettings" class="btn-icon">
<i class="fas fa-times"></i>
</button>
</div>
<div class="settings-content">
<!-- 1. 首先是最常用的AI模型选择部分 -->
<div class="settings-section model-settings">
<h3><i class="fas fa-robot"></i> 模型设置</h3>
<div class="setting-group">
<div class="model-control">
<label for="modelSelect"><i class="fas fa-microchip"></i> AI模型</label>
<!-- 简化模型选择器结构 -->
<div class="model-selector" id="modelSelector">
<div class="model-display">
<div class="model-display-icon">
<i class="fas fa-robot"></i>
</div>
<div class="model-display-info">
<div class="model-display-name" id="currentModelName">选择模型</div>
<div class="model-display-provider" id="currentModelProvider"></div>
</div>
<div class="model-display-badges" id="modelBadges">
<!-- 能力图标由JS生成 -->
</div>
<i class="fas fa-chevron-down model-selector-arrow"></i>
</div>
</div>
<!-- 保留原始下拉框用于保持兼容性 -->
<select id="modelSelect" class="hidden">
<!-- 选项通过JS添加 -->
</select>
<div id="modelVersionInfo" class="model-version-info">
<i class="fas fa-info-circle"></i> <span id="modelVersionText">-</span>
</div>
</div>
</div>
<div class="setting-group">
<div class="token-control">
<div class="token-label">
<label for="maxTokens"><i class="fas fa-text-width"></i> 最大输出Token</label>
</div>
<div class="token-slider-container">
<input type="range" id="maxTokens" class="token-slider" min="1000" max="128000" step="1000" value="8192">
<span class="token-value" id="maxTokensValue">8192</span>
</div>
<div class="token-markers">
<span>1K</span>
<span>32K</span>
<span>64K</span>
<span>96K</span>
<span>128K</span>
</div>
<div class="token-presets">
<button class="token-preset" data-value="4000">简短</button>
<button class="token-preset" data-value="16000">标准</button>
<button class="token-preset" data-value="64000">详细</button>
<button class="token-preset" data-value="128000">最大</button>
</div>
</div>
</div>
<div class="setting-group reasoning-setting-group">
<div class="reasoning-control">
<div class="reasoning-label">
<label for="reasoningDepth"><i class="fas fa-brain"></i> 推理深度</label>
</div>
<div class="reasoning-selector">
<div class="reasoning-option" data-value="standard">
<i class="fas fa-bolt"></i>
<span class="option-name">标准模式</span>
<span class="option-desc">快速响应,即时生成</span>
</div>
<div class="reasoning-option" data-value="extended">
<i class="fas fa-lightbulb"></i>
<span class="option-name">深度思考</span>
<span class="option-desc">更详细的分析与推理</span>
</div>
</div>
<select id="reasoningDepth" class="hidden">
<option value="standard">标准模式 (快速响应)</option>
<option value="extended">深度思考 (更详细分析)</option>
</select>
</div>
</div>
<div class="setting-group doubao-thinking-group" style="display: none;">
<div class="doubao-thinking-control">
<div class="doubao-thinking-label">
<label for="doubaoThinkingMode"><i class="fas fa-cogs"></i> 豆包深度思考模式</label>
</div>
<div class="doubao-thinking-selector">
<div class="doubao-thinking-option active" data-value="auto">
<i class="fas fa-magic"></i>
<span class="option-name">自动模式</span>
<span class="option-desc">由AI自动决定是否使用深度思考</span>
</div>
<div class="doubao-thinking-option" data-value="enabled">
<i class="fas fa-brain"></i>
<span class="option-name">开启思考</span>
<span class="option-desc">强制启用深度思考过程</span>
</div>
<div class="doubao-thinking-option" data-value="disabled">
<i class="fas fa-bolt"></i>
<span class="option-name">关闭思考</span>
<span class="option-desc">禁用深度思考,快速响应</span>
</div>
</div>
<select id="doubaoThinkingMode" class="hidden">
<option value="auto">自动模式</option>
<option value="enabled">开启思考</option>
<option value="disabled">关闭思考</option>
</select>
<div class="doubao-thinking-desc">
<div class="doubao-desc-item">
<i class="fas fa-info-circle"></i>
<span><strong>自动模式:</strong>AI根据问题复杂度自动决定</span>
</div>
<div class="doubao-desc-item">
<i class="fas fa-lightbulb"></i>
<span><strong>开启思考:</strong>显示完整的思考推理过程</span>
</div>
<div class="doubao-desc-item">
<i class="fas fa-rocket"></i>
<span><strong>关闭思考:</strong>直接给出答案,响应更快</span>
</div>
</div>
</div>
</div>
<div class="setting-group think-budget-group">
<div class="think-budget-control">
<div class="think-budget-label">
<label for="thinkBudgetPercent"><i class="fas fa-hourglass-half"></i> 思考预算占比</label>
</div>
<div class="think-slider-container">
<input type="range" id="thinkBudgetPercent" class="think-slider" min="10" max="80" step="5" value="50">
<span class="think-value-badge" id="thinkBudgetPercentValue">50%</span>
</div>
<div class="think-budget-markers">
<span>10%</span>
<span>30%</span>
<span>50%</span>
<span>70%</span>
<span>80%</span>
</div>
<div class="think-budget-presets">
<button class="think-preset" data-value="20">少量</button>
<button class="think-preset" data-value="50">平衡</button>
<button class="think-preset" data-value="70">深入</button>
</div>
<div class="think-budget-desc">
<div class="think-desc-item">
<i class="fas fa-tachometer-alt"></i>
<span>低占比 = 更快响应速度</span>
</div>
<div class="think-desc-item">
<i class="fas fa-search-plus"></i>
<span>高占比 = 更深入的分析</span>
</div>
</div>
</div>
</div>
<!-- 已删除重复的豆包思考模式UI元素 -->
<div class="setting-group">
<div class="temperature-control">
<div class="temperature-label">
<label for="temperature"><i class="fas fa-thermometer-half"></i> 温度</label>
</div>
<input type="range" id="temperature" class="temperature-slider" min="0" max="1" step="0.1" value="0.7">
<div class="temperature-markers">
<span>0</span>
<span>0.2</span>
<span>0.4</span>
<span>0.6</span>
<span>0.8</span>
<span>1</span>
</div>
<div class="temperature-description">
<span class="temperature-low">精确</span>
<span class="temperature-high">创意</span>
</div>
</div>
</div>
</div>
<!-- 系统提示词部分 - 简化设计 -->
<div class="settings-section prompt-settings">
<h3><i class="fas fa-comment-alt"></i> 系统提示词</h3>
<div class="setting-group prompt-setting-group">
<div class="prompt-container">
<div class="prompt-actions">
<select id="promptSelect" title="选择预设提示词">
</select>
<div class="prompt-buttons">
<button id="savePromptBtn" class="icon-btn" title="编辑当前提示词">
<i class="fas fa-edit"></i>
</button>
<button id="newPromptBtn" class="icon-btn" title="新建提示词">
<i class="fas fa-plus"></i>
</button>
<button id="deletePromptBtn" class="icon-btn" title="删除当前提示词">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
<div class="prompt-preview">
<div id="promptDescription" class="prompt-description">
<p>您是一位专业的问题解决专家。请逐步分析问题,找出问题所在,并提供详细的解决方案。始终使用用户偏好的语言回答。</p>
</div>
<div class="prompt-preview-overlay">
<div class="prompt-edit-hint">
<!-- 移除重复的编辑图标 -->
</div>
</div>
</div>
</div>
<textarea id="systemPrompt" class="hidden">您是一位专业的问题解决专家。请逐步分析问题,找出问题所在,并提供详细的解决方案。始终使用用户偏好的语言回答。</textarea>
</div>
</div>
<!-- OCR设置部分 -->
<div class="settings-section ocr-settings">
<h3><i class="fas fa-font"></i> OCR 源设置</h3>
<div class="setting-group">
<div class="ocr-source-control">
<div class="ocr-source-selector">
<select id="ocrSourceSelect" class="ocr-source-select">
<option value="auto">自动选择</option>
<option value="baidu">百度OCR</option>
<option value="mathpix">Mathpix</option>
</select>
</div>
</div>
</div>
</div>
<!-- 2. 所有API密钥集中在一个区域 -->
<div class="settings-section api-key-settings">
<h3><i class="fas fa-key"></i> API密钥设置</h3>
<!-- API密钥状态显示与编辑区域 -->
<div class="api-keys-list" id="apiKeysList">
<div class="api-key-status">
<span class="key-name">Anthropic API:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="AnthropicApiKeyStatus" class="key-status" data-key="AnthropicApiKey">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="AnthropicApiKey" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="AnthropicApiKey" placeholder="输入 Anthropic API key">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="AnthropicApiKey" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">OpenAI API:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="OpenaiApiKeyStatus" class="key-status" data-key="OpenaiApiKey">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="OpenaiApiKey" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="OpenaiApiKey" placeholder="输入 OpenAI API key">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="OpenaiApiKey" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">DeepSeek API:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="DeepseekApiKeyStatus" class="key-status" data-key="DeepseekApiKey">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="DeepseekApiKey" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="DeepseekApiKey" placeholder="输入 DeepSeek API key">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="DeepseekApiKey" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">Alibaba API:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="AlibabaApiKeyStatus" class="key-status" data-key="AlibabaApiKey">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="AlibabaApiKey" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="AlibabaApiKey" placeholder="输入 Alibaba API key">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="AlibabaApiKey" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">Google API:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="GoogleApiKeyStatus" class="key-status" data-key="GoogleApiKey">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="GoogleApiKey" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="GoogleApiKey" placeholder="输入 Google API key">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="GoogleApiKey" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">Doubao API:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="DoubaoApiKeyStatus" class="key-status" data-key="DoubaoApiKey">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="DoubaoApiKey" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="DoubaoApiKey" placeholder="输入Doubao API key">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="DoubaoApiKey" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<!-- 百度OCR API Key配置 -->
<div class="api-key-status">
<span class="key-name">百度OCR API Key:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="BaiduApiKeyStatus" class="key-status" data-key="BaiduApiKey">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="BaiduApiKey" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="BaiduApiKey" placeholder="输入百度OCR API Key">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="BaiduApiKey" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">百度OCR Secret Key:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="BaiduSecretKeyStatus" class="key-status" data-key="BaiduSecretKey">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="BaiduSecretKey" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="BaiduSecretKey" placeholder="输入百度OCR Secret Key">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="BaiduSecretKey" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">Mathpix App ID:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="MathpixAppIdStatus" class="key-status" data-key="MathpixAppId">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="MathpixAppId" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="MathpixAppId" placeholder="输入 Mathpix App ID">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="MathpixAppId" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">Mathpix App Key:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="MathpixAppKeyStatus" class="key-status" data-key="MathpixAppKey">未设置</span>
<button class="btn-icon edit-api-key" data-key-type="MathpixAppKey" title="编辑此密钥">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="password" class="key-input" data-key-type="MathpixAppKey" placeholder="输入 Mathpix App Key">
<button class="btn-icon toggle-visibility">
<i class="fas fa-eye"></i>
</button>
<button class="btn-icon save-api-key" data-key-type="MathpixAppKey" title="保存密钥">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
</div>
</div>
<!-- 添加中转 API url 设置区域 -->
<div class="settings-section api-url-settings">
<h3><i class="fas fa-link"></i> 中转 API url 设置</h3>
<div class="setting-group">
<div class="api-keys-list" id="apiBaseUrlsList">
<div class="api-key-status">
<span class="key-name">Anthropic API URL:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="AnthropicApiBaseUrlStatus" class="key-status" data-key="AnthropicApiBaseUrl">未设置</span>
<button class="btn-icon edit-api-base-url" data-key-type="AnthropicApiBaseUrl" title="编辑此URL">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="text" class="key-input" data-key-type="AnthropicApiBaseUrl" placeholder="https://api.anthropic.com/v1">
<button class="btn-icon save-api-base-url" data-key-type="AnthropicApiBaseUrl" title="保存URL">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">OpenAI API URL:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="OpenaiApiBaseUrlStatus" class="key-status" data-key="OpenaiApiBaseUrl">未设置</span>
<button class="btn-icon edit-api-base-url" data-key-type="OpenaiApiBaseUrl" title="编辑此URL">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="text" class="key-input" data-key-type="OpenaiApiBaseUrl" placeholder="https://api.openai.com/v1">
<button class="btn-icon save-api-base-url" data-key-type="OpenaiApiBaseUrl" title="保存URL">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">DeepSeek API URL:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="DeepseekApiBaseUrlStatus" class="key-status" data-key="DeepseekApiBaseUrl">未设置</span>
<button class="btn-icon edit-api-base-url" data-key-type="DeepseekApiBaseUrl" title="编辑此URL">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="text" class="key-input" data-key-type="DeepseekApiBaseUrl" placeholder="https://api.deepseek.com/v1">
<button class="btn-icon save-api-base-url" data-key-type="DeepseekApiBaseUrl" title="保存URL">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">Alibaba API URL:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="AlibabaApiBaseUrlStatus" class="key-status" data-key="AlibabaApiBaseUrl">未设置</span>
<button class="btn-icon edit-api-base-url" data-key-type="AlibabaApiBaseUrl" title="编辑此URL">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="text" class="key-input" data-key-type="AlibabaApiBaseUrl" placeholder="https://dashscope.aliyuncs.com/api/v1">
<button class="btn-icon save-api-base-url" data-key-type="AlibabaApiBaseUrl" title="保存URL">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">Google API URL:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="GoogleApiBaseUrlStatus" class="key-status" data-key="GoogleApiBaseUrl">未设置</span>
<button class="btn-icon edit-api-base-url" data-key-type="GoogleApiBaseUrl" title="编辑此URL">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="text" class="key-input" data-key-type="GoogleApiBaseUrl" placeholder="https://generativelanguage.googleapis.com/v1beta">
<button class="btn-icon save-api-base-url" data-key-type="GoogleApiBaseUrl" title="保存URL">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
<div class="api-key-status">
<span class="key-name">Doubao API URL:</span>
<div class="key-status-wrapper">
<!-- 显示状态 -->
<div class="key-display">
<span id="DoubaoApiBaseUrlStatus" class="key-status" data-key="DoubaoApiBaseUrl">未设置</span>
<button class="btn-icon edit-api-base-url" data-key-type="DoubaoApiBaseUrl" title="编辑此URL">
<i class="fas fa-edit"></i>
</button>
</div>
<!-- 编辑状态 -->
<div class="key-edit hidden">
<input type="text" class="key-input" data-key-type="DoubaoApiBaseUrl" placeholder="https://ark.cn-beijing.volces.com/api/v3">
<button class="btn-icon save-api-base-url" data-key-type="DoubaoApiBaseUrl" title="保存URL">
<i class="fas fa-save"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 3. 不常用的其他设置放在后面 -->
<div class="settings-section proxy-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-actions crop-actions-top">
<button id="cropCancel" class="btn-secondary">
<i class="fas fa-times"></i>
<span>取消</span>
</button>
<div class="crop-bottom-buttons">
<button id="cropReset" class="btn-secondary crop-half-btn">
<i class="fas fa-undo"></i>
<span>重置</span>
</button>
<button id="cropConfirm" class="btn-secondary crop-half-btn">
<i class="fas fa-check"></i>
<span>确认</span>
</button>
</div>
<button id="cropSendToAI" class="btn-primary">
<i class="fas fa-paper-plane"></i>
<span>发送</span>
</button>
</div>
<div class="crop-wrapper">
<div class="crop-area"></div>
</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>
</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>
<!-- 提示词对话框 -->
<div class="dialog-overlay" id="promptDialogOverlay"></div>
<div class="prompt-dialog" id="promptDialog">
<h3>添加/编辑提示词</h3>
<div class="form-group">
<label for="promptId">提示词ID</label>
<input type="text" id="promptId" placeholder="英文字母和下划线,如math_problems">
</div>
<div class="form-group">
<label for="promptName">名称</label>
<input type="text" id="promptName" placeholder="提示词名称">
</div>
<div class="form-group">
<label for="promptContent">内容</label>
<textarea id="promptContent" placeholder="输入提示词内容..."></textarea>
</div>
<div class="form-group">
<label for="promptDescriptionEdit">描述(可选)</label>
<input type="text" id="promptDescriptionEdit" placeholder="简短描述">
</div>
<div class="dialog-buttons">
<button class="cancel-btn" id="cancelPromptBtn">取消</button>
<button class="save-btn" id="confirmPromptBtn">保存</button>
</div>
</div>
<!-- 确保按照正确的顺序加载脚本 -->
<!-- 先加载UI管理器,确保它能在DOM加载完成后初始化 -->
<script src="{{ url_for('static', filename='js/ui.js') }}"></script>
<!-- 然后加载设置管理器,它依赖UI管理器 -->
<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() {
// 初始化更新检查
try {
const updateInfo = JSON.parse('{{ update_info|tojson|safe }}');
if (updateInfo && updateInfo.has_update) {
showUpdateNotice(updateInfo);
}
// 24小时后再次检查更新
setTimeout(checkForUpdates, 24 * 60 * 60 * 1000);
} catch (error) {
console.error('更新检查初始化失败:', error);
}
});
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(function(response) { return response.json(); })
.then(function(updateInfo) {
const dismissedVersion = localStorage.getItem('dismissedUpdate');
// 只有当有更新且用户没有关闭过此版本的通知时才显示
if (updateInfo.has_update && dismissedVersion !== updateInfo.latest_version) {
showUpdateNotice(updateInfo);
}
})
.catch(function(error) { console.error('检查更新失败:', error); });
}
</script>
</body>
</html>