diff --git a/client/src/settings_ui.py b/client/src/settings_ui.py index 4a76f57..aa3c6a1 100644 --- a/client/src/settings_ui.py +++ b/client/src/settings_ui.py @@ -223,6 +223,9 @@ class SettingsPage(QWidget): self.deviceNameInput.setMaxLength(50) self.deviceNameInput.setAccessibleName("当前客户端设备名") + self.currentDeviceSaveButton = PushButton(FIF.SAVE, "保存", self) + self.currentDeviceSaveButton.setAccessibleName("保存当前设备信息") + self.currentDeviceCard = self._build_current_device_card() self.addressInput = LineEdit(self) @@ -314,6 +317,11 @@ class SettingsPage(QWidget): form.addRow(deviceIdLabel, self.deviceIdInput) form.addRow(deviceNameLabel, self.deviceNameInput) layout.addLayout(form) + + commandLayout = QHBoxLayout() + commandLayout.addStretch(1) + commandLayout.addWidget(self.currentDeviceSaveButton) + layout.addLayout(commandLayout) return card def _build_android_device_card(self) -> CardWidget: diff --git a/client/src/settings_ui_event.py b/client/src/settings_ui_event.py index 7984d32..bde57cc 100644 --- a/client/src/settings_ui_event.py +++ b/client/src/settings_ui_event.py @@ -1,17 +1,40 @@ -"""设置页的事件绑定。 +"""设置页的事件绑定和当前客户端设备号生成。 -本文件把界面操作转换为轻量信号,不直接执行 ADB、SQLite 或硬件信息读取。 +本文件把界面操作转换为轻量信号,不直接执行 ADB 或 SQLite。 后续应用服务应在后台线程处理阻塞操作,再通过页面更新方法返回结果。 """ +import hashlib +import platform +import uuid + from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot +DEVICE_ID_PLACEHOLDER = "待生成" + + +def generate_client_device_id() -> str: + """根据本机特征生成设备号,不暴露原始系统和硬件信息。""" + + fingerprint = "|".join( + ( + platform.system(), + platform.node(), + platform.machine(), + f"{uuid.getnode():012x}", + ) + ) + digest = hashlib.sha256(fingerprint.encode("utf-8")).hexdigest()[:16].upper() + return f"CLIENT-{digest}" + + class SettingsPageEventBinder(QObject): """绑定设备管理控件,并向应用层发出稳定事件。""" searchRequested = pyqtSignal() connectRequested = pyqtSignal(str) + currentDeviceSaveRequested = pyqtSignal(str, str) saveRequested = pyqtSignal(str, str) deleteRequested = pyqtSignal(str) @@ -20,6 +43,9 @@ class SettingsPageEventBinder(QObject): self._page = page self._busy = False + page.currentDeviceSaveButton.clicked.connect( + self._request_save_current_device + ) page.searchButton.clicked.connect(self._request_search) page.connectButton.clicked.connect(self._request_connect) page.saveButton.clicked.connect(self._request_save) @@ -28,6 +54,20 @@ class SettingsPageEventBinder(QObject): page.deviceTableModel.checkedDeviceChanged.connect(self._sync_button_state) self._sync_button_state() + @pyqtSlot() + def _request_save_current_device(self) -> None: + if self._busy: + return + + device_id = self._page.deviceIdInput.text().strip() + if not device_id or device_id == DEVICE_ID_PLACEHOLDER: + device_id = generate_client_device_id() + self._page.deviceIdInput.setText(device_id) + + device_name = self._page.deviceNameInput.text().strip() + self._page.deviceNameInput.setText(device_name) + self.currentDeviceSaveRequested.emit(device_id, device_name) + @pyqtSlot() def _request_search(self) -> None: if self._busy: @@ -78,6 +118,7 @@ class SettingsPageEventBinder(QObject): def _sync_button_state(self, *_args) -> None: serial = self._page.deviceTableModel.checked_serial has_address = bool(self._page.addressInput.text().strip()) + self._page.currentDeviceSaveButton.setEnabled(not self._busy) self._page.searchButton.setEnabled(not self._busy) self._page.connectButton.setEnabled(not self._busy and has_address) self._page.saveButton.setEnabled(not self._busy and bool(serial))