更新設置分頁,新增佈局模式與方向選擇功能,並改善相關UI及翻譯支持。

This commit is contained in:
Minidoracat 2025-06-03 13:42:59 +08:00
parent 4df533b8e1
commit a4dd076038
7 changed files with 303 additions and 102 deletions

View File

@ -20,15 +20,19 @@ from ...i18n import t, get_i18n_manager
class SettingsTab(QWidget):
"""設置分頁組件"""
language_changed = Signal()
layout_mode_change_requested = Signal(bool) # 佈局模式變更請求信號
layout_change_requested = Signal(bool, str) # 佈局變更請求信號 (combined_mode, orientation)
def __init__(self, combined_mode: bool, config_manager, parent=None):
super().__init__(parent)
self.combined_mode = combined_mode
self.config_manager = config_manager
self.layout_orientation = self.config_manager.get_layout_orientation()
self.i18n = get_i18n_manager()
self._setup_ui()
# 在UI設置完成後確保正確設置初始狀態
self._set_initial_layout_state()
def _setup_ui(self) -> None:
"""設置用戶介面"""
layout = QVBoxLayout(self)
@ -107,7 +111,7 @@ class SettingsTab(QWidget):
layout_layout.setSpacing(12)
layout_layout.setContentsMargins(16, 16, 16, 16)
# 佈局模式選擇
# 佈局模式選擇 - 使用三個獨立的單選按鈕
self.layout_button_group = QButtonGroup()
# 分離模式
@ -118,24 +122,36 @@ class SettingsTab(QWidget):
layout_layout.addWidget(self.separate_mode_radio)
self.separate_desc_label = QLabel(t('settings.layout.separateModeDescription'))
self.separate_desc_label.setStyleSheet("color: #9e9e9e; font-size: 12px; margin-left: 20px; margin-bottom: 8px;")
self.separate_desc_label.setStyleSheet("color: #9e9e9e; font-size: 12px; margin-left: 20px; margin-bottom: 12px;")
self.separate_desc_label.setWordWrap(True)
layout_layout.addWidget(self.separate_desc_label)
# 合併模式
self.combined_mode_radio = QRadioButton(t('settings.layout.combinedMode'))
self.combined_mode_radio.setChecked(self.combined_mode)
self.combined_mode_radio.setStyleSheet("font-size: 14px; font-weight: bold; color: #e0e0e0;")
self.layout_button_group.addButton(self.combined_mode_radio, 1)
layout_layout.addWidget(self.combined_mode_radio)
# 合併模式(垂直布局)
self.combined_vertical_radio = QRadioButton(t('settings.layout.combinedVertical'))
self.combined_vertical_radio.setChecked(self.combined_mode and self.layout_orientation == 'vertical')
self.combined_vertical_radio.setStyleSheet("font-size: 14px; font-weight: bold; color: #e0e0e0;")
self.layout_button_group.addButton(self.combined_vertical_radio, 1)
layout_layout.addWidget(self.combined_vertical_radio)
self.combined_desc_label = QLabel(t('settings.layout.combinedModeDescription'))
self.combined_desc_label.setStyleSheet("color: #9e9e9e; font-size: 12px; margin-left: 20px; margin-bottom: 8px;")
self.combined_desc_label.setWordWrap(True)
layout_layout.addWidget(self.combined_desc_label)
self.combined_vertical_desc_label = QLabel(t('settings.layout.combinedVerticalDescription'))
self.combined_vertical_desc_label.setStyleSheet("color: #9e9e9e; font-size: 12px; margin-left: 20px; margin-bottom: 12px;")
self.combined_vertical_desc_label.setWordWrap(True)
layout_layout.addWidget(self.combined_vertical_desc_label)
# 連接佈局模式變更信號
self.layout_button_group.buttonToggled.connect(self._on_layout_mode_changed)
# 合併模式(水平布局)
self.combined_horizontal_radio = QRadioButton(t('settings.layout.combinedHorizontal'))
self.combined_horizontal_radio.setChecked(self.combined_mode and self.layout_orientation == 'horizontal')
self.combined_horizontal_radio.setStyleSheet("font-size: 14px; font-weight: bold; color: #e0e0e0;")
self.layout_button_group.addButton(self.combined_horizontal_radio, 2)
layout_layout.addWidget(self.combined_horizontal_radio)
self.combined_horizontal_desc_label = QLabel(t('settings.layout.combinedHorizontalDescription'))
self.combined_horizontal_desc_label.setStyleSheet("color: #9e9e9e; font-size: 12px; margin-left: 20px; margin-bottom: 12px;")
self.combined_horizontal_desc_label.setWordWrap(True)
layout_layout.addWidget(self.combined_horizontal_desc_label)
# 連接佈局變更信號
self.layout_button_group.buttonToggled.connect(self._on_layout_changed)
layout.addWidget(self.layout_group)
@ -194,15 +210,16 @@ class SettingsTab(QWidget):
# 發送語言變更信號
self.language_changed.emit()
def _on_layout_mode_changed(self, button, checked: bool) -> None:
"""處理佈局模式變更"""
def _on_layout_changed(self, button, checked: bool) -> None:
"""處理佈局變更"""
if not checked: # 只處理選中的按鈕
return
# 確定新的模式
new_combined_mode = button == self.combined_mode_radio
# 確定新的模式和方向
new_combined_mode = button == self.combined_vertical_radio or button == self.combined_horizontal_radio
new_orientation = 'vertical' if button == self.combined_vertical_radio else 'horizontal'
if new_combined_mode != self.combined_mode:
if new_combined_mode != self.combined_mode or new_orientation != self.layout_orientation:
# 提示用戶需要重新創建界面
reply = QMessageBox.question(
self,
@ -213,13 +230,17 @@ class SettingsTab(QWidget):
)
if reply == QMessageBox.Yes:
# 用戶確認變更,發送佈局模式變更請求
# 用戶確認變更,發送佈局變更請求
self.combined_mode = new_combined_mode
self.layout_mode_change_requested.emit(self.combined_mode)
self.layout_orientation = new_orientation
self.layout_change_requested.emit(self.combined_mode, self.layout_orientation)
else:
# 用戶選擇不重新載入,恢復原來的選項
if self.combined_mode:
self.combined_mode_radio.setChecked(True)
if self.layout_orientation == 'vertical':
self.combined_vertical_radio.setChecked(True)
else:
self.combined_horizontal_radio.setChecked(True)
else:
self.separate_mode_radio.setChecked(True)
@ -241,11 +262,13 @@ class SettingsTab(QWidget):
# 更新佈局設置文字
self.separate_mode_radio.setText(t('settings.layout.separateMode'))
self.combined_mode_radio.setText(t('settings.layout.combinedMode'))
self.combined_vertical_radio.setText(t('settings.layout.combinedVertical'))
self.combined_horizontal_radio.setText(t('settings.layout.combinedHorizontal'))
# 更新佈局描述文字
self.separate_desc_label.setText(t('settings.layout.separateModeDescription'))
self.combined_desc_label.setText(t('settings.layout.combinedModeDescription'))
self.combined_vertical_desc_label.setText(t('settings.layout.combinedVerticalDescription'))
self.combined_horizontal_desc_label.setText(t('settings.layout.combinedHorizontalDescription'))
# 更新視窗設置文字
self.always_center_checkbox.setText(t('settings.window.alwaysCenter'))
@ -260,7 +283,60 @@ class SettingsTab(QWidget):
def set_layout_mode(self, combined_mode: bool) -> None:
"""設置佈局模式"""
self.combined_mode = combined_mode
# 暫時斷開信號連接,避免觸發變更事件
try:
self.layout_button_group.buttonToggled.disconnect()
except RuntimeError:
pass
# 根據當前模式和方向設置正確的選項
if combined_mode:
self.combined_mode_radio.setChecked(True)
if self.layout_orientation == 'vertical':
self.combined_vertical_radio.setChecked(True)
else: # horizontal
self.combined_horizontal_radio.setChecked(True)
else:
self.separate_mode_radio.setChecked(True)
# 重新連接信號
self.layout_button_group.buttonToggled.connect(self._on_layout_changed)
def set_layout_orientation(self, orientation: str) -> None:
"""設置佈局方向"""
self.layout_orientation = orientation
# 暫時斷開信號連接,避免觸發變更事件
try:
self.layout_button_group.buttonToggled.disconnect()
except RuntimeError:
pass
# 如果是合併模式,根據方向設置正確的選項
if self.combined_mode:
if orientation == 'vertical':
self.combined_vertical_radio.setChecked(True)
else: # horizontal
self.combined_horizontal_radio.setChecked(True)
# 重新連接信號
self.layout_button_group.buttonToggled.connect(self._on_layout_changed)
def _set_initial_layout_state(self) -> None:
"""設置初始佈局狀態"""
# 暫時斷開信號連接,避免觸發變更事件
try:
self.layout_button_group.buttonToggled.disconnect()
except RuntimeError:
pass
# 根據當前配置設置正確的選項
if self.combined_mode:
if self.layout_orientation == 'vertical':
self.combined_vertical_radio.setChecked(True)
else: # horizontal
self.combined_horizontal_radio.setChecked(True)
else:
self.separate_mode_radio.setChecked(True)
# 重新連接信號
self.layout_button_group.buttonToggled.connect(self._on_layout_changed)

View File

@ -69,6 +69,17 @@ class ConfigManager:
self.set('combined_mode', combined_mode)
debug_log(f"佈局模式設置: {'合併模式' if combined_mode else '分離模式'}")
def get_layout_orientation(self) -> str:
"""獲取佈局方向vertical=垂直上下horizontal=水平(左右))"""
return self.get('layout_orientation', 'vertical')
def set_layout_orientation(self, orientation: str) -> None:
"""設置佈局方向"""
if orientation not in ['vertical', 'horizontal']:
orientation = 'vertical'
self.set('layout_orientation', orientation)
debug_log(f"佈局方向設置: {'垂直(上下)' if orientation == 'vertical' else '水平(左右)'}")
def get_language(self) -> str:
"""獲取語言設置"""
return self.get('language', 'zh-TW')

View File

@ -35,6 +35,7 @@ class FeedbackWindow(QMainWindow):
# 初始化組件
self.config_manager = ConfigManager()
self.combined_mode = self.config_manager.get_layout_mode()
self.layout_orientation = self.config_manager.get_layout_orientation()
# 設置UI
self._setup_ui()
@ -150,7 +151,8 @@ class FeedbackWindow(QMainWindow):
self.tab_widget,
self.project_dir,
self.summary,
self.combined_mode
self.combined_mode,
self.layout_orientation
)
# 創建分頁
@ -286,18 +288,24 @@ class FeedbackWindow(QMainWindow):
}
""")
def _on_layout_mode_change_requested(self, combined_mode: bool) -> None:
"""處理佈局模式變更請求"""
def _on_layout_change_requested(self, combined_mode: bool, orientation: str) -> None:
"""處理佈局變更請求(模式和方向同時變更)"""
try:
# 保存當前內容
current_data = self.tab_manager.get_feedback_data()
# 記住當前分頁索引
current_tab_index = self.tab_widget.currentIndex()
# 保存新設置
self.combined_mode = combined_mode
self.layout_orientation = orientation
self.config_manager.set_layout_mode(combined_mode)
self.config_manager.set_layout_orientation(orientation)
# 重新創建分頁
self.tab_manager.set_layout_mode(combined_mode)
self.tab_manager.set_layout_orientation(orientation)
self.tab_manager.create_tabs()
# 恢復內容
@ -313,10 +321,26 @@ class FeedbackWindow(QMainWindow):
# 刷新UI文字
self._refresh_ui_texts()
debug_log(f"佈局模式已切換到: {'合併模式' if combined_mode else '分離模式'}")
# 恢復到設定頁面(通常是倒數第二個分頁)
if self.combined_mode:
# 合併模式:回饋、命令、設置、關於
settings_tab_index = 2
else:
# 分離模式:回饋、摘要、命令、設置、關於
settings_tab_index = 3
# 確保索引在有效範圍內
if settings_tab_index < self.tab_widget.count():
self.tab_widget.setCurrentIndex(settings_tab_index)
mode_text = "合併模式" if combined_mode else "分離模式"
orientation_text = "(水平布局)" if orientation == "horizontal" else "(垂直布局)"
if combined_mode:
mode_text += orientation_text
debug_log(f"佈局已切換到: {mode_text}")
except Exception as e:
debug_log(f"佈局模式切換失敗: {e}")
debug_log(f"佈局變更失敗: {e}")
QMessageBox.warning(self, t('errors.title'), t('errors.interfaceReloadError', error=str(e)))
def _handle_image_paste_from_textarea(self) -> None:

View File

@ -21,11 +21,12 @@ from .config_manager import ConfigManager
class TabManager:
"""分頁管理器"""
def __init__(self, tab_widget: QTabWidget, project_dir: str, summary: str, combined_mode: bool):
def __init__(self, tab_widget: QTabWidget, project_dir: str, summary: str, combined_mode: bool, layout_orientation: str = 'vertical'):
self.tab_widget = tab_widget
self.project_dir = project_dir
self.summary = summary
self.combined_mode = combined_mode
self.layout_orientation = layout_orientation
# 配置管理器
self.config_manager = ConfigManager()
@ -61,13 +62,14 @@ class TabManager:
# 設置分頁
self.settings_tab = SettingsTab(self.combined_mode, self.config_manager)
self.settings_tab.set_layout_orientation(self.layout_orientation)
self.tab_widget.addTab(self.settings_tab, t('tabs.language'))
# 關於分頁
self.about_tab = AboutTab()
self.tab_widget.addTab(self.about_tab, t('tabs.about'))
debug_log(f"分頁創建完成,模式: {'合併' if self.combined_mode else '分離'}")
debug_log(f"分頁創建完成,模式: {'合併' if self.combined_mode else '分離'},方向: {self.layout_orientation}")
def _create_combined_feedback_tab(self) -> None:
"""創建合併模式的回饋分頁包含AI摘要"""
@ -84,8 +86,9 @@ class TabManager:
splitter_wrapper_layout.setContentsMargins(16, 16, 16, 0) # 恢復左右邊距設置
splitter_wrapper_layout.setSpacing(0)
# 使用垂直分割器管理 AI摘要、回饋輸入和圖片區域
main_splitter = QSplitter(Qt.Vertical)
# 根據布局方向創建分割器
orientation = Qt.Horizontal if self.layout_orientation == 'horizontal' else Qt.Vertical
main_splitter = QSplitter(orientation)
main_splitter.setChildrenCollapsible(False)
main_splitter.setHandleWidth(6)
main_splitter.setContentsMargins(0, 0, 0, 0) # 設置分割器邊距為0
@ -98,65 +101,127 @@ class TabManager:
}
""")
main_splitter.setStyleSheet("""
QSplitter {
border: none;
background: transparent;
}
QSplitter::handle:vertical {
height: 8px;
background-color: #3c3c3c;
border: 1px solid #555555;
border-radius: 4px;
margin-left: 16px;
margin-right: 16px;
margin-top: 2px;
margin-bottom: 2px;
}
QSplitter::handle:vertical:hover {
background-color: #606060;
border-color: #808080;
}
QSplitter::handle:vertical:pressed {
background-color: #007acc;
border-color: #005a9e;
}
""")
# 根據方向設置不同的分割器樣式
if self.layout_orientation == 'horizontal':
# 水平布局(左右)
main_splitter.setStyleSheet("""
QSplitter {
border: none;
background: transparent;
}
QSplitter::handle:horizontal {
width: 8px;
background-color: #3c3c3c;
border: 1px solid #555555;
border-radius: 4px;
margin-top: 16px;
margin-bottom: 16px;
margin-left: 2px;
margin-right: 2px;
}
QSplitter::handle:horizontal:hover {
background-color: #606060;
border-color: #808080;
}
QSplitter::handle:horizontal:pressed {
background-color: #007acc;
border-color: #005a9e;
}
""")
else:
# 垂直布局(上下)
main_splitter.setStyleSheet("""
QSplitter {
border: none;
background: transparent;
}
QSplitter::handle:vertical {
height: 8px;
background-color: #3c3c3c;
border: 1px solid #555555;
border-radius: 4px;
margin-left: 16px;
margin-right: 16px;
margin-top: 2px;
margin-bottom: 2px;
}
QSplitter::handle:vertical:hover {
background-color: #606060;
border-color: #808080;
}
QSplitter::handle:vertical:pressed {
background-color: #007acc;
border-color: #005a9e;
}
""")
# 創建AI摘要組件
self.summary_tab = SummaryTab(self.summary)
self.summary_tab.setMinimumHeight(150)
self.summary_tab.setMaximumHeight(1000) # 允許更大的拖拽範圍
# 創建回饋輸入組件
self.feedback_tab = FeedbackTab()
# 確保回饋分頁有足夠的最小高度來顯示圖片區域
self.feedback_tab.setMinimumHeight(480)
self.feedback_tab.setMaximumHeight(2000) # 允許更大的拖拽範圍
# 添加到主分割器
main_splitter.addWidget(self.summary_tab)
main_splitter.addWidget(self.feedback_tab)
if self.layout_orientation == 'horizontal':
# 水平布局設置
self.summary_tab.setMinimumWidth(300)
self.summary_tab.setMaximumWidth(800)
self.feedback_tab.setMinimumWidth(400)
self.feedback_tab.setMaximumWidth(1200)
# 調整分割器比例和初始大小,確保圖片區域可見
main_splitter.setStretchFactor(0, 1) # AI摘要區域
main_splitter.setStretchFactor(1, 2) # 回饋輸入區域(包含圖片)- 給予更多空間
# 添加到主分割器
main_splitter.addWidget(self.summary_tab)
main_splitter.addWidget(self.feedback_tab)
# 調整分割器比例(水平布局)
main_splitter.setStretchFactor(0, 1) # AI摘要區域
main_splitter.setStretchFactor(1, 2) # 回饋輸入區域
# 從配置載入分割器位置
saved_sizes = self.config_manager.get_splitter_sizes('main_splitter_horizontal')
if saved_sizes and len(saved_sizes) == 2:
main_splitter.setSizes(saved_sizes)
else:
main_splitter.setSizes([400, 600]) # 預設大小(水平)
# 連接分割器位置變化信號
main_splitter.splitterMoved.connect(
lambda pos, index: self._save_splitter_position(main_splitter, 'main_splitter_horizontal')
)
# 設置最小高度
main_splitter.setMinimumHeight(600)
main_splitter.setMaximumHeight(2000)
# 從配置載入分割器位置,如果沒有則使用預設值
saved_sizes = self.config_manager.get_splitter_sizes('main_splitter')
if saved_sizes and len(saved_sizes) == 2:
main_splitter.setSizes(saved_sizes)
else:
main_splitter.setSizes([160, 480]) # 預設大小
# 垂直布局設置
self.summary_tab.setMinimumHeight(150)
self.summary_tab.setMaximumHeight(1000)
self.feedback_tab.setMinimumHeight(480)
self.feedback_tab.setMaximumHeight(2000)
# 連接分割器位置變化信號,自動保存位置
main_splitter.splitterMoved.connect(
lambda pos, index: self._save_main_splitter_position(main_splitter)
)
# 添加到主分割器
main_splitter.addWidget(self.summary_tab)
main_splitter.addWidget(self.feedback_tab)
# 設置主分割器的最小高度,確保圖片區域可見
main_splitter.setMinimumHeight(660) # 進一步增加最小高度
main_splitter.setMaximumHeight(3000) # 允許更大的高度以觸發滾動
# 調整分割器比例(垂直布局)
main_splitter.setStretchFactor(0, 1) # AI摘要區域
main_splitter.setStretchFactor(1, 2) # 回饋輸入區域
# 從配置載入分割器位置
saved_sizes = self.config_manager.get_splitter_sizes('main_splitter_vertical')
if saved_sizes and len(saved_sizes) == 2:
main_splitter.setSizes(saved_sizes)
else:
main_splitter.setSizes([160, 480]) # 預設大小(垂直)
# 連接分割器位置變化信號
main_splitter.splitterMoved.connect(
lambda pos, index: self._save_splitter_position(main_splitter, 'main_splitter_vertical')
)
# 設置最小高度
main_splitter.setMinimumHeight(660)
main_splitter.setMaximumHeight(3000)
splitter_wrapper_layout.addWidget(main_splitter)
@ -168,7 +233,10 @@ class TabManager:
# 設置合併分頁的大小策略,確保能夠觸發父容器的滾動條
self.combined_feedback_tab.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self.combined_feedback_tab.setMinimumHeight(700) # 設置最小高度
if self.layout_orientation == 'vertical':
self.combined_feedback_tab.setMinimumHeight(700) # 垂直布局設置最小高度
else:
self.combined_feedback_tab.setMinimumWidth(800) # 水平布局設置最小寬度
def update_tab_texts(self) -> None:
"""更新分頁標籤文字"""
@ -246,8 +314,8 @@ class TabManager:
if self.settings_tab:
if hasattr(parent, 'language_changed'):
self.settings_tab.language_changed.connect(parent.language_changed)
if hasattr(parent, '_on_layout_mode_change_requested'):
self.settings_tab.layout_mode_change_requested.connect(parent._on_layout_mode_change_requested)
if hasattr(parent, '_on_layout_change_requested'):
self.settings_tab.layout_change_requested.connect(parent._on_layout_change_requested)
# 連接回饋分頁的圖片貼上信號
if self.feedback_tab:
@ -267,8 +335,14 @@ class TabManager:
if self.settings_tab:
self.settings_tab.set_layout_mode(combined_mode)
def _save_main_splitter_position(self, splitter: QSplitter) -> None:
def set_layout_orientation(self, orientation: str) -> None:
"""設置佈局方向"""
self.layout_orientation = orientation
if self.settings_tab:
self.settings_tab.set_layout_orientation(orientation)
def _save_splitter_position(self, splitter: QSplitter, config_key: str) -> None:
"""保存分割器位置"""
sizes = splitter.sizes()
self.config_manager.set_splitter_sizes('main_splitter', sizes)
self.config_manager.set_splitter_sizes(config_key, sizes)
debug_log(f"分割器位置保存成功,大小: {sizes}")

View File

@ -46,6 +46,11 @@
"emptyMessage": "Please enter feedback content before submitting. You can describe your thoughts, suggestions, or areas that need modification.",
"outputPlaceholder": "Command output will appear here..."
},
"summary": {
"title": "AI Work Summary",
"description": "Below is the work content that AI has just completed for you. Please review and provide feedback.",
"testDescription": "Below is the message content replied by AI. Please review and provide feedback."
},
"command": {
"title": "Command Execution",
"description": "You can execute commands to verify results or gather more information.",
@ -87,10 +92,12 @@
},
"layout": {
"title": "Interface Layout",
"combinedMode": "Combined Mode",
"combinedModeDescription": "Display AI summary and feedback on the same page for easy comparison",
"separateMode": "Separate Mode",
"separateModeDescription": "AI summary and feedback are in separate tabs"
"separateModeDescription": "AI summary and feedback are in separate tabs",
"combinedVertical": "Combined Mode (Vertical Layout)",
"combinedVerticalDescription": "AI summary on top, feedback input below, both on the same page",
"combinedHorizontal": "Combined Mode (Horizontal Layout)",
"combinedHorizontalDescription": "AI summary on left, feedback input on right, expanding summary viewing area"
},
"window": {
"title": "Window Positioning",

View File

@ -31,6 +31,11 @@
"emptyTitle": "反馈内容为空",
"emptyMessage": "请先输入反馈内容再提交。您可以描述想法、建议或需要修改的地方。"
},
"summary": {
"title": "AI 工作摘要",
"description": "以下是 AI 刚才为您完成的工作内容,请检视并提供反馈。",
"testDescription": "以下是 AI 回复的消息内容,请检视并提供反馈。"
},
"command": {
"title": "命令执行",
"description": "您可以执行命令来验证结果或收集更多信息。",
@ -67,10 +72,12 @@
},
"layout": {
"title": "界面布局",
"combinedMode": "合并模式",
"combinedModeDescription": "将 AI 摘要和反馈放在同一页面,便于对照阅读",
"separateMode": "分离模式",
"separateModeDescription": "AI 摘要和反馈分别在不同页签"
"separateModeDescription": "AI 摘要和反馈分别在不同页签",
"combinedVertical": "合并模式(垂直布局)",
"combinedVerticalDescription": "AI 摘要在上,反馈输入在下,摘要和反馈在同一页面",
"combinedHorizontal": "合并模式(水平布局)",
"combinedHorizontalDescription": "AI 摘要在左,反馈输入在右,增大摘要可视区域"
},
"window": {
"title": "窗口定位",

View File

@ -88,10 +88,12 @@
},
"layout": {
"title": "界面佈局",
"combinedMode": "合併模式",
"combinedModeDescription": "將 AI 摘要和回饋放在同一頁面,便於對照閱讀",
"separateMode": "分離模式",
"separateModeDescription": "AI 摘要和回饋分別在不同頁籤"
"separateModeDescription": "AI 摘要和回饋分別在不同頁籤",
"combinedVertical": "合併模式(垂直布局)",
"combinedVerticalDescription": "AI 摘要在上,回饋輸入在下,摘要和回饋在同一頁面",
"combinedHorizontal": "合併模式(水平布局)",
"combinedHorizontalDescription": "AI 摘要在左,回饋輸入在右,增大摘要可視區域"
},
"window": {
"title": "視窗定位",