diff --git a/resource/OneKeyLogDiag_v2.ui b/resource/OneKeyLogDiag_v2.ui new file mode 100644 index 0000000..6a28a90 --- /dev/null +++ b/resource/OneKeyLogDiag_v2.ui @@ -0,0 +1,137 @@ + + + MainWindow + + + + 0 + 0 + 1139 + 667 + + + + OneKeyLogDiag + + + + + + + 0 + + + + 控制台 + + + + + + 目标项目 + + + + + + + + + + + + + + 基本信息 + + + + + + + + + + 关键告警 + + + + + 温度信息 + + + + + + + + + + + + + 事件时间线 + + + + + 日志查看 + + + + + + + + + + + + + + + + + + 0 + 0 + 1139 + 21 + + + + + 文件 + + + + + + 管理 + + + + + + + + + + + 打开 + + + + + 清理缓存 + + + + + 清理日志 + + + + + + diff --git a/src/app/main.py b/src/app/main.py index 18f3a41..4f9b374 100644 --- a/src/app/main.py +++ b/src/app/main.py @@ -1,11 +1,31 @@ import os, sys +from PyQt6.QtWidgets import QApplication sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from common.app_logger import record_log from common.cache_mgmt import app_cache_create +from frontend.main_window import MainWindow + if __name__ == "__main__": + # Windows系统特定设置,确保任务栏图标正确显示 + try: + from ctypes import windll + myappid = 'common.onekeydiag.2.0' # 自定义唯一ID + windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid) + except ImportError: + pass # 非Windows系统忽略 + # Project Entry app_cache_create() record_log("INFO", "Start App") + + # 创建PyQt应用实例 + app = QApplication(sys.argv) + + # 初始化并显示主窗口 + window = MainWindow() + window.show() + # 进入应用主循环 + sys.exit(app.exec()) \ No newline at end of file diff --git a/src/backend/.gitignore b/src/backend/.gitignore index 7070e9f..15bd602 100644 --- a/src/backend/.gitignore +++ b/src/backend/.gitignore @@ -1,2 +1,4 @@ +__pycache__/ + # 外网开源, 项目级敏感代码忽略 proj_ZiJin/ \ No newline at end of file diff --git a/src/backend/__init__.py b/src/backend/__init__.py index c840b67..fdc36aa 100644 --- a/src/backend/__init__.py +++ b/src/backend/__init__.py @@ -1,6 +1,18 @@ from .back_service import ( get_all_proj_name, + get_project_temperature_list, + get_project_logname_list, do_proj_parse ) -__all__ = [ get_all_proj_name, do_proj_parse ] \ No newline at end of file +from .back_service import ( + AppService +) + +__all__ = [ + get_all_proj_name, + get_project_temperature_list, + get_project_logname_list, + do_proj_parse +] +__all__ += [AppService] \ No newline at end of file diff --git a/src/backend/back_service.py b/src/backend/back_service.py index 76f9c2c..86b14f2 100644 --- a/src/backend/back_service.py +++ b/src/backend/back_service.py @@ -1,6 +1,10 @@ import os import importlib +class AppService: + def __init__(self): + self.parseStatus = False + def get_all_proj_dir(): proj_dirs = [] # 1.Search proj from src @@ -62,15 +66,35 @@ def dynamic_import_lib(pacakge_name): try: # 动态导入模块 module = importlib.import_module(package_path) - print(f"成功导入模块: {package_path}") + # print(f"成功导入模块: {package_path}") return module except ImportError: - print(f"无法导入模块: {package_path}") + # print(f"无法导入模块: {package_path}") return None except Exception as e: print(f"导入模块时发生错误: {e}") return None +def get_project_temperature_list(key): + porj_package = "proj_" + key + result = [] + + pHandlers = dynamic_import_lib(porj_package) + if hasattr(pHandlers, "get_temperature_list"): + result = pHandlers.get_temperature_list() + + return result + +def get_project_logname_list(key): + porj_package = "proj_" + key + result = [] + + pHandlers = dynamic_import_lib(porj_package) + if hasattr(pHandlers, "get_logname_list"): + result = pHandlers.get_logname_list() + + return result + def do_proj_parse(key="app"): porj_package = "proj_" + key diff --git a/src/backend/proj_app/.gitignore b/src/backend/proj_app/.gitignore new file mode 100644 index 0000000..ba0430d --- /dev/null +++ b/src/backend/proj_app/.gitignore @@ -0,0 +1 @@ +__pycache__/ \ No newline at end of file diff --git a/src/backend/proj_app/__init__.py b/src/backend/proj_app/__init__.py index 4cff789..bbbba3c 100644 --- a/src/backend/proj_app/__init__.py +++ b/src/backend/proj_app/__init__.py @@ -2,4 +2,14 @@ from .service_app import ( start_parse ) -__all__ = [ start_parse ] \ No newline at end of file +from .app_temperature import ( + get_temperature_list +) + +from .app_logparse import ( + get_logname_list +) + +__all__ = [ start_parse ] +__all__ += [ get_temperature_list ] +__all__ += [ get_logname_list ] diff --git a/src/backend/proj_app/app_logparse.py b/src/backend/proj_app/app_logparse.py new file mode 100644 index 0000000..b54c7d0 --- /dev/null +++ b/src/backend/proj_app/app_logparse.py @@ -0,0 +1,4 @@ +app_logname_list = ["sel.log", "audit.log"] + +def get_logname_list(): + return app_logname_list \ No newline at end of file diff --git a/src/backend/proj_app/app_temperature.py b/src/backend/proj_app/app_temperature.py new file mode 100644 index 0000000..7e0946f --- /dev/null +++ b/src/backend/proj_app/app_temperature.py @@ -0,0 +1,5 @@ + +app_temperature_list = [ "CPU_Temp", "Mempry_Temp" ] + +def get_temperature_list(): + return app_temperature_list \ No newline at end of file diff --git a/src/common/__init__.py b/src/common/__init__.py index 0a9e36b..2548c29 100644 --- a/src/common/__init__.py +++ b/src/common/__init__.py @@ -13,6 +13,11 @@ from .file_tool import( get_user_appdata_path ) +from .cache_mgmt import( + clean_app_cache, + clean_running_log +) + # From ._globals __all__ = [ cache_dir, source_dir ] @@ -20,4 +25,7 @@ __all__ = [ cache_dir, source_dir ] __all__ += [ record_log ] # From .file_tool -__all__ += [ force_empty_folder, add_to_json_array, get_user_appdata_path ] \ No newline at end of file +__all__ += [ force_empty_folder, add_to_json_array, get_user_appdata_path ] + +# From .cache_mgmt +__all__ += [ clean_app_cache, clean_running_log] \ No newline at end of file diff --git a/src/common/app_logger.py b/src/common/app_logger.py index 280e368..65d358b 100644 --- a/src/common/app_logger.py +++ b/src/common/app_logger.py @@ -3,7 +3,7 @@ import time from . import cache_dir -LOG_FILE = os.path.join(cache_dir, "running.log") +LOG_FILE = os.path.join(cache_dir, "apprunning.log") def record_log(log_level, log_description): """ diff --git a/src/common/cache_mgmt.py b/src/common/cache_mgmt.py index f78bb2a..685bb8d 100644 --- a/src/common/cache_mgmt.py +++ b/src/common/cache_mgmt.py @@ -48,7 +48,7 @@ def clean_app_cache(): force_empty_folder(cache_dir) def clean_running_log(): - LOG_FILE = os.path.join(cache_dir, "running.log") + LOG_FILE = os.path.join(cache_dir, "apprunning.log") if os.path.exists(LOG_FILE): os.remove(LOG_FILE) \ No newline at end of file diff --git a/src/frontend/.gitignore b/src/frontend/.gitignore new file mode 100644 index 0000000..ba0430d --- /dev/null +++ b/src/frontend/.gitignore @@ -0,0 +1 @@ +__pycache__/ \ No newline at end of file diff --git a/src/frontend/__init__.py b/src/frontend/__init__.py index e69de29..42a8095 100644 --- a/src/frontend/__init__.py +++ b/src/frontend/__init__.py @@ -0,0 +1,4 @@ +from .main_window import MainWindow + +__all__ = [ MainWindow] + diff --git a/src/frontend/event_handler.py b/src/frontend/event_handler.py new file mode 100644 index 0000000..f3af934 --- /dev/null +++ b/src/frontend/event_handler.py @@ -0,0 +1,54 @@ +from common import record_log + +class EventHandler: + def __init__(self, main_window): + self.main_window = main_window # 持有主窗口引用 + + def bind_event(self): + record_log("INFO", "Start Bind Event") + # 菜单项事件绑定 + self.main_window.action_cleanCache.triggered.connect(self.on_click_clean_cache) + self.main_window.action_cleanLog.triggered.connect(self.on_click_clean_running_log) + + # 下拉项事件绑定 + self.main_window.comboBox_proj_select.currentTextChanged.connect(self.on_combo_project_changed) + + def on_combo_project_changed(self, select_text): + from backend import ( + get_project_temperature_list, + get_project_logname_list) + + temperature_list = get_project_temperature_list(select_text) + temperature_count = len(temperature_list) + logname_list = get_project_logname_list(select_text) + logname_count = len(logname_list) + + self.main_window.comboBox_temperature.clear() + self.main_window.comboBox_logreader.clear() + + if temperature_count > 0: + self.main_window.comboBox_temperature.addItems(temperature_list) + else: + record_log("WARNING", f"Project:{select_text} | No temperature list found") + record_log("INFO", "Please check if there has 'get_temperature_list' in plugin") + + if logname_count > 0: + self.main_window.comboBox_logreader.addItems(logname_list) + else: + record_log("WARNING", f"Project:{select_text} | No log name list found") + record_log("INFO", "Please check if there has 'get_logname_list' in plugin") + + def on_click_clean_running_log(self): + from common import clean_running_log + self.main_window.textEdit_console.append("系统信息: Clean apprunning.log") + clean_running_log() + + def on_click_clean_cache(self): + from common import clean_app_cache + self.main_window.textEdit_console.append("系统信息: Clean all app cache") + clean_app_cache() + + + + + \ No newline at end of file diff --git a/src/frontend/file_processor.py b/src/frontend/file_processor.py new file mode 100644 index 0000000..dd3899d --- /dev/null +++ b/src/frontend/file_processor.py @@ -0,0 +1,3 @@ +class FileProcessor: + def __init__(self, main_window): + self.main_window = main_window \ No newline at end of file diff --git a/src/frontend/main_window.py b/src/frontend/main_window.py new file mode 100644 index 0000000..293e834 --- /dev/null +++ b/src/frontend/main_window.py @@ -0,0 +1,44 @@ +from PyQt6.QtCore import Qt +from PyQt6.QtWidgets import QMainWindow, QWidget + +# Import From local source +from .onekeydiag_ui import Ui_MainWindow +from .ui_initializer import UIInitializer +from .event_handler import EventHandler +from .view_render import ViewRenderer +from .file_processor import FileProcessor + +from backend import AppService +from common import record_log + +class MainWindow(QMainWindow, Ui_MainWindow): + def __init__(self): + super().__init__() + # 1. 初始化UI界面 + self.setupUi(self) + # 2. 初始化服务状态 + self.serviceStatus = AppService() + + # 3. 初始化各功能模块(注入主窗口实例) + self.ui_init = UIInitializer(self) + self.file_processor = FileProcessor(self) + self.view_renderer = ViewRenderer(self) + self.event_handler = EventHandler(self) + + # 4. 执行各模块初始化逻辑 + self.local_init_module() + + def local_init_module(self): + record_log("INFO", "Start init UI") + + # UI_Initializer + self.ui_init.enable_window_dragEvent() + self.ui_init.init_comboBox_project_select() + self.ui_init.init_comboBox_temperature_select() + self.ui_init.init_comboBox_logreader_select() + self.ui_init.init_textEdit_console_style() + self.ui_init.init_textBrowser_baseinfo_style() + self.ui_init.init_textBrowser_logreader_style() + + # Event_Handler + self.event_handler.bind_event() \ No newline at end of file diff --git a/src/frontend/onekeydiag_ui.py b/src/frontend/onekeydiag_ui.py index e69de29..b5ddcbf 100644 --- a/src/frontend/onekeydiag_ui.py +++ b/src/frontend/onekeydiag_ui.py @@ -0,0 +1,115 @@ +# Form implementation generated from reading ui file 'resource\OneKeyLogDiag_v2.ui' +# +# Created by: PyQt6 UI code generator 6.4.2 +# +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt6 import QtCore, QtGui, QtWidgets + + +class Ui_MainWindow(object): + def setupUi(self, MainWindow): + MainWindow.setObjectName("MainWindow") + MainWindow.resize(1139, 667) + self.centralwidget = QtWidgets.QWidget(parent=MainWindow) + self.centralwidget.setObjectName("centralwidget") + self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget) + self.horizontalLayout.setObjectName("horizontalLayout") + self.tabWidget = QtWidgets.QTabWidget(parent=self.centralwidget) + self.tabWidget.setObjectName("tabWidget") + self.tab_console = QtWidgets.QWidget() + self.tab_console.setObjectName("tab_console") + self.verticalLayout_4 = QtWidgets.QVBoxLayout(self.tab_console) + self.verticalLayout_4.setObjectName("verticalLayout_4") + self.label_proj_name = QtWidgets.QLabel(parent=self.tab_console) + self.label_proj_name.setObjectName("label_proj_name") + self.verticalLayout_4.addWidget(self.label_proj_name) + self.comboBox_proj_select = QtWidgets.QComboBox(parent=self.tab_console) + self.comboBox_proj_select.setObjectName("comboBox_proj_select") + self.verticalLayout_4.addWidget(self.comboBox_proj_select) + self.textEdit_console = QtWidgets.QTextEdit(parent=self.tab_console) + self.textEdit_console.setObjectName("textEdit_console") + self.verticalLayout_4.addWidget(self.textEdit_console) + self.tabWidget.addTab(self.tab_console, "") + self.tab_baseinfo = QtWidgets.QWidget() + self.tab_baseinfo.setObjectName("tab_baseinfo") + self.verticalLayout_3 = QtWidgets.QVBoxLayout(self.tab_baseinfo) + self.verticalLayout_3.setObjectName("verticalLayout_3") + self.textBrowser_baseinfo = QtWidgets.QTextBrowser(parent=self.tab_baseinfo) + self.textBrowser_baseinfo.setObjectName("textBrowser_baseinfo") + self.verticalLayout_3.addWidget(self.textBrowser_baseinfo) + self.tabWidget.addTab(self.tab_baseinfo, "") + self.tab_alert = QtWidgets.QWidget() + self.tab_alert.setObjectName("tab_alert") + self.tabWidget.addTab(self.tab_alert, "") + self.tab_temperature = QtWidgets.QWidget() + self.tab_temperature.setObjectName("tab_temperature") + self.verticalLayout = QtWidgets.QVBoxLayout(self.tab_temperature) + self.verticalLayout.setObjectName("verticalLayout") + self.comboBox_temperature = QtWidgets.QComboBox(parent=self.tab_temperature) + self.comboBox_temperature.setObjectName("comboBox_temperature") + self.verticalLayout.addWidget(self.comboBox_temperature) + self.graphicsView_temperature = QtWidgets.QGraphicsView(parent=self.tab_temperature) + self.graphicsView_temperature.setObjectName("graphicsView_temperature") + self.verticalLayout.addWidget(self.graphicsView_temperature) + self.tabWidget.addTab(self.tab_temperature, "") + self.tab_timeline = QtWidgets.QWidget() + self.tab_timeline.setObjectName("tab_timeline") + self.tabWidget.addTab(self.tab_timeline, "") + self.tab_logreader = QtWidgets.QWidget() + self.tab_logreader.setObjectName("tab_logreader") + self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.tab_logreader) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.comboBox_logreader = QtWidgets.QComboBox(parent=self.tab_logreader) + self.comboBox_logreader.setObjectName("comboBox_logreader") + self.verticalLayout_2.addWidget(self.comboBox_logreader) + self.textBrowser_logreader = QtWidgets.QTextBrowser(parent=self.tab_logreader) + self.textBrowser_logreader.setObjectName("textBrowser_logreader") + self.verticalLayout_2.addWidget(self.textBrowser_logreader) + self.tabWidget.addTab(self.tab_logreader, "") + self.horizontalLayout.addWidget(self.tabWidget) + MainWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(parent=MainWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 1139, 21)) + self.menubar.setObjectName("menubar") + self.menu_file = QtWidgets.QMenu(parent=self.menubar) + self.menu_file.setObjectName("menu_file") + self.menu_mgmt = QtWidgets.QMenu(parent=self.menubar) + self.menu_mgmt.setObjectName("menu_mgmt") + MainWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(parent=MainWindow) + self.statusbar.setObjectName("statusbar") + MainWindow.setStatusBar(self.statusbar) + self.action_uploadFile = QtGui.QAction(parent=MainWindow) + self.action_uploadFile.setObjectName("action_uploadFile") + self.action_cleanCache = QtGui.QAction(parent=MainWindow) + self.action_cleanCache.setObjectName("action_cleanCache") + self.action_cleanLog = QtGui.QAction(parent=MainWindow) + self.action_cleanLog.setObjectName("action_cleanLog") + self.menu_file.addAction(self.action_uploadFile) + self.menu_mgmt.addAction(self.action_cleanCache) + self.menu_mgmt.addAction(self.action_cleanLog) + self.menubar.addAction(self.menu_file.menuAction()) + self.menubar.addAction(self.menu_mgmt.menuAction()) + + self.retranslateUi(MainWindow) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(MainWindow) + + def retranslateUi(self, MainWindow): + _translate = QtCore.QCoreApplication.translate + MainWindow.setWindowTitle(_translate("MainWindow", "OneKeyLogDiag")) + self.label_proj_name.setText(_translate("MainWindow", "目标项目")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_console), _translate("MainWindow", "控制台")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_baseinfo), _translate("MainWindow", "基本信息")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_alert), _translate("MainWindow", "关键告警")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_temperature), _translate("MainWindow", "温度信息")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_timeline), _translate("MainWindow", "事件时间线")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_logreader), _translate("MainWindow", "日志查看")) + self.menu_file.setTitle(_translate("MainWindow", "文件")) + self.menu_mgmt.setTitle(_translate("MainWindow", "管理")) + self.action_uploadFile.setText(_translate("MainWindow", "打开")) + self.action_cleanCache.setText(_translate("MainWindow", "清理缓存")) + self.action_cleanLog.setText(_translate("MainWindow", "清理日志")) diff --git a/src/frontend/ui_initializer.py b/src/frontend/ui_initializer.py new file mode 100644 index 0000000..e2f54bb --- /dev/null +++ b/src/frontend/ui_initializer.py @@ -0,0 +1,80 @@ +from common import record_log + +class UIInitializer: + def __init__(self, main_window): + self.main_window = main_window # 持有主窗口引用 + + def enable_window_dragEvent(self): + self.main_window.setAcceptDrops(True) + + def init_comboBox_project_select(self): + from backend import get_all_proj_name + project_list = get_all_proj_name() + project_count = len(project_list) + + self.main_window.comboBox_proj_select.clear() + if project_count > 0: + self.main_window.comboBox_proj_select.addItems(project_list) + + def init_comboBox_temperature_select(self): + current_project_key = self.main_window.comboBox_proj_select.currentText() + from backend import get_project_temperature_list + + temperature_list = get_project_temperature_list(current_project_key) + temperature_count = len(temperature_list) + + self.main_window.comboBox_temperature.clear() + if temperature_count > 0: + self.main_window.comboBox_temperature.addItems(temperature_list) + + def init_comboBox_logreader_select(self): + current_project_key = self.main_window.comboBox_proj_select.currentText() + from backend import get_project_logname_list + + logname_list = get_project_logname_list(current_project_key) + logname_count = len(logname_list) + + self.main_window.comboBox_logreader.clear() + if logname_count > 0: + self.main_window.comboBox_logreader.addItems(logname_list) + + def init_textEdit_console_style(self): + # self.main_window.textEdit_console.setStyleSheet(""" + # QTextBrowser { + # font-family: 'SimHei'; + # font-size: 20px; + # color: #2c3e50; + # background-color: #f8f9fa; + # border: 1px solid #ddd; + # border-radius: 4px; + # padding: 8px; + # } + # """) + pass + + def init_textBrowser_baseinfo_style(self): + self.main_window.textBrowser_baseinfo.setStyleSheet(""" + QTextEdit { + font-family: 'SimHei'; + font-size: 24px; + color: #2c3e50; + background-color: #f8f9fa; + border: 1px solid #ddd; + border-radius: 4px; + padding: 8px; + } + """) + + def init_textBrowser_logreader_style(self): + self.main_window.textBrowser_logreader.setStyleSheet(""" + QTextBrowser { + font-family: 'Consola'; + font-size: 18px; + color: #2c3e50; + background-color: #f8f9fa; + border: 1px solid #ddd; + border-radius: 4px; + padding: 8px; + } + """) + \ No newline at end of file diff --git a/src/frontend/view_render.py b/src/frontend/view_render.py new file mode 100644 index 0000000..fc8445a --- /dev/null +++ b/src/frontend/view_render.py @@ -0,0 +1,5 @@ +class ViewRenderer: + """视图渲染模块:负责图片显示、表格数据填充等UI渲染逻辑""" + def __init__(self, main_window): + # 持有主窗口引用,用于访问UI组件(如graphicsView、model_alert) + self.main_window = main_window \ No newline at end of file