Bläddra i källkod

更新快捷指令

liuq 3 månader sedan
förälder
incheckning
d99324099f
3 ändrade filer med 183 tillägg och 2 borttagningar
  1. 45 0
      src/display/gui_display.py
  2. 119 2
      src/display/gui_display.qml
  3. 19 0
      src/display/gui_display_model.py

+ 45 - 0
src/display/gui_display.py

@@ -4,6 +4,7 @@ GUI 显示模块 - 使用 QML 实现.
 """
 
 import asyncio
+import json
 import os
 import signal
 from abc import ABCMeta
@@ -340,6 +341,7 @@ class GuiDisplay(BaseDisplay, QObject, metaclass=CombinedMeta):
         完成启动流程.
         """
         await self.update_emotion("neutral")
+        self._load_quick_commands()
 
         # 根据配置决定显示模式
         if getattr(self, "_is_fullscreen", False):
@@ -349,6 +351,49 @@ class GuiDisplay(BaseDisplay, QObject, metaclass=CombinedMeta):
 
         self._setup_system_tray()
 
+    def _load_quick_commands(self):
+        """
+        加载快捷指令配置.
+        """
+        try:
+            # 获取项目根目录 (假设当前文件在 src/display/)
+            root_dir = Path(__file__).resolve().parents[2]
+            config_dir = root_dir / "config"
+            config_file = config_dir / "quick_commands.json"
+
+            # 确保config目录存在
+            if not config_dir.exists():
+                config_dir.mkdir(parents=True, exist_ok=True)
+
+            if not config_file.exists():
+                # 默认配置
+                default_commands = [
+                    {"label": "音量 80%", "text": "音量调整到80"},
+                    {"label": "音量 20%", "text": "音量调整到20"},
+                    {"label": "打开灯光", "text": "打开灯光"},
+                    {"label": "关闭灯光", "text": "关闭灯光"},
+                ]
+                with open(config_file, "w", encoding="utf-8") as f:
+                    json.dump(default_commands, f, indent=4, ensure_ascii=False)
+                commands = default_commands
+            else:
+                with open(config_file, "r", encoding="utf-8") as f:
+                    commands = json.load(f)
+
+            # 简单的校验
+            valid_commands = []
+            if isinstance(commands, list):
+                for cmd in commands:
+                    if isinstance(cmd, dict) and "label" in cmd and "text" in cmd:
+                        valid_commands.append(cmd)
+
+            self.display_model.set_quick_commands(valid_commands)
+            self.logger.info(f"已加载 {len(valid_commands)} 条快捷指令")
+
+        except Exception as e:
+            self.logger.error(f"加载快捷指令失败: {e}")
+            self.display_model.set_quick_commands([])
+
     # =========================================================================
     # 信号连接
     # =========================================================================

+ 119 - 2
src/display/gui_display.qml

@@ -22,6 +22,96 @@ Rectangle {
     signal titleDragMoveTo(real mouseX, real mouseY)
     signal titleDragEnd()
 
+    // 快捷指令弹窗
+    Popup {
+        id: quickCmdPopup
+        width: root.width * 0.5
+        height: root.height * 0.5
+        parent: root
+        x: (root.width - width) / 2
+        y: (root.height - height) / 2
+        modal: true
+        focus: true
+        closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
+
+        background: Rectangle {
+            color: "white"
+            radius: 12
+            border.color: "#e5e6eb"
+            border.width: 1
+            layer.enabled: true
+            layer.effect: DropShadow {
+                transparentBorder: true
+                horizontalOffset: 0
+                verticalOffset: 4
+                radius: 16
+                samples: 25
+                color: "#20000000"
+            }
+        }
+
+        ColumnLayout {
+            anchors.fill: parent
+            anchors.margins: 12
+            spacing: 8
+
+            Text {
+                text: "快捷指令"
+                font.family: "PingFang SC, Microsoft YaHei UI"
+                font.weight: Font.Bold
+                font.pixelSize: 15
+                color: "#1d2129"
+                Layout.alignment: Qt.AlignHCenter
+                Layout.topMargin: 4
+            }
+
+            ListView {
+                id: listView
+                Layout.fillWidth: true
+                Layout.fillHeight: true
+                clip: true
+                spacing: 4
+                model: displayModel ? displayModel.quickCommands : []
+
+                delegate: ItemDelegate {
+                    width: ListView.view.width
+                    height: 40
+                    
+                    background: Rectangle {
+                        color: parent.pressed ? "#e5e6eb" : (parent.hovered ? "#f2f3f5" : "transparent")
+                        radius: 6
+                    }
+
+                    contentItem: Text {
+                        text: modelData.label || ""
+                        font.family: "PingFang SC, Microsoft YaHei UI"
+                        font.pixelSize: 13
+                        color: "#333333"
+                        verticalAlignment: Text.AlignVCenter
+                        leftPadding: 12
+                    }
+                    
+                    onClicked: {
+                        if (modelData.text) {
+                            root.sendButtonClicked(modelData.text)
+                        }
+                        quickCmdPopup.close()
+                    }
+                }
+
+                // 空状态提示
+                Text {
+                    anchors.centerIn: parent
+                    text: "暂无指令"
+                    font.family: "PingFang SC, Microsoft YaHei UI"
+                    font.pixelSize: 13
+                    color: "#86909c"
+                    visible: parent.count === 0
+                }
+            }
+        }
+    }
+
     // 主布局
     ColumnLayout {
         anchors.fill: parent
@@ -319,8 +409,8 @@ Rectangle {
 
                 // 输入 + 发送
                 RowLayout {
-                    Layout.fillWidth: true
-                    Layout.minimumWidth: 120
+                    Layout.fillWidth: false
+                    Layout.preferredWidth: 160
                     Layout.preferredHeight: 38
                     spacing: 6
 
@@ -391,6 +481,33 @@ Rectangle {
                     onClicked: root.modeButtonClicked()
                 }
 
+                // 快捷指令(次要)
+                Button {
+                    id: quickCmdBtn
+                    Layout.preferredWidth: 200
+                    Layout.fillWidth: true
+                    Layout.maximumWidth: 300
+                    Layout.preferredHeight: 38
+                    text: "快捷指令"
+                    background: Rectangle { 
+                        color: quickCmdBtn.pressed ? "#b7eb8f" : (quickCmdBtn.hovered ? "#d9f7be" : "#f6ffed")
+                        radius: 8 
+                        border.color: "#b7eb8f"
+                        border.width: 1
+                    }
+                    contentItem: Text {
+                        text: quickCmdBtn.text
+                        font.family: "PingFang SC, Microsoft YaHei UI"
+                        font.pixelSize: 16
+                        font.weight: Font.Bold
+                        color: "#389e0d"
+                        horizontalAlignment: Text.AlignHCenter
+                        verticalAlignment: Text.AlignVCenter
+                        elide: Text.ElideRight
+                    }
+                    onClicked: quickCmdPopup.open()
+                }
+
                 // 设置(次要)
                 Button {
                     id: settingsBtn

+ 19 - 0
src/display/gui_display_model.py

@@ -18,6 +18,7 @@ class GuiDisplayModel(QObject):
     buttonTextChanged = pyqtSignal()
     modeTextChanged = pyqtSignal()
     autoModeChanged = pyqtSignal()
+    quickCommandsChanged = pyqtSignal()
 
     # 用户操作信号
     manualButtonPressed = pyqtSignal()
@@ -39,6 +40,7 @@ class GuiDisplayModel(QObject):
         self._mode_text = "手动对话"  # 模式切换按钮文本
         self._auto_mode = False  # 是否自动模式
         self._is_connected = False
+        self._quick_commands = []  # 快捷指令列表
 
     # 状态文本属性
     @pyqtProperty(str, notify=statusTextChanged)
@@ -106,6 +108,17 @@ class GuiDisplayModel(QObject):
             self._auto_mode = value
             self.autoModeChanged.emit()
 
+    # 快捷指令列表属性
+    @pyqtProperty(list, notify=quickCommandsChanged)
+    def quickCommands(self):
+        return self._quick_commands
+
+    @quickCommands.setter
+    def quickCommands(self, value):
+        if self._quick_commands != value:
+            self._quick_commands = value
+            self.quickCommandsChanged.emit()
+
     # 便捷方法
     def update_status(self, status: str, connected: bool):
         """
@@ -147,3 +160,9 @@ class GuiDisplayModel(QObject):
             self.modeText = "自动对话"
         else:
             self.modeText = "手动对话"
+
+    def set_quick_commands(self, commands: list):
+        """
+        设置快捷指令列表.
+        """
+        self.quickCommands = commands