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>

Files changed (3) hide show
  1. static/script.js +22 -0
  2. static/style.css +97 -0
  3. 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&#10;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>