1. 修复豆包系统提示词不起作用问题,以及输出格式渲染不正确问题;

2. 截图支持窗口大小与位置记忆,并在完成截图后默认发送给AI;
3. 调整页面布局,适合盲按开始截图,结果窗口置于截图之上.
This commit is contained in:
Gnoloah
2025-09-12 12:06:35 +08:00
parent acdfca54b1
commit 4921d98d0a
7 changed files with 354 additions and 82 deletions

View File

@@ -110,7 +110,15 @@
"supportsMultimodal": true, "supportsMultimodal": true,
"isReasoning": false, "isReasoning": false,
"version": "latest", "version": "latest",
"description": "Google更快速的Gemini 2.5 Flash模型支持图像理解有免费配额" "description": "Google最新的Gemini 2.5 Flash模型支持图像理解速度更快,性能更好"
},
"gemini-2.0-flash": {
"name": "Gemini 2.0 Flash",
"provider": "google",
"supportsMultimodal": true,
"isReasoning": false,
"version": "latest",
"description": "Google更快速的Gemini 2.0 Flash模型支持图像理解有免费配额"
}, },
"doubao-seed-1-6-250615": { "doubao-seed-1-6-250615": {
"name": "Doubao-Seed-1.6", "name": "Doubao-Seed-1.6",

View File

@@ -1,5 +1,5 @@
{ {
"version": "1.3.0", "version": "1.4.0",
"build_date": "2025-04-11", "build_date": "2025-04-11",
"github_repo": "Zippland/Snap-Solver" "github_repo": "Zippland/Snap-Solver"
} }

View File

@@ -74,9 +74,16 @@ class DoubaoModel(BaseModel):
"Content-Type": "application/json" "Content-Type": "application/json"
} }
# 构建消息 - 根据官方API文档暂时不使用系统提示词 # 构建消息 - 添加系统提示词
messages = [] messages = []
# 添加系统提示词
if self.system_prompt:
messages.append({
"role": "system",
"content": self.system_prompt
})
# 添加用户查询 # 添加用户查询
user_content = text user_content = text
if self.language and self.language != 'auto': if self.language and self.language != 'auto':
@@ -221,6 +228,16 @@ class DoubaoModel(BaseModel):
elif image_data.startswith('iVBORw0KGgo'): # PNG magic number in base64 elif image_data.startswith('iVBORw0KGgo'): # PNG magic number in base64
image_format = "png" image_format = "png"
# 构建消息
messages = []
# 添加系统提示词
if self.system_prompt:
messages.append({
"role": "system",
"content": self.system_prompt
})
user_content = [ user_content = [
{ {
"type": "text", "type": "text",
@@ -234,12 +251,10 @@ class DoubaoModel(BaseModel):
} }
] ]
messages = [ messages.append({
{
"role": "user", "role": "user",
"content": user_content "content": user_content
} })
]
# 处理推理配置 # 处理推理配置
thinking = { thinking = {

View File

@@ -53,7 +53,7 @@ class GoogleModel(BaseModel):
def get_model_identifier(self) -> str: def get_model_identifier(self) -> str:
"""返回默认的模型标识符""" """返回默认的模型标识符"""
return "gemini-2.5-flash" # 使用有免费配额的模型作为默认值 return "gemini-2.0-flash" # 使用有免费配额的模型作为默认值
def analyze_text(self, text: str, proxies: dict = None) -> Generator[dict, None, None]: def analyze_text(self, text: str, proxies: dict = None) -> Generator[dict, None, None]:
"""流式生成文本响应""" """流式生成文本响应"""

View File

@@ -657,12 +657,24 @@ class SnapSolver {
case 'error': case 'error':
console.error('Analysis error:', data.error); console.error('Analysis error:', data.error);
const errorMessage = data.error || 'Unknown error occurred';
// 安全处理错误消息,确保它是字符串
let errorMessage = 'Unknown error occurred';
if (data.error) {
if (typeof data.error === 'string') {
errorMessage = data.error;
} else if (typeof data.error === 'object') {
// 如果是对象尝试获取消息字段或转换为JSON
errorMessage = data.error.message || data.error.error || JSON.stringify(data.error);
} else {
errorMessage = String(data.error);
}
}
// 显示错误信息 // 显示错误信息
if (errorMessage && this.responseContent) { if (this.responseContent) {
const currentText = this.responseContent.textContent || ''; // 不要尝试获取现有内容,直接显示错误信息
this.setElementContent(this.responseContent, currentText + '\nError: ' + errorMessage); this.setElementContent(this.responseContent, 'Error: ' + errorMessage);
} }
// 重新启用按钮 // 重新启用按钮
@@ -803,11 +815,35 @@ class SnapSolver {
setElementContent(element, content) { setElementContent(element, content) {
if (!element) return; if (!element) return;
// 首先确保content是字符串
if (typeof content !== 'string') {
if (content === null || content === undefined) {
content = '';
} else if (typeof content === 'object') {
// 对于对象,尝试获取有意义的字符串表示
if (content.error || content.message) {
content = content.error || content.message;
} else if (content.toString && typeof content.toString === 'function' && content.toString() !== '[object Object]') {
content = content.toString();
} else {
// 作为最后手段使用JSON.stringify
try {
content = JSON.stringify(content, null, 2);
} catch (e) {
content = '[Complex Object]';
}
}
} else {
content = String(content);
}
}
try { try {
// 检查marked是否已配置 // 检查marked是否已配置
if (typeof marked === 'undefined') { if (typeof marked === 'undefined') {
console.warn('Marked库未加载回退到纯文本显示'); console.warn('Marked库未加载回退到纯文本显示');
element.textContent = content; // 即使回退到纯文本,也要保留换行和基本格式
element.innerHTML = content.replace(/\n/g, '<br>');
return; return;
} }
@@ -825,8 +861,8 @@ class SnapSolver {
} }
} catch (error) { } catch (error) {
console.error('Markdown解析错误:', error); console.error('Markdown解析错误:', error);
// 发生错误时回退到纯文本显示 // 发生错误时也保留换行格式
element.textContent = content; element.innerHTML = content.replace(/\n/g, '<br>');
} }
// 自动滚动到底部 // 自动滚动到底部
@@ -868,7 +904,14 @@ class SnapSolver {
dragMode: 'move', dragMode: 'move',
aspectRatio: NaN, aspectRatio: NaN,
modal: true, modal: true,
background: true background: true,
ready: function() {
// 如果有上次保存的裁剪框数据,应用它
if (self.lastCropBoxData) {
self.cropper.setCropBoxData(self.lastCropBoxData);
console.log('Applied saved crop box data');
}
}
}); });
} catch (error) { } catch (error) {
console.error('Failed to initialize cropper', error); console.error('Failed to initialize cropper', error);
@@ -940,6 +983,9 @@ class SnapSolver {
setupCropEvents() { setupCropEvents() {
// 移除裁剪按钮的点击事件监听 // 移除裁剪按钮的点击事件监听
// 存储裁剪框数据
this.lastCropBoxData = null;
// Crop confirm button // Crop confirm button
document.getElementById('cropConfirm').addEventListener('click', () => { document.getElementById('cropConfirm').addEventListener('click', () => {
if (!this.checkConnectionBeforeAction()) return; if (!this.checkConnectionBeforeAction()) return;
@@ -957,6 +1003,9 @@ class SnapSolver {
const cropBoxData = this.cropper.getCropBoxData(); const cropBoxData = this.cropper.getCropBoxData();
console.log('Crop box data:', cropBoxData); console.log('Crop box data:', cropBoxData);
// 保存裁剪框数据以便下次使用
this.lastCropBoxData = cropBoxData;
if (!cropBoxData || typeof cropBoxData.width !== 'number' || typeof cropBoxData.height !== 'number') { if (!cropBoxData || typeof cropBoxData.width !== 'number' || typeof cropBoxData.height !== 'number') {
throw new Error('Invalid crop box data'); throw new Error('Invalid crop box data');
} }
@@ -1008,6 +1057,22 @@ class SnapSolver {
this.updateImageActionButtons(); this.updateImageActionButtons();
window.uiManager.showToast('裁剪成功'); window.uiManager.showToast('裁剪成功');
// 获取当前模型信息
const settings = window.settingsManager.getSettings();
const supportsMultimodal = settings.modelInfo?.supportsMultimodal || false;
// 如果模型支持多模态自动发送至AI
if (supportsMultimodal) {
setTimeout(() => {
// 显示Claude分析面板
this.claudePanel.classList.remove('hidden');
this.emptyState.classList.add('hidden');
// 发送图像到Claude进行分析
this.sendImageToClaude(this.croppedImage);
}, 500); // 短暂延迟以确保UI更新
}
} catch (error) { } catch (error) {
console.error('Cropping error details:', { console.error('Cropping error details:', {
message: error.message, message: error.message,
@@ -1036,6 +1101,15 @@ class SnapSolver {
this.imagePreview.classList.add('hidden'); this.imagePreview.classList.add('hidden');
document.querySelector('.crop-area').innerHTML = ''; document.querySelector('.crop-area').innerHTML = '';
}); });
// Crop reset button
document.getElementById('cropReset').addEventListener('click', () => {
if (this.cropper) {
// 重置裁剪区域到默认状态
this.cropper.reset();
window.uiManager.showToast('已重置裁剪区域');
}
});
} }
setupAnalysisEvents() { setupAnalysisEvents() {
@@ -1167,7 +1241,7 @@ class SnapSolver {
} }
}); });
} catch (error) { } catch (error) {
this.responseContent.textContent = 'Error: Failed to send text for analysis - ' + error.message; this.setElementContent(this.responseContent, 'Error: Failed to send text for analysis - ' + error.message);
this.sendExtractedTextBtn.disabled = false; this.sendExtractedTextBtn.disabled = false;
window.uiManager.showToast('发送文本进行分析失败', 'error'); window.uiManager.showToast('发送文本进行分析失败', 'error');
} }
@@ -1346,7 +1420,7 @@ class SnapSolver {
// 注意Claude面板的显示已经在点击事件中处理这里不再重复 // 注意Claude面板的显示已经在点击事件中处理这里不再重复
} catch (error) { } catch (error) {
this.responseContent.textContent = 'Error: ' + error.message; this.setElementContent(this.responseContent, 'Error: ' + error.message);
window.uiManager.showToast('发送图片分析失败', 'error'); window.uiManager.showToast('发送图片分析失败', 'error');
this.sendToClaudeBtn.disabled = false; this.sendToClaudeBtn.disabled = false;
} }
@@ -1453,6 +1527,8 @@ class SnapSolver {
smartLists: true, // 使用比原生markdown更智能的列表行为 smartLists: true, // 使用比原生markdown更智能的列表行为
smartypants: false, // 不要使用更智能的标点符号 smartypants: false, // 不要使用更智能的标点符号
xhtml: false, // 不使用自闭合标签 xhtml: false, // 不使用自闭合标签
mangle: false, // 不混淆邮箱地址
headerIds: false, // 不生成header ID
highlight: function(code, lang) { highlight: function(code, lang) {
// 如果highlight.js不可用直接返回代码 // 如果highlight.js不可用直接返回代码
if (typeof hljs === 'undefined') { if (typeof hljs === 'undefined') {

View File

@@ -22,7 +22,8 @@
--highlight-bg-color-dark: #2d333b; --highlight-bg-color-dark: #2d333b;
--button-hover: #f3f4f6; --button-hover: #f3f4f6;
--button-active: #ebecf0; --button-active: #ebecf0;
--header-height: 60px; --header-height: 40px;
--header-height: 40px;
--transition-speed: 0.3s; --transition-speed: 0.3s;
--screen-md: 768px; --screen-md: 768px;
--screen-sm: 480px; --screen-sm: 480px;
@@ -131,12 +132,19 @@ body {
/* Header Styles */ /* Header Styles */
.app-header { .app-header {
background-color: var(--surface); background-color: var(--surface);
padding: 0.75rem 1rem; padding: 0.3rem 1rem;
padding: 0.3rem 1rem;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
z-index: 100; z-index: 100;
position: sticky; position: sticky;
top: 0; top: 0;
border-bottom: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color);
height: var(--header-height);
display: flex;
align-items: center;
height: var(--header-height);
display: flex;
align-items: center;
} }
.header-content { .header-content {
@@ -149,6 +157,12 @@ body {
width: 100%; width: 100%;
} }
.header-middle {
display: flex;
align-items: center;
gap: 0.5rem;
}
.app-header h1 { .app-header h1 {
font-size: 1.3rem; font-size: 1.3rem;
color: var(--primary); color: var(--primary);
@@ -163,7 +177,7 @@ body {
font-size: 0.8rem; font-size: 0.8rem;
padding: 0.2rem 0.5rem; padding: 0.2rem 0.5rem;
border-radius: 1rem; border-radius: 1rem;
margin: 0 0.5rem; margin: 0;
white-space: nowrap; white-space: nowrap;
font-weight: 600; font-weight: 600;
display: inline-flex; display: inline-flex;
@@ -206,11 +220,14 @@ body {
.header-buttons { .header-buttons {
display: flex; display: flex;
gap: 0.5rem; gap: 0.5rem;
align-items: center; /* 确保按钮垂直居中 */
align-items: center; /* 确保按钮垂直居中 */
} }
.header-buttons .btn-icon { .header-buttons .btn-icon {
width: 36px; width: 36px;
height: 36px; height: 32px;
height: 32px;
border-radius: 50%; border-radius: 50%;
display: flex; display: flex;
align-items: center; align-items: center;
@@ -221,6 +238,16 @@ body {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
} }
.capture-btn-highlight {
background-color: var(--primary) !important;
color: white !important;
box-shadow: 0 4px 12px rgba(var(--primary-rgb), 0.3) !important;
width: auto !important;
min-width: 100px !important;
border-radius: 18px !important;
padding: 0 8px !important;
}
.header-buttons .btn-icon:hover { .header-buttons .btn-icon:hover {
transform: translateY(-2px); transform: translateY(-2px);
background-color: var(--hover-color); background-color: var(--hover-color);
@@ -236,8 +263,10 @@ body {
.app-main { .app-main {
flex: 1; flex: 1;
display: flex; display: flex;
padding: 1.5rem; padding: 0.5rem 1rem; /* 减小垂直内边距和水平内边距 */
gap: 1.5rem; gap: 1rem;
padding: 0.5rem 1rem; /* 减小垂直内边距和水平内边距 */
gap: 1rem;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
background-color: var(--background); background-color: var(--background);
@@ -375,20 +404,27 @@ body {
.btn-action { .btn-action {
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%); background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%);
color: white; color: white;
padding: 0.6rem 1rem; padding: 0.8rem 1.5rem;
padding: 0.8rem 1.5rem;
border: none; border: none;
border-radius: 0.4rem; border-radius: 2rem;
font-size: 0.85rem; font-size: 1rem;
border-radius: 2rem;
font-size: 1rem;
font-weight: 600; font-weight: 600;
cursor: pointer; cursor: pointer;
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
gap: 0.4rem; gap: 0.5rem;
gap: 0.5rem;
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1); transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
position: relative; position: relative;
overflow: hidden; overflow: hidden;
min-width: 180px;
min-width: 180px;
} }
.btn-action i { .btn-action i {
@@ -515,6 +551,10 @@ body {
font-size: 1.1rem; font-size: 1.1rem;
} }
.header-middle {
gap: 0.3rem;
}
#connectionStatus { #connectionStatus {
font-size: 0.7rem; font-size: 0.7rem;
padding: 0.15rem 0.4rem; padding: 0.15rem 0.4rem;
@@ -525,6 +565,12 @@ body {
height: 32px; height: 32px;
} }
.capture-btn-highlight {
min-width: 90px !important;
padding: 0 6px !important;
font-size: 0.85rem !important;
}
.toolbar-buttons { .toolbar-buttons {
flex-direction: row; flex-direction: row;
gap: 0.5rem; gap: 0.5rem;
@@ -552,6 +598,37 @@ body {
min-height: 200px; min-height: 200px;
} }
.claude-panel .response-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.25rem 0.75rem; /* 调整垂直内边距 */
background-color: var(--surface-alt);
border-bottom: 1px solid var(--border-color);
border-top-left-radius: 0.75rem;
border-top-right-radius: 0.75rem;
font-weight: 600;
color: var(--text-primary);
font-size: 1rem;
}
border-radius: 0.75rem;
min-height: 200px;
}
.claude-panel .response-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.25rem 0.75rem; /* 调整垂直内边距 */
background-color: var(--surface-alt);
border-bottom: 1px solid var(--border-color);
border-top-left-radius: 0.75rem;
border-top-right-radius: 0.75rem;
font-weight: 600;
color: var(--text-primary);
font-size: 1rem;
}
.response-content { .response-content {
padding: 1rem; padding: 1rem;
font-size: 0.85rem; font-size: 0.85rem;
@@ -590,10 +667,20 @@ body {
font-size: 1rem; font-size: 1rem;
} }
.header-middle {
gap: 0.2rem;
}
.header-middle .btn-icon {
width: 28px;
height: 28px;
}
#connectionStatus { #connectionStatus {
max-width: 70px; max-width: 70px;
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;
font-size: 0.65rem;
} }
.header-buttons .btn-icon { .header-buttons .btn-icon {
@@ -602,6 +689,12 @@ body {
font-size: 0.85rem; font-size: 0.85rem;
} }
.capture-btn-highlight {
min-width: 80px !important;
padding: 0 4px !important;
font-size: 0.8rem !important;
}
.toolbar-buttons { .toolbar-buttons {
justify-content: center; justify-content: center;
} }
@@ -684,6 +777,10 @@ body {
transition: all 0.3s ease; transition: all 0.3s ease;
overflow: visible; overflow: visible;
width: 100%; width: 100%;
position: relative;
margin-bottom: 1.5rem;
position: relative;
margin-bottom: 1.5rem;
} }
.claude-panel:not(.hidden) { .claude-panel:not(.hidden) {
@@ -705,7 +802,8 @@ body {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
padding: 1rem 1.25rem; padding: 0.25rem 1.25rem; /* 进一步减小垂直内边距 */
padding: 0.25rem 1.25rem; /* 进一步减小垂直内边距 */
border-bottom: 1px solid var(--border-color); border-bottom: 1px solid var(--border-color);
background-color: var(--surface); background-color: var(--surface);
position: sticky; position: sticky;
@@ -1603,6 +1701,26 @@ button:disabled {
background-color: var(--surface); background-color: var(--surface);
} }
.crop-actions-top {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 10;
background-color: rgba(0, 0, 0, 0.7);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
.crop-actions-top {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 10;
background-color: rgba(0, 0, 0, 0.7);
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
}
/* Animations */ /* Animations */
@keyframes toast-in { @keyframes toast-in {
from { from {
@@ -2948,10 +3066,17 @@ button:disabled {
.capture-btn-highlight { .capture-btn-highlight {
background-color: #ff5a5f !important; background-color: #ff5a5f !important;
color: white !important; color: white !important;
transform: scale(1.15); /* transform: scale(1.3); */ /* 移除整体缩放 */
box-shadow: 0 0 8px rgba(255, 90, 95, 0.5); box-shadow: 0 0 12px rgba(255, 90, 95, 0.6);
border-radius: 50%; border-radius: 0.5rem; /* 调整为长条状的圆角 */
/* transform: scale(1.3); */ /* 移除整体缩放 */
box-shadow: 0 0 12px rgba(255, 90, 95, 0.6);
border-radius: 0.5rem; /* 调整为长条状的圆角 */
position: relative; position: relative;
width: 100px !important; /* 增加宽度 */
height: 36px !important; /* 保持与普通按钮相同的高度 */
width: 100px !important; /* 增加宽度 */
height: 36px !important; /* 保持与普通按钮相同的高度 */
} }
.capture-btn-highlight i { .capture-btn-highlight i {
@@ -2960,12 +3085,14 @@ button:disabled {
.capture-btn-highlight:hover { .capture-btn-highlight:hover {
background-color: #ff7e82 !important; background-color: #ff7e82 !important;
transform: scale(1.2); /* transform: scale(1.2); */
/* transform: scale(1.2); */
box-shadow: 0 0 12px rgba(255, 90, 95, 0.7); box-shadow: 0 0 12px rgba(255, 90, 95, 0.7);
} }
.capture-btn-highlight:active { .capture-btn-highlight:active {
transform: scale(1.1); /* transform: scale(1.1); */
/* transform: scale(1.1); */
box-shadow: 0 0 5px rgba(255, 90, 95, 0.4); box-shadow: 0 0 5px rgba(255, 90, 95, 0.4);
} }

View File

@@ -32,17 +32,20 @@
<header class="app-header"> <header class="app-header">
<div class="header-content"> <div class="header-content">
<h1>Snap Solver <span class="version-badge">v<span id="currentVersion">{{ update_info.current_version }}</span></span></h1> <h1>Snap Solver <span class="version-badge">v<span id="currentVersion">{{ update_info.current_version }}</span></span></h1>
<div id="connectionStatus" class="status disconnected">未连接</div> <div class="header-middle">
<div class="header-buttons">
<button id="captureBtn" class="btn-icon capture-btn-highlight" title="截图" disabled>
<i class="fas fa-camera"></i>
</button>
<button id="themeToggle" class="btn-icon" title="切换主题"> <button id="themeToggle" class="btn-icon" title="切换主题">
<i class="fas fa-moon"></i> <i class="fas fa-moon"></i>
</button> </button>
<button id="settingsToggle" class="btn-icon" title="设置"> <button id="settingsToggle" class="btn-icon" title="设置">
<i class="fas fa-cog"></i> <i class="fas fa-cog"></i>
</button> </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>
</div> </div>
</header> </header>
@@ -61,6 +64,68 @@
<main class="app-main"> <main class="app-main">
<div class="content-panel"> <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 class="capture-section">
<div id="emptyState" class="empty-state"> <div id="emptyState" class="empty-state">
<i class="fas fa-camera-retro"></i> <i class="fas fa-camera-retro"></i>
@@ -100,37 +165,6 @@
</button> </button>
</div> </div>
</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> </div>
<aside id="settingsPanel" class="settings-panel"> <aside id="settingsPanel" class="settings-panel">
@@ -774,19 +808,31 @@
</main> </main>
<div id="cropContainer" class="crop-container hidden"> <div id="cropContainer" class="crop-container hidden">
<div class="crop-wrapper"> <div class="crop-actions crop-actions-top">
<div class="crop-area"></div> <div class="crop-actions crop-actions-top">
</div>
<div class="crop-actions">
<button id="cropCancel" class="btn-secondary"> <button id="cropCancel" class="btn-secondary">
<i class="fas fa-times"></i> <i class="fas fa-times"></i>
<span>取消</span> <span>取消</span>
</button> </button>
<button id="cropReset" class="btn-secondary">
<i class="fas fa-undo"></i>
<span>重置</span>
</button>
<button id="cropReset" class="btn-secondary">
<i class="fas fa-undo"></i>
<span>重置</span>
</button>
<button id="cropConfirm" class="btn-primary"> <button id="cropConfirm" class="btn-primary">
<i class="fas fa-check"></i> <i class="fas fa-check"></i>
<span>确认</span> <span>确认</span>
</button> </button>
</div> </div>
<div class="crop-wrapper">
<div class="crop-area"></div>
</div>
<div class="crop-wrapper">
<div class="crop-area"></div>
</div>
</div> </div>
<div id="toastContainer" class="toast-container"></div> <div id="toastContainer" class="toast-container"></div>