diff --git a/src/mcp_feedback_enhanced/web/static/css/styles.css b/src/mcp_feedback_enhanced/web/static/css/styles.css
index e332926..b268490 100644
--- a/src/mcp_feedback_enhanced/web/static/css/styles.css
+++ b/src/mcp_feedback_enhanced/web/static/css/styles.css
@@ -989,9 +989,11 @@ body {
.image-preview-container {
display: flex;
flex-wrap: wrap;
- gap: 8px;
+ gap: 4px;
margin-top: 12px;
justify-content: center;
+ /* 添加 padding 為刪除按鈕留出空間 */
+ padding: 8px;
}
.image-preview-container:empty {
@@ -1003,10 +1005,12 @@ body {
position: relative;
display: inline-block;
border-radius: 6px;
- overflow: hidden;
+ /* 移除 overflow: hidden 以確保刪除按鈕完全顯示 */
background: var(--bg-primary);
border: 1px solid var(--border-color);
transition: all 0.3s ease;
+ /* 添加一些 margin 為刪除按鈕留出空間 */
+ margin: 10px;
}
.image-preview-item:hover {
@@ -1019,6 +1023,7 @@ body {
height: 80px;
object-fit: cover;
display: block;
+ border-radius: 6px;
}
/* 圖片刪除按鈕 */
diff --git a/src/mcp_feedback_enhanced/web/static/js/app.js b/src/mcp_feedback_enhanced/web/static/js/app.js
index c375616..6687f8d 100644
--- a/src/mcp_feedback_enhanced/web/static/js/app.js
+++ b/src/mcp_feedback_enhanced/web/static/js/app.js
@@ -259,12 +259,35 @@ class FeedbackApp {
this.commandOutput = document.getElementById('commandOutput');
this.runCommandBtn = document.getElementById('runCommandBtn');
- // 圖片相關元素
- this.imageInput = document.getElementById('imageInput');
- this.imageUploadArea = document.getElementById('imageUploadArea');
- this.imagePreviewContainer = document.getElementById('imagePreviewContainer');
- this.imageSizeLimitSelect = document.getElementById('imageSizeLimit');
- this.enableBase64DetailCheckbox = document.getElementById('enableBase64Detail');
+ // 動態初始化圖片相關元素
+ this.initImageElements();
+ }
+
+ /**
+ * 動態初始化圖片相關元素,支援多佈局模式
+ */
+ initImageElements() {
+ // 根據當前佈局模式確定元素前綴
+ const prefix = this.layoutMode && this.layoutMode.startsWith('combined') ? 'combined' : 'feedback';
+
+ console.log(`🖼️ 初始化圖片元素,使用前綴: ${prefix}`);
+
+ // 圖片相關元素 - 優先使用當前模式的元素
+ this.imageInput = document.getElementById(`${prefix}ImageInput`) || document.getElementById('imageInput');
+ this.imageUploadArea = document.getElementById(`${prefix}ImageUploadArea`) || document.getElementById('imageUploadArea');
+ this.imagePreviewContainer = document.getElementById(`${prefix}ImagePreviewContainer`) || document.getElementById('imagePreviewContainer');
+ this.imageSizeLimitSelect = document.getElementById(`${prefix}ImageSizeLimit`) || document.getElementById('imageSizeLimit');
+ this.enableBase64DetailCheckbox = document.getElementById(`${prefix}EnableBase64Detail`) || document.getElementById('enableBase64Detail');
+
+ // 記錄當前使用的前綴,用於後續操作
+ this.currentImagePrefix = prefix;
+
+ // 驗證關鍵元素是否存在
+ if (!this.imageInput || !this.imageUploadArea) {
+ console.warn(`⚠️ 圖片元素初始化失敗 - imageInput: ${!!this.imageInput}, imageUploadArea: ${!!this.imageUploadArea}`);
+ } else {
+ console.log(`✅ 圖片元素初始化成功 - 前綴: ${prefix}`);
+ }
}
initTabs() {
@@ -349,67 +372,203 @@ class FeedbackApp {
this.handleCombinedMode();
}
+ // 重新初始化圖片處理(確保使用正確的佈局模式元素)
+ this.reinitializeImageHandling();
+
// 保存當前頁籤設定
this.saveSettings();
console.log(`切換到頁籤: ${tabName}`);
}
- initImageHandling() {
- if (!this.imageUploadArea || !this.imageInput) return;
+ /**
+ * 重新初始化圖片處理功能
+ */
+ reinitializeImageHandling() {
+ console.log('🔄 重新初始化圖片處理功能...');
+ // 移除舊的事件監聽器
+ this.removeImageEventListeners();
+
+ // 重新初始化圖片元素
+ this.initImageElements();
+
+ // 如果有必要的元素,重新設置事件監聽器
+ if (this.imageUploadArea && this.imageInput) {
+ this.setupImageEventListeners();
+ console.log('✅ 圖片處理功能重新初始化完成');
+ } else {
+ console.warn('⚠️ 圖片處理重新初始化失敗 - 缺少必要元素');
+ }
+
+ // 更新圖片預覽(確保在新的容器中顯示)
+ this.updateImagePreview();
+ }
+
+ /**
+ * 設置圖片事件監聽器
+ */
+ setupImageEventListeners() {
// 文件選擇事件
- this.imageInput.addEventListener('change', (e) => {
+ this.imageChangeHandler = (e) => {
this.handleFileSelect(e.target.files);
- });
+ };
+ this.imageInput.addEventListener('change', this.imageChangeHandler);
// 點擊上傳區域
- this.imageUploadArea.addEventListener('click', () => {
+ this.imageClickHandler = () => {
this.imageInput.click();
- });
+ };
+ this.imageUploadArea.addEventListener('click', this.imageClickHandler);
// 拖放事件
- this.imageUploadArea.addEventListener('dragover', (e) => {
+ this.imageDragOverHandler = (e) => {
e.preventDefault();
this.imageUploadArea.classList.add('dragover');
- });
+ };
+ this.imageUploadArea.addEventListener('dragover', this.imageDragOverHandler);
- this.imageUploadArea.addEventListener('dragleave', (e) => {
+ this.imageDragLeaveHandler = (e) => {
e.preventDefault();
this.imageUploadArea.classList.remove('dragover');
- });
+ };
+ this.imageUploadArea.addEventListener('dragleave', this.imageDragLeaveHandler);
- this.imageUploadArea.addEventListener('drop', (e) => {
+ this.imageDropHandler = (e) => {
e.preventDefault();
this.imageUploadArea.classList.remove('dragover');
this.handleFileSelect(e.dataTransfer.files);
- });
+ };
+ this.imageUploadArea.addEventListener('drop', this.imageDropHandler);
- // 剪貼板貼上事件
- document.addEventListener('paste', (e) => {
- const items = e.clipboardData.items;
- for (let item of items) {
- if (item.type.indexOf('image') !== -1) {
- e.preventDefault();
- const file = item.getAsFile();
- this.handleFileSelect([file]);
- break;
+ // 初始化圖片設定事件
+ this.initImageSettings();
+ }
+
+ initImageHandling() {
+ console.log('🖼️ 開始初始化圖片處理功能...');
+
+ // 重新初始化圖片元素(確保使用最新的佈局模式)
+ this.initImageElements();
+
+ if (!this.imageUploadArea || !this.imageInput) {
+ console.warn('⚠️ 圖片處理初始化失敗 - 缺少必要元素');
+ return;
+ }
+
+ // 清除舊的事件監聽器(如果存在)
+ this.removeImageEventListeners();
+
+ // 設置圖片事件監聽器
+ this.setupImageEventListeners();
+
+ // 設置全域剪貼板貼上事件(只設置一次)
+ if (!this.pasteHandler) {
+ this.pasteHandler = (e) => {
+ const items = e.clipboardData.items;
+ for (let item of items) {
+ if (item.type.indexOf('image') !== -1) {
+ e.preventDefault();
+ const file = item.getAsFile();
+ this.handleFileSelect([file]);
+ break;
+ }
}
- }
- });
+ };
+ document.addEventListener('paste', this.pasteHandler);
+ console.log('✅ 全域剪貼板貼上事件已設置');
+ }
- // 圖片設定事件
+ console.log('✅ 圖片處理功能初始化完成');
+ }
+
+ /**
+ * 移除舊的圖片事件監聽器
+ */
+ removeImageEventListeners() {
+ if (this.imageInput && this.imageChangeHandler) {
+ this.imageInput.removeEventListener('change', this.imageChangeHandler);
+ }
+ if (this.imageUploadArea) {
+ if (this.imageClickHandler) {
+ this.imageUploadArea.removeEventListener('click', this.imageClickHandler);
+ }
+ if (this.imageDragOverHandler) {
+ this.imageUploadArea.removeEventListener('dragover', this.imageDragOverHandler);
+ }
+ if (this.imageDragLeaveHandler) {
+ this.imageUploadArea.removeEventListener('dragleave', this.imageDragLeaveHandler);
+ }
+ if (this.imageDropHandler) {
+ this.imageUploadArea.removeEventListener('drop', this.imageDropHandler);
+ }
+ }
+ }
+
+ /**
+ * 初始化圖片設定事件
+ */
+ initImageSettings() {
+ // 圖片大小限制設定
if (this.imageSizeLimitSelect) {
this.imageSizeLimitSelect.addEventListener('change', (e) => {
this.imageSizeLimit = parseInt(e.target.value);
+ this.saveSettings();
});
}
+ // Base64 詳細模式設定
if (this.enableBase64DetailCheckbox) {
this.enableBase64DetailCheckbox.addEventListener('change', (e) => {
this.enableBase64Detail = e.target.checked;
+ this.saveSettings();
});
}
+
+ // 同步設定到其他佈局模式
+ this.syncImageSettingsAcrossLayouts();
+ }
+
+ /**
+ * 同步圖片設定到所有佈局模式
+ */
+ syncImageSettingsAcrossLayouts() {
+ const prefixes = ['feedback', 'combined'];
+
+ prefixes.forEach(prefix => {
+ const sizeSelect = document.getElementById(`${prefix}ImageSizeLimit`);
+ const base64Checkbox = document.getElementById(`${prefix}EnableBase64Detail`);
+
+ if (sizeSelect && sizeSelect !== this.imageSizeLimitSelect) {
+ sizeSelect.value = this.imageSizeLimit.toString();
+ sizeSelect.addEventListener('change', (e) => {
+ this.imageSizeLimit = parseInt(e.target.value);
+ // 同步到其他元素
+ prefixes.forEach(otherPrefix => {
+ const otherSelect = document.getElementById(`${otherPrefix}ImageSizeLimit`);
+ if (otherSelect && otherSelect !== e.target) {
+ otherSelect.value = e.target.value;
+ }
+ });
+ this.saveSettings();
+ });
+ }
+
+ if (base64Checkbox && base64Checkbox !== this.enableBase64DetailCheckbox) {
+ base64Checkbox.checked = this.enableBase64Detail;
+ base64Checkbox.addEventListener('change', (e) => {
+ this.enableBase64Detail = e.target.checked;
+ // 同步到其他元素
+ prefixes.forEach(otherPrefix => {
+ const otherCheckbox = document.getElementById(`${otherPrefix}EnableBase64Detail`);
+ if (otherCheckbox && otherCheckbox !== e.target) {
+ otherCheckbox.checked = e.target.checked;
+ }
+ });
+ this.saveSettings();
+ });
+ }
+ });
}
handleFileSelect(files) {
@@ -455,22 +614,149 @@ class FeedbackApp {
}
updateImagePreview() {
- if (!this.imagePreviewContainer) return;
+ // 更新所有佈局模式的圖片預覽容器
+ const previewContainers = [
+ document.getElementById('feedbackImagePreviewContainer'),
+ document.getElementById('combinedImagePreviewContainer'),
+ this.imagePreviewContainer // 當前主要容器
+ ].filter(container => container); // 過濾掉不存在的容器
- this.imagePreviewContainer.innerHTML = '';
+ if (previewContainers.length === 0) {
+ console.warn('⚠️ 沒有找到圖片預覽容器');
+ return;
+ }
- this.images.forEach((image, index) => {
- const preview = document.createElement('div');
- preview.className = 'image-preview';
- preview.innerHTML = `
-
-