瀏覽代碼

更新库

liuq 5 月之前
父節點
當前提交
6505ae2748
共有 4 個文件被更改,包括 196 次插入3 次删除
  1. 1 1
      requirements.txt
  2. 26 2
      src/display/gui_display.py
  3. 119 0
      src/views/components/numeric_keypad.py
  4. 50 0
      小智.spec

+ 1 - 1
requirements.txt

@@ -14,7 +14,7 @@ soxr==0.5.0.post1
 psutil==7.0.0
 pillow==11.3.0
 webrtcvad-wheels==2.0.14
-sherpa-onnx==1.12.8
+sherpa-onnx==1.12.20
 pendulum==3.1.0
 
 # 纯 Python 为主

+ 26 - 2
src/display/gui_display.py

@@ -18,6 +18,7 @@ from PyQt5.QtWidgets import QApplication, QVBoxLayout, QWidget
 from src.display.base_display import BaseDisplay
 from src.display.gui_display_model import GuiDisplayModel
 from src.utils.resource_finder import find_assets_dir
+from src.views.components.numeric_keypad import NumericKeypad
 
 
 # 创建兼容的元类
@@ -231,7 +232,10 @@ class GuiDisplay(BaseDisplay, QObject, metaclass=CombinedMeta):
         """
         self.root = QWidget()
         self.root.setWindowTitle("")
-        self.root.setWindowFlags(Qt.FramelessWindowHint | Qt.Window)
+        # 设置窗口标志:无边框 + 窗口置顶
+        self.root.setWindowFlags(
+            Qt.FramelessWindowHint | Qt.Window | Qt.WindowStaysOnTopHint
+        )
 
         # 根据配置计算窗口大小
         window_size, is_fullscreen = self._calculate_window_size()
@@ -367,7 +371,7 @@ class GuiDisplay(BaseDisplay, QObject, metaclass=CombinedMeta):
         # 标题栏控制信号映射
         titlebar_signals = {
             "titleMinimize": self._minimize_window,
-            "titleClose": self._quit_application,
+            "titleClose": self._on_title_close,
             "titleDragStart": self._on_title_drag_start,
             "titleDragMoveTo": self._on_title_drag_move,
             "titleDragEnd": self._on_title_drag_end,
@@ -446,6 +450,10 @@ class GuiDisplay(BaseDisplay, QObject, metaclass=CombinedMeta):
         """
         处理设置按钮点击.
         """
+        # 弹出密码验证
+        if not NumericKeypad.verify(self.root):
+            return
+
         try:
             from src.views.settings import SettingsWindow
 
@@ -611,9 +619,20 @@ class GuiDisplay(BaseDisplay, QObject, metaclass=CombinedMeta):
         """
         最小化窗口.
         """
+        # 弹出密码验证
+        if not NumericKeypad.verify(self.root):
+            return
+
         if self.root:
             self.root.showMinimized()
 
+    def _on_title_close(self):
+        """
+        标题栏关闭按钮点击.
+        """
+        if self.root:
+            self.root.close()
+
     def _quit_application(self):
         """
         退出应用程序.
@@ -664,6 +683,11 @@ class GuiDisplay(BaseDisplay, QObject, metaclass=CombinedMeta):
         """
         处理窗口关闭事件.
         """
+        # 弹出密码验证
+        if not NumericKeypad.verify(self.root):
+            event.ignore()
+            return
+
         # 如果系统托盘可用,最小化到托盘
         if self.system_tray and (
             getattr(self.system_tray, "is_available", lambda: False)()

+ 119 - 0
src/views/components/numeric_keypad.py

@@ -0,0 +1,119 @@
+# -*- coding: utf-8 -*-
+from PyQt5.QtWidgets import (
+    QDialog, QVBoxLayout, QGridLayout, QPushButton, 
+    QLineEdit, QMessageBox, QWidget
+)
+from PyQt5.QtCore import Qt
+from PyQt5.QtGui import QFont
+
+class NumericKeypad(QDialog):
+    """
+    数字密码键盘控件
+    
+    用于验证操作权限,默认密码为 199510
+    """
+    def __init__(self, parent=None):
+        super().__init__(parent)
+        self.setWindowTitle("请输入密码")
+        self.setFixedSize(320, 420)
+        self.setWindowFlags(Qt.Dialog | Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowCloseButtonHint)
+        
+        # 验证密码
+        self.target_password = "199510"
+        
+        self._init_ui()
+        self._setup_styles()
+
+    def _init_ui(self):
+        # 主布局
+        layout = QVBoxLayout()
+        layout.setSpacing(15)
+        layout.setContentsMargins(20, 20, 20, 20)
+        self.setLayout(layout)
+
+        # 显示框
+        self.display = QLineEdit()
+        self.display.setEchoMode(QLineEdit.Password)
+        self.display.setReadOnly(True)
+        self.display.setAlignment(Qt.AlignCenter)
+        self.display.setMinimumHeight(50)
+        self.display.setPlaceholderText("请输入6位数字密码")
+        layout.addWidget(self.display)
+
+        # 键盘区域
+        grid_layout = QGridLayout()
+        grid_layout.setSpacing(10)
+        
+        # 按钮配置
+        buttons = [
+            ('1', 0, 0), ('2', 0, 1), ('3', 0, 2),
+            ('4', 1, 0), ('5', 1, 1), ('6', 1, 2),
+            ('7', 2, 0), ('8', 2, 1), ('9', 2, 2),
+            ('删除', 3, 0), ('0', 3, 1), ('确认', 3, 2),
+        ]
+
+        for text, row, col in buttons:
+            btn = QPushButton(text)
+            btn.setFixedSize(80, 60)
+            btn.clicked.connect(lambda checked, t=text: self._on_btn_clicked(t))
+            grid_layout.addWidget(btn, row, col)
+
+        layout.addLayout(grid_layout)
+
+    def _setup_styles(self):
+        self.setStyleSheet("""
+            QDialog {
+                background-color: #f0f0f0;
+            }
+            QLineEdit {
+                background-color: white;
+                border: 2px solid #ddd;
+                border-radius: 8px;
+                font-size: 24px;
+                color: #333;
+                padding: 5px;
+            }
+            QPushButton {
+                background-color: white;
+                border: 1px solid #ddd;
+                border-radius: 8px;
+                font-size: 20px;
+                color: #333;
+            }
+            QPushButton:hover {
+                background-color: #e6e6e6;
+            }
+            QPushButton:pressed {
+                background-color: #d0d0d0;
+            }
+        """)
+
+    def _on_btn_clicked(self, text):
+        current_text = self.display.text()
+        
+        if text == '删除':
+            self.display.setText(current_text[:-1])
+        elif text == '确认':
+            self._verify_password()
+        else:
+            if len(current_text) < 6:  # 限制长度
+                self.display.setText(current_text + text)
+
+    def _verify_password(self):
+        input_pwd = self.display.text()
+        if input_pwd == self.target_password:
+            self.accept()  # 验证通过,关闭对话框并返回 QDialog.Accepted
+        else:
+            QMessageBox.warning(self, "验证失败", "密码错误,请重试!")
+            self.display.clear()
+
+    @staticmethod
+    def verify(parent=None):
+        """
+        静态方法,方便调用
+        返回: bool (验证是否通过)
+        """
+        dialog = NumericKeypad(parent)
+        result = dialog.exec_()
+        return result == QDialog.Accepted
+

+ 50 - 0
小智.spec

@@ -0,0 +1,50 @@
+# -*- mode: python ; coding: utf-8 -*-
+# Generated by UnifyPy 2.0
+
+block_cipher = None
+
+a = Analysis(
+    ['C:\\worksapce\\py_xiaozhi\\main.py'],
+    pathex=[],
+    binaries=[],
+    datas=[('models', 'models'), ('scripts', 'scripts'), ('src', 'src'), ('libs', 'libs'), ('assets', 'assets')],
+    hiddenimports=[],
+    hookspath=[],
+    hooksconfig={},
+    runtime_hooks=[],
+    excludes=[],
+    win_no_prefer_redirects=False,
+    win_private_assemblies=False,
+    cipher=block_cipher,
+    noarchive=False,
+)
+
+pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
+
+exe = EXE(
+    pyz,
+    a.scripts,
+    [],
+    exclude_binaries=True,
+    name='小智',
+    debug=False,
+    bootloader_ignore_signals=False,
+    strip=False,
+    upx=True,
+    upx_exclude=[],
+    runtime_tmpdir=None,
+    console=False,
+    disable_windowed_traceback=False,
+    contents_directory='.',
+    icon='assets/icon.png',
+)
+
+coll = COLLECT(exe,
+               a.binaries,
+               a.zipfiles,
+               a.datas,
+               strip=False,
+               upx=True,
+               upx_exclude=[],
+               name='小智')
+