wapadil Claude commited on
Commit ·
bac962d
1
Parent(s): 4af6f42
[UX] 界面优化 - 移除URL输入 + API配置改为弹窗
Browse files用户需求:
1. 移除"输入图像URL (每行一个)"功能
2. 将API配置改为点击设置按钮弹出的窗口,节省空间
实现内容:
- 删除图像URL输入的textarea组件
- 移除桌面端的API配置卡片(折叠式)
- 添加固定定位的设置按钮(右上角齿轮图标)
- 创建API配置弹窗(居中显示,点击遮罩或Esc关闭)
技术细节:
- templates/index.html:264-267 - 删除imageUrls输入区域
- templates/index.html:154-192 - 移除apiConfigCard
- templates/index.html:152-154 - 添加settings-floating-btn
- templates/index.html:378-414 - 添加settings-modal弹窗
- static/style.css:2988-3083 - 添加弹窗样式
- static/script.js:2657-2677 - 添加弹窗控制函数
UI改进:
✅ 节省左侧面板垂直空间
✅ 设置按钮始终可见,易于访问
✅ 弹窗居中,避免干扰主工作区
✅ 支持Esc键关闭,增强用户体验
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- static/script.js +22 -0
- static/style.css +97 -0
- templates/index.html +43 -45
static/script.js
CHANGED
|
@@ -2653,3 +2653,25 @@ function syncMainToDrawer() {
|
|
| 2653 |
const drawerPrompt = document.getElementById('drawerPrompt');
|
| 2654 |
if (drawerPrompt) drawerPrompt.value = mainPrompt;
|
| 2655 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2653 |
const drawerPrompt = document.getElementById('drawerPrompt');
|
| 2654 |
if (drawerPrompt) drawerPrompt.value = mainPrompt;
|
| 2655 |
}
|
| 2656 |
+
|
| 2657 |
+
// Settings Modal Functions
|
| 2658 |
+
function toggleSettingsModal() {
|
| 2659 |
+
const modal = document.getElementById('settingsModal');
|
| 2660 |
+
if (modal) {
|
| 2661 |
+
modal.classList.toggle('show');
|
| 2662 |
+
}
|
| 2663 |
+
}
|
| 2664 |
+
|
| 2665 |
+
function closeSettingsModal(event) {
|
| 2666 |
+
const modal = document.getElementById('settingsModal');
|
| 2667 |
+
if (modal && (event === undefined || event.target === modal)) {
|
| 2668 |
+
modal.classList.remove('show');
|
| 2669 |
+
}
|
| 2670 |
+
}
|
| 2671 |
+
|
| 2672 |
+
// Close modal on Escape key
|
| 2673 |
+
document.addEventListener('keydown', function(e) {
|
| 2674 |
+
if (e.key === 'Escape') {
|
| 2675 |
+
closeSettingsModal();
|
| 2676 |
+
}
|
| 2677 |
+
});
|
static/style.css
CHANGED
|
@@ -2983,4 +2983,101 @@ select:focus-visible,
|
|
| 2983 |
0 0 20px rgba(0, 122, 255, 0.1);
|
| 2984 |
border-color: var(--brand-primary);
|
| 2985 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2986 |
}
|
|
|
|
| 2983 |
0 0 20px rgba(0, 122, 255, 0.1);
|
| 2984 |
border-color: var(--brand-primary);
|
| 2985 |
}
|
| 2986 |
+
}
|
| 2987 |
+
|
| 2988 |
+
/* Settings Floating Button */
|
| 2989 |
+
.settings-floating-btn {
|
| 2990 |
+
position: fixed;
|
| 2991 |
+
top: 20px;
|
| 2992 |
+
right: 20px;
|
| 2993 |
+
width: 48px;
|
| 2994 |
+
height: 48px;
|
| 2995 |
+
border-radius: 50%;
|
| 2996 |
+
background: var(--surface-primary);
|
| 2997 |
+
border: 1px solid var(--border-light);
|
| 2998 |
+
font-size: 24px;
|
| 2999 |
+
cursor: pointer;
|
| 3000 |
+
z-index: 999;
|
| 3001 |
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
| 3002 |
+
transition: all 0.2s ease;
|
| 3003 |
+
display: flex;
|
| 3004 |
+
align-items: center;
|
| 3005 |
+
justify-content: center;
|
| 3006 |
+
}
|
| 3007 |
+
|
| 3008 |
+
.settings-floating-btn:hover {
|
| 3009 |
+
transform: scale(1.1);
|
| 3010 |
+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
| 3011 |
+
}
|
| 3012 |
+
|
| 3013 |
+
/* Settings Modal */
|
| 3014 |
+
.settings-modal {
|
| 3015 |
+
display: none;
|
| 3016 |
+
position: fixed;
|
| 3017 |
+
top: 0;
|
| 3018 |
+
left: 0;
|
| 3019 |
+
width: 100%;
|
| 3020 |
+
height: 100%;
|
| 3021 |
+
background: rgba(0, 0, 0, 0.5);
|
| 3022 |
+
z-index: 1000;
|
| 3023 |
+
align-items: center;
|
| 3024 |
+
justify-content: center;
|
| 3025 |
+
}
|
| 3026 |
+
|
| 3027 |
+
.settings-modal.show {
|
| 3028 |
+
display: flex;
|
| 3029 |
+
}
|
| 3030 |
+
|
| 3031 |
+
.settings-modal-content {
|
| 3032 |
+
background: var(--surface-primary);
|
| 3033 |
+
border-radius: var(--radius-lg);
|
| 3034 |
+
max-width: 500px;
|
| 3035 |
+
width: 90%;
|
| 3036 |
+
max-height: 80vh;
|
| 3037 |
+
overflow-y: auto;
|
| 3038 |
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
| 3039 |
+
}
|
| 3040 |
+
|
| 3041 |
+
.settings-modal-header {
|
| 3042 |
+
display: flex;
|
| 3043 |
+
align-items: center;
|
| 3044 |
+
justify-content: space-between;
|
| 3045 |
+
padding: var(--spacing-4);
|
| 3046 |
+
border-bottom: 1px solid var(--border-light);
|
| 3047 |
+
}
|
| 3048 |
+
|
| 3049 |
+
.settings-modal-header h2 {
|
| 3050 |
+
margin: 0;
|
| 3051 |
+
font-size: var(--font-lg);
|
| 3052 |
+
}
|
| 3053 |
+
|
| 3054 |
+
.modal-close-btn {
|
| 3055 |
+
width: 32px;
|
| 3056 |
+
height: 32px;
|
| 3057 |
+
border-radius: 50%;
|
| 3058 |
+
border: none;
|
| 3059 |
+
background: transparent;
|
| 3060 |
+
font-size: 24px;
|
| 3061 |
+
cursor: pointer;
|
| 3062 |
+
color: var(--text-secondary);
|
| 3063 |
+
transition: all 0.2s ease;
|
| 3064 |
+
}
|
| 3065 |
+
|
| 3066 |
+
.modal-close-btn:hover {
|
| 3067 |
+
background: var(--surface-secondary);
|
| 3068 |
+
color: var(--text-primary);
|
| 3069 |
+
}
|
| 3070 |
+
|
| 3071 |
+
.settings-modal-body {
|
| 3072 |
+
padding: var(--spacing-4);
|
| 3073 |
+
}
|
| 3074 |
+
|
| 3075 |
+
.settings-modal-body .form-group {
|
| 3076 |
+
margin-bottom: var(--spacing-4);
|
| 3077 |
+
}
|
| 3078 |
+
|
| 3079 |
+
@media (max-width: 768px) {
|
| 3080 |
+
.settings-floating-btn {
|
| 3081 |
+
display: none;
|
| 3082 |
+
}
|
| 3083 |
}
|
templates/index.html
CHANGED
|
@@ -148,49 +148,14 @@
|
|
| 148 |
</div>
|
| 149 |
|
| 150 |
<div class="app-container" id="main-content">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
<!-- Left Panel: Controls (desktop) -->
|
| 152 |
<div class="left-panel">
|
| 153 |
<div class="controls-section">
|
| 154 |
-
<div class="card collapsed" id="apiConfigCard">
|
| 155 |
-
<div class="card-header">
|
| 156 |
-
<h2>🔑 API配置</h2>
|
| 157 |
-
<button type="button" class="settings-toggle-btn" onclick="toggleApiConfig()"
|
| 158 |
-
aria-expanded="false" aria-controls="apiConfigContent" title="展开/收起API配置">
|
| 159 |
-
<span class="toggle-icon">▼</span>
|
| 160 |
-
</button>
|
| 161 |
-
</div>
|
| 162 |
-
<div class="settings-content" id="apiConfigContent">
|
| 163 |
-
<div class="settings-grid">
|
| 164 |
-
<div class="form-group">
|
| 165 |
-
<label for="apiKey">FAL API密钥</label>
|
| 166 |
-
<div class="api-key-input-group">
|
| 167 |
-
<input type="password" id="apiKey" placeholder="请输入您的FAL API密钥" />
|
| 168 |
-
<button type="button" id="toggleApiKey" class="btn-icon" title="显示/隐藏密钥" aria-label="显示/隐藏密钥">👁</button>
|
| 169 |
-
<button type="button" id="testApiKey" class="btn-test" title="测试连接">测试</button>
|
| 170 |
-
</div>
|
| 171 |
-
<small class="help-text">从 <a href="https://fal.ai" target="_blank">fal.ai</a> 获取您的API密钥</small>
|
| 172 |
-
<div id="apiKeyStatus" class="api-key-status" role="status" aria-live="polite"></div>
|
| 173 |
-
</div>
|
| 174 |
-
<div class="form-group">
|
| 175 |
-
<label for="modelSelect">模型选择</label>
|
| 176 |
-
<select id="modelSelect">
|
| 177 |
-
<option value="fal-ai/bytedance/seedream/v4/edit">图像编辑</option>
|
| 178 |
-
<option value="fal-ai/qwen-image-edit-plus">图像编辑 (通义千问)</option>
|
| 179 |
-
<option value="fal-ai/bytedance/seedream/v4/text-to-image">文本生成图像</option>
|
| 180 |
-
</select>
|
| 181 |
-
<small class="help-text">选择用于生成的模型</small>
|
| 182 |
-
</div>
|
| 183 |
-
<div class="form-group">
|
| 184 |
-
<div class="checkbox-group">
|
| 185 |
-
<input type="checkbox" id="enableSDE" />
|
| 186 |
-
<label for="enableSDE">启用结构化指令编辑器 (SDE)</label>
|
| 187 |
-
</div>
|
| 188 |
-
<small class="help-text">将提示词拆分为三个模块:参考协议、场景描述、风格化协议</small>
|
| 189 |
-
</div>
|
| 190 |
-
</div>
|
| 191 |
-
</div>
|
| 192 |
-
</div>
|
| 193 |
-
|
| 194 |
<div class="card">
|
| 195 |
<div class="card-header">
|
| 196 |
<h2 id="promptTitle">✏️ 编辑指令</h2>
|
|
@@ -260,11 +225,6 @@
|
|
| 260 |
<small class="help-text upload-limits">单文件 ≤16MB,支持JPG、PNG、WebP格式</small>
|
| 261 |
<div id="imagePreview" class="image-preview"></div>
|
| 262 |
</div>
|
| 263 |
-
|
| 264 |
-
<div class="form-group">
|
| 265 |
-
<label for="imageUrls">或输入图像URL (每行一个)</label>
|
| 266 |
-
<textarea id="imageUrls" rows="3" placeholder="https://example.com/image1.jpg https://example.com/image2.jpg"></textarea>
|
| 267 |
-
</div>
|
| 268 |
</div>
|
| 269 |
|
| 270 |
<div class="card collapsed" id="settingsCard">
|
|
@@ -415,6 +375,44 @@
|
|
| 415 |
</div>
|
| 416 |
</div>
|
| 417 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 418 |
<!-- Non-intrusive Notification System -->
|
| 419 |
<div class="banner" role="status" aria-live="polite" hidden id="banner"></div>
|
| 420 |
<div class="toasts" aria-live="polite" aria-atomic="true" id="toasts"></div>
|
|
|
|
| 148 |
</div>
|
| 149 |
|
| 150 |
<div class="app-container" id="main-content">
|
| 151 |
+
<!-- Settings Button (fixed position) -->
|
| 152 |
+
<button class="settings-floating-btn" onclick="toggleSettingsModal()" title="打开设置">
|
| 153 |
+
⚙️
|
| 154 |
+
</button>
|
| 155 |
+
|
| 156 |
<!-- Left Panel: Controls (desktop) -->
|
| 157 |
<div class="left-panel">
|
| 158 |
<div class="controls-section">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
<div class="card">
|
| 160 |
<div class="card-header">
|
| 161 |
<h2 id="promptTitle">✏️ 编辑指令</h2>
|
|
|
|
| 225 |
<small class="help-text upload-limits">单文件 ≤16MB,支持JPG、PNG、WebP格式</small>
|
| 226 |
<div id="imagePreview" class="image-preview"></div>
|
| 227 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 228 |
</div>
|
| 229 |
|
| 230 |
<div class="card collapsed" id="settingsCard">
|
|
|
|
| 375 |
</div>
|
| 376 |
</div>
|
| 377 |
|
| 378 |
+
<!-- Settings Modal -->
|
| 379 |
+
<div class="settings-modal" id="settingsModal" onclick="closeSettingsModal(event)">
|
| 380 |
+
<div class="settings-modal-content" onclick="event.stopPropagation()">
|
| 381 |
+
<div class="settings-modal-header">
|
| 382 |
+
<h2>🔑 API配置</h2>
|
| 383 |
+
<button type="button" class="modal-close-btn" onclick="closeSettingsModal()" title="关闭">×</button>
|
| 384 |
+
</div>
|
| 385 |
+
<div class="settings-modal-body">
|
| 386 |
+
<div class="form-group">
|
| 387 |
+
<label for="apiKey">FAL API密钥</label>
|
| 388 |
+
<div class="api-key-input-group">
|
| 389 |
+
<input type="password" id="apiKey" placeholder="请输入您的FAL API密钥" />
|
| 390 |
+
<button type="button" id="toggleApiKey" class="btn-icon" title="显示/隐藏密钥" aria-label="显示/隐藏密钥">👁</button>
|
| 391 |
+
<button type="button" id="testApiKey" class="btn-test" title="测试连接">测试</button>
|
| 392 |
+
</div>
|
| 393 |
+
<small class="help-text">从 <a href="https://fal.ai" target="_blank">fal.ai</a> 获取您的API密钥</small>
|
| 394 |
+
<div id="apiKeyStatus" class="api-key-status" role="status" aria-live="polite"></div>
|
| 395 |
+
</div>
|
| 396 |
+
<div class="form-group">
|
| 397 |
+
<label for="modelSelect">模型选择</label>
|
| 398 |
+
<select id="modelSelect">
|
| 399 |
+
<option value="fal-ai/bytedance/seedream/v4/edit">图像编辑</option>
|
| 400 |
+
<option value="fal-ai/qwen-image-edit-plus">图像编辑 (通义千问)</option>
|
| 401 |
+
<option value="fal-ai/bytedance/seedream/v4/text-to-image">文本生成图像</option>
|
| 402 |
+
</select>
|
| 403 |
+
<small class="help-text">选择用于生成的模型</small>
|
| 404 |
+
</div>
|
| 405 |
+
<div class="form-group">
|
| 406 |
+
<div class="checkbox-group">
|
| 407 |
+
<input type="checkbox" id="enableSDE" />
|
| 408 |
+
<label for="enableSDE">启用结构化指令编辑器 (SDE)</label>
|
| 409 |
+
</div>
|
| 410 |
+
<small class="help-text">将提示词拆分为三个模块:参考协议、场景描述、风格化协议</small>
|
| 411 |
+
</div>
|
| 412 |
+
</div>
|
| 413 |
+
</div>
|
| 414 |
+
</div>
|
| 415 |
+
|
| 416 |
<!-- Non-intrusive Notification System -->
|
| 417 |
<div class="banner" role="status" aria-live="polite" hidden id="banner"></div>
|
| 418 |
<div class="toasts" aria-live="polite" aria-atomic="true" id="toasts"></div>
|