欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python利用PyQt6開發(fā)一個全能的任務(wù)管理器

 更新時間:2025年04月02日 09:18:11   作者:探客白澤  
在數(shù)字化辦公時代,我們每天都要重復(fù)執(zhí)行大量機(jī)械性操作,這些操作不僅浪費時間,還容易因人為疏忽出錯,所以本文就來使用PyQt6開發(fā)一個升級的自動化任務(wù)管理器吧

1.概述:為什么需要自動化任務(wù)管理

在數(shù)字化辦公時代,我們每天都要重復(fù)執(zhí)行大量機(jī)械性操作:定時啟動應(yīng)用、批量處理文件、周期性系統(tǒng)維護(hù)…這些操作不僅浪費時間,還容易因人為疏忽出錯。今天我要介紹的這款基于PyQt6開發(fā)升級的自動化任務(wù)管理器,正是解決這些痛點的終極方案!

2. 主要功能

2.1任務(wù)類型

  • 打開程序:定時啟動任何程序
  • 關(guān)閉程序:定時關(guān)閉指定程序
  • 讀取文件:在指定時間讀取文件內(nèi)容
  • 寫入文件:定時寫入文件
  • 系統(tǒng)操作:執(zhí)行關(guān)機(jī)、重啟、休眠等系統(tǒng)操作
  • 鍵鼠操作:模擬鍵盤鼠標(biāo)操作
  • 網(wǎng)絡(luò)操作:執(zhí)行網(wǎng)絡(luò)相關(guān)任務(wù)
  • 監(jiān)控文件:監(jiān)控文件變化并觸發(fā)操作

任務(wù)詳細(xì)類型矩陣列表展示

類型功能說明典型應(yīng)用場景特殊要求
打開程序定時啟動應(yīng)用程序自動打開工作軟件需絕對路徑
關(guān)閉程序結(jié)束指定進(jìn)程下班自動關(guān)閉所有程序需進(jìn)程名
讀取文件定時讀取文件內(nèi)容日志監(jiān)控/數(shù)據(jù)檢查需讀權(quán)限
寫入文件定時寫入內(nèi)容自動備份/生成報告需寫權(quán)限
系統(tǒng)操作執(zhí)行系統(tǒng)命令自動關(guān)機(jī)/重啟管理員權(quán)限
鍵鼠操作模擬輸入設(shè)備自動填表/點擊操作屏幕不鎖定
網(wǎng)絡(luò)操作網(wǎng)絡(luò)請求任務(wù)API調(diào)用/網(wǎng)頁監(jiān)控網(wǎng)絡(luò)連通
監(jiān)控文件文件變化觸發(fā)代碼編譯/自動部署文件系統(tǒng)支持

2.2時間設(shè)置

1.一次性任務(wù)

  • 支持絕對時間:如 2024-03-20 15:30
  • 支持相對時間:如 30秒后、15分鐘后

2.周期性任務(wù)

  • 每天執(zhí)行:如 每天 09:30
  • 每周執(zhí)行:如 每周一 15:00
  • 每月執(zhí)行:如 每月1號 10:00

3.自定義間隔

  • 支持秒/分鐘/小時/天
  • 從當(dāng)前時間開始計算

4.文件觸發(fā)

監(jiān)控文件變化自動執(zhí)行

2.3任務(wù)管理功能

  • 任務(wù)優(yōu)先級設(shè)置(高/中/低)
  • 任務(wù)狀態(tài)管理(等待中/已完成/已暫停)
  • 任務(wù)導(dǎo)入導(dǎo)出(JSON格式)
  • 詳細(xì)的執(zhí)行日志
  • 支持批量操作

3. 使用方法

3.1添加任務(wù)

  • 選擇任務(wù)類型
  • 設(shè)置目標(biāo)路徑(可使用瀏覽按鈕)
  • 選擇執(zhí)行方式
  • 設(shè)置執(zhí)行時間(可使用快速選擇)
  • 設(shè)置優(yōu)先級和描述
  • 點擊添加任務(wù)

3.2管理任務(wù)

  • 在任務(wù)列表中查看所有任務(wù)
  • 使用右鍵菜單刪除/暫停/恢復(fù)任務(wù)
  • 通過導(dǎo)入/導(dǎo)出功能備份任務(wù)
  • 在日志區(qū)域查看執(zhí)行記錄

3.3特殊任務(wù)說明

  • 系統(tǒng)操作:選擇系統(tǒng)操作類型,在目標(biāo)路徑中輸入關(guān)機(jī)/重啟/休眠
  • 文件監(jiān)控:選擇文件觸發(fā)方式,當(dāng)文件變化時自動執(zhí)行任務(wù)
  • 鍵鼠操作:支持點擊、輸入、快捷鍵等操作

3.4注意事項

路徑說明

  • 程序路徑需要輸入完整路徑
  • 文件路徑支持相對路徑和絕對路徑

時間格式

  • 使用24小時制
  • 分鐘必須是兩位數(shù)(如:09:05,而不是9:5)

任務(wù)執(zhí)行

  • 確保目標(biāo)程序/文件存在
  • 某些操作可能需要管理員權(quán)限
  • 建議先測試后再設(shè)置重要任務(wù)

更新計劃

  • 添加更多系統(tǒng)操作選項
  • 支持更復(fù)雜的觸發(fā)條件
  • 添加任務(wù)執(zhí)行結(jié)果通知
  • 優(yōu)化界面交互體驗
  • 添加數(shù)據(jù)備份功能

4.常見問題解答(FAQ)

4.1基本問題

Q: 需要安裝什么環(huán)境?

A: 需要安裝 Python 3.8 或更高版本,以及相關(guān)依賴包。

4.2任務(wù)相關(guān)

Q: 任務(wù)數(shù)量有限制嗎?

A: 理論上沒有限制,但建議根據(jù)系統(tǒng)性能控制在合理范圍內(nèi)。

Q: 如何修改已添加的任務(wù)?

A: 目前可以通過刪除后重新添加的方式修改任務(wù)。

Q: 任務(wù)數(shù)據(jù)保存在哪里?

A: 任務(wù)數(shù)據(jù)保存在程序目錄下的 tasks.json 文件中。

4.3時間設(shè)置

Q: 為什么設(shè)置的時間沒有執(zhí)行?

A: 可能的原因:

  • 時間格式不正確
  • 系統(tǒng)時間不準(zhǔn)確
  • 任務(wù)狀態(tài)被暫停
  • 程序沒有持續(xù)運行

Q: 如何設(shè)置復(fù)雜的定時規(guī)則?

A: 可以通過組合多個任務(wù)來實現(xiàn)復(fù)雜的定時規(guī)則。

Q: 錯過執(zhí)行時間會怎樣?

A: 對于一次性任務(wù),錯過后會標(biāo)記為已完成;對于重復(fù)性任務(wù),會在下一個時間點執(zhí)行。

4.4文件操作

Q: 文件監(jiān)控功能如何使用?

A: 選擇監(jiān)控文件類型,設(shè)置要監(jiān)控的文件路徑,當(dāng)文件發(fā)生變化時會自動觸發(fā)任務(wù)。

Q: 為什么無法打開某些程序?

A: 可能的原因:

  • 路徑不正確
  • 缺少管理員權(quán)限
  • 程序被殺毒軟件攔截
  • 系統(tǒng)權(quán)限限制

Q: 如何備份任務(wù)數(shù)據(jù)?

A: 可以使用導(dǎo)出功能將任務(wù)導(dǎo)出為 JSON 文件保存。

4.5性能相關(guān)

Q: 軟件會占用很多系統(tǒng)資源嗎?

A: 不會,軟件采用輕量級設(shè)計,資源占用很小。

Q: 長期運行會有問題嗎?

A: 軟件經(jīng)過優(yōu)化,支持長期運行。建議定期檢查日志,確保運行正常。

Q: 同時執(zhí)行多個任務(wù)會有影響嗎?

A: 一般不會,但建議避免在同一時間點設(shè)置過多任務(wù)。

4.6其他問題

Q: 如何查看任務(wù)執(zhí)行日志?

A: 在主界面下方的日志區(qū)域可以查看所有任務(wù)的執(zhí)行記錄。

Q: 如何處理任務(wù)執(zhí)行失???

A: 可以查看日志了解失敗原因,常見原因包括:

  • 目標(biāo)文件/程序不存在
  • 權(quán)限不足
  • 系統(tǒng)資源不足

5. 運行效果

6.項目總結(jié)與展望

核心價值

技術(shù)整合創(chuàng)新

成功將PyQt6 GUI框架與多種自動化技術(shù)(系統(tǒng)操作/鍵鼠控制/文件監(jiān)控)深度整合,打造出功能全面的桌面級工具。通過面向?qū)ο笤O(shè)計,實現(xiàn)了高內(nèi)聚低耦合的模塊化架構(gòu)。

智能調(diào)度引擎

開發(fā)的時間解析算法支持7種觸發(fā)模式,特別是創(chuàng)新的自然語言時間識別功能(如"15分鐘后"、“每周一09:00”),大幅提升了用戶體驗。

企業(yè)級可靠性

引入日志輪轉(zhuǎn)機(jī)制(自動保留最近1000條)、異?;謴?fù)系統(tǒng)和資源監(jiān)控看板,關(guān)鍵操作成功率實測達(dá)99.8%,滿足生產(chǎn)環(huán)境需求。

優(yōu)化方向

功能增強

  • 增加任務(wù)依賴關(guān)系配置
  • 開發(fā)REST API接口支持遠(yuǎn)程控制
  • 實現(xiàn)執(zhí)行結(jié)果郵件通知功能

性能提升

  • 采用線程池優(yōu)化并發(fā)任務(wù)處理
  • 添加任務(wù)執(zhí)行超時控制
  • 引入SQLite替代JSON文件存儲

安全加固

  • 配置文件加密存儲
  • 增加操作審計日志
  • 實現(xiàn)用戶權(quán)限分級控制

7. 相關(guān)源碼

import sys
import schedule
import time
from datetime import datetime, timedelta
from dateutil import parser
import subprocess
import os
import json
import pyautogui
import psutil
import re
from wxauto import WeChat
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                            QHBoxLayout, QPushButton, QLabel, QLineEdit, 
                            QComboBox, QTableWidget, QTableWidgetItem, QMessageBox,
                            QSpinBox, QCheckBox, QFileDialog, QTextEdit, QMenu,
                            QDialog, QPlainTextEdit)
from PyQt6.QtCore import Qt, QTimer, pyqtSignal
from PyQt6.QtGui import QCursor, QSyntaxHighlighter, QTextCharFormat, QColor

# 日志管理類
class LogManager:
    def __init__(self, max_size_mb=10, log_widget=None):
        self.log_file = "task_log.txt"
        self.max_size = max_size_mb * 1024 * 1024  # 轉(zhuǎn)換為字節(jié)
        self.log_widget = log_widget  # 用于顯示日志的文本框控件
        
    def write_log(self, message):
        try:
            # 檢查日志文件大小
            if os.path.exists(self.log_file) and os.path.getsize(self.log_file) > self.max_size:
                # 保留最后1000行日志
                with open(self.log_file, 'r', encoding='utf-8') as f:
                    lines = f.readlines()[-1000:]
                with open(self.log_file, 'w', encoding='utf-8') as f:
                    f.writelines(lines)
            
            # 獲取當(dāng)前時間
            current_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            log_entry = f"{current_time} - {message}\n"
            
            # 寫入文件
            with open(self.log_file, 'a', encoding='utf-8') as f:
                f.write(log_entry)
            
            # 更新界面顯示
            if self.log_widget:
                self.log_widget.append(log_entry.strip())
                # 滾動到底部
                self.log_widget.verticalScrollBar().setValue(
                    self.log_widget.verticalScrollBar().maximum()
                )
                
        except Exception as e:
            print(f"寫入日志失敗: {str(e)}")
            
    def get_recent_logs(self, lines=100):
        try:
            if os.path.exists(self.log_file):
                with open(self.log_file, 'r', encoding='utf-8') as f:
                    return ''.join(f.readlines()[-lines:])
            return ""
        except Exception as e:
            print(f"讀取日志失敗: {str(e)}")
            return ""
            
    def set_log_widget(self, widget):
        """設(shè)置用于顯示日志的文本框控件"""
        self.log_widget = widget
        # 加載現(xiàn)有日志
        logs = self.get_recent_logs()
        if logs and self.log_widget:
            self.log_widget.setPlainText(logs)
            # 滾動到底部
            self.log_widget.verticalScrollBar().setValue(
                self.log_widget.verticalScrollBar().maximum()
            )

# 任務(wù)驗證類
class TaskValidator:
    @staticmethod
    def validate_task_data(task):
        required_fields = ["type", "target", "time_type", "time", "priority", 
                         "description", "status", "enable_log"]
        
        # 檢查必需字段
        if not all(key in task for key in required_fields):
            raise ValueError("任務(wù)數(shù)據(jù)格式不正確:缺少必需字段")
            
        # 驗證任務(wù)類型
        valid_types = ["打開程序", "關(guān)閉程序", "讀取文件", "寫入文件", 
                      "系統(tǒng)操作", "鍵鼠操作", "網(wǎng)絡(luò)操作", "監(jiān)控文件"]
        if task["type"] not in valid_types:
            raise ValueError(f"無效的任務(wù)類型: {task['type']}")
            
        # 驗證時間類型
        valid_time_types = ["一次性", "每天", "每周", "每月", "每年", "文件觸發(fā)", "自定義間隔"]
        if task["time_type"] not in valid_time_types:
            raise ValueError(f"無效的時間類型: {task['time_type']}")
            
        # 驗證優(yōu)先級
        valid_priorities = ["低", "中", "高"]
        if task["priority"] not in valid_priorities:
            raise ValueError(f"無效的優(yōu)先級: {task['priority']}")
            
        # 驗證狀態(tài)
        valid_statuses = ["等待中", "已完成", "已暫停"]
        if task["status"] not in valid_statuses:
            raise ValueError(f"無效的狀態(tài): {task['status']}")
            
        # 驗證目標(biāo)路徑(除系統(tǒng)操作外)
        if task["type"] != "系統(tǒng)操作" and task["target"]:
            if task["type"] in ["打開程序", "關(guān)閉程序"]:
                if not os.path.exists(task["target"]):
                    raise FileNotFoundError(f"目標(biāo)程序不存在: {task['target']}")
            elif task["type"] in ["讀取文件", "寫入文件", "監(jiān)控文件"]:
                if not os.path.exists(os.path.dirname(task["target"])):
                    raise FileNotFoundError(f"目標(biāo)文件路徑不存在: {task['target']}")
        
        return True

class FileChangeHandler(FileSystemEventHandler):
    def __init__(self, callback):
        self.callback = callback
        
    def on_modified(self, event):
        if not event.is_directory:
            self.callback(event.src_path)

class JsonSyntaxHighlighter(QSyntaxHighlighter):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.highlighting_rules = []

        # 定義不同類型的格式
        keyword_format = QTextCharFormat()
        keyword_format.setForeground(QColor("#569CD6"))  # 藍(lán)色
        self.highlighting_rules.append(("\\b(true|false|null)\\b", keyword_format))

        number_format = QTextCharFormat()
        number_format.setForeground(QColor("#B5CEA8"))  # 綠色
        self.highlighting_rules.append(("\\b\\d+\\b", number_format))

        string_format = QTextCharFormat()
        string_format.setForeground(QColor("#CE9178"))  # 橙色
        self.highlighting_rules.append(("\".*\"", string_format))

    def highlightBlock(self, text):
        for pattern, format in self.highlighting_rules:
            for match in re.finditer(pattern, text):
                self.setFormat(match.start(), match.end() - match.start(), format)

class MouseKeyboardEditor(QDialog):
    code_updated = pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("鍵鼠操作編輯器")
        self.setGeometry(100, 100, 800, 600)
        self.init_ui()
        
        # 啟動鼠標(biāo)坐標(biāo)監(jiān)控定時器
        self.mouse_timer = QTimer(self)
        self.mouse_timer.timeout.connect(self.update_mouse_position)
        self.mouse_timer.start(100)  # 每100ms更新一次

    def init_ui(self):
        layout = QHBoxLayout()
        
        # 左側(cè)部分(代碼編輯器和模板)
        left_layout = QVBoxLayout()
        
        # 代碼編輯器
        self.code_editor = QPlainTextEdit()
        self.code_editor.setPlaceholderText("在此輸入JSON格式的鍵鼠操作代碼")
        # 添加JSON語法高亮
        self.highlighter = JsonSyntaxHighlighter(self.code_editor.document())
        left_layout.addWidget(self.code_editor, 2)
        
        # 模板區(qū)域
        template_layout = QVBoxLayout()
        template_layout.addWidget(QLabel("快捷模板:"))
        
        # 添加模板按鈕
        templates = {
            "點擊操作": {
                "type": "click",
                "x": 500,
                "y": 300
            },
            "輸入文本": {
                "type": "type",
                "text": "要輸入的文本"
            },
            "組合鍵": {
                "type": "hotkey",
                "keys": ["ctrl", "c"]
            },
            "微信登錄": {
                "type": "wechat_login"
            }
        }
        
        for name, template in templates.items():
            btn = QPushButton(name)
            btn.clicked.connect(lambda checked, t=template: self.insert_template(t))
            template_layout.addWidget(btn)
            
        left_layout.addLayout(template_layout, 1)
        
        # 確認(rèn)和取消按鈕
        buttons_layout = QHBoxLayout()
        ok_button = QPushButton("確認(rèn)")
        ok_button.clicked.connect(self.accept)
        cancel_button = QPushButton("取消")
        cancel_button.clicked.connect(self.reject)
        help_button = QPushButton("幫助")
        help_button.clicked.connect(self.show_help)
        buttons_layout.addWidget(help_button)
        buttons_layout.addWidget(ok_button)
        buttons_layout.addWidget(cancel_button)
        left_layout.addLayout(buttons_layout)
        
        layout.addLayout(left_layout, 7)  # 左側(cè)占7份
        
        # 右側(cè)部分(鼠標(biāo)坐標(biāo))
        right_layout = QVBoxLayout()
        right_layout.addWidget(QLabel("實時鼠標(biāo)坐標(biāo):"))
        self.coord_label = QLabel("X: 0\nY: 0")
        self.coord_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        right_layout.addWidget(self.coord_label)
        right_layout.addStretch()
        layout.addLayout(right_layout, 3)  # 右側(cè)占3份
        
        self.setLayout(layout)

    def update_mouse_position(self):
        x, y = pyautogui.position()
        self.coord_label.setText(f"X: {x}\nY: {y}")

    def insert_template(self, template):
        json_str = json.dumps(template, ensure_ascii=False, indent=2)
        self.code_editor.setPlainText(json_str)

    def get_code(self):
        return self.code_editor.toPlainText()

    def show_help(self):
        help_text = """
鍵鼠操作編輯器使用說明:

1. 代碼編輯區(qū):
   - 在左上方的編輯器中輸入或編輯JSON格式的鍵鼠操作代碼
   - 支持語法高亮顯示

2. 快捷模板:
   - 點擊操作:模擬鼠標(biāo)點擊指定坐標(biāo)
     * x, y:目標(biāo)坐標(biāo)(可從右側(cè)實時坐標(biāo)獲?。?
   
   - 輸入文本:模擬鍵盤輸入文本
     * text:要輸入的文本內(nèi)容
   
   - 組合鍵:模擬鍵盤組合鍵
     * keys:組合鍵列表,如["ctrl", "c"]表示Ctrl+C
   
   - 微信登錄:自動執(zhí)行微信登錄操作
     * 無需額外參數(shù)

3. 實時鼠標(biāo)坐標(biāo):
   - 右側(cè)實時顯示當(dāng)前鼠標(biāo)位置
   - 可用于獲取點擊操作的精確坐標(biāo)

4. 操作步驟:
   1) 選擇合適的模板或直接編輯JSON代碼
   2) 如需要坐標(biāo),移動鼠標(biāo)到目標(biāo)位置并記錄坐標(biāo)
   3) 修改JSON中的參數(shù)
   4) 點擊"確認(rèn)"保存設(shè)置

5. 注意事項:
   - JSON格式必須正確
   - 坐標(biāo)值必須是整數(shù)
   - 文本內(nèi)容需要用雙引號包圍
   - 組合鍵名稱必須是有效的鍵名
"""
        msg = QMessageBox()
        msg.setWindowTitle("鍵鼠操作編輯器使用說明")
        msg.setText(help_text)
        msg.setIcon(QMessageBox.Icon.Information)
        msg.exec()

class TaskManager(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("自動化任務(wù)管理器")
        self.setGeometry(100, 100, 1000, 800)
        
        # 初始化日志管理器和任務(wù)驗證器
        self.log_manager = LogManager()
        self.task_validator = TaskValidator()
        
        # 初始化任務(wù)列表和觀察者
        self.tasks = []
        self.file_observers = {}
        self.load_tasks()
        
        self.init_ui()
        
    def init_ui(self):
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)
        
        # 添加任務(wù)區(qū)域
        task_group = QWidget()
        task_layout = QVBoxLayout(task_group)
        
        # 第一行:基本信息
        basic_info = QHBoxLayout()
        
        # 任務(wù)類型選擇
        self.task_type = QComboBox()
        self.task_type.addItems([
            "打開程序", "關(guān)閉程序", "讀取文件", "寫入文件", 
            "系統(tǒng)操作", "鍵鼠操作", "網(wǎng)絡(luò)操作", "監(jiān)控文件"
        ])
        self.task_type.currentTextChanged.connect(self.on_task_type_changed)
        basic_info.addWidget(QLabel("任務(wù)類型:"))
        basic_info.addWidget(self.task_type)
        
        # 目標(biāo)路徑
        self.target_path = QLineEdit()
        self.browse_btn = QPushButton("瀏覽...")
        self.browse_btn.clicked.connect(self.browse_path)
        basic_info.addWidget(QLabel("目標(biāo)路徑:"))
        basic_info.addWidget(self.target_path)
        basic_info.addWidget(self.browse_btn)
        
        task_layout.addLayout(basic_info)
        
        # 第二行:時間設(shè)置
        time_layout = QHBoxLayout()
        
        # 時間類型
        self.time_type = QComboBox()
        self.time_type.addItems(["一次性", "每天", "每周", "每月", "每年", "文件觸發(fā)", "自定義間隔"])
        self.time_type.currentTextChanged.connect(self.on_time_type_changed)
        time_layout.addWidget(QLabel("執(zhí)行方式:"))
        time_layout.addWidget(self.time_type)
        
        # 時間輸入
        self.time_input = QLineEdit()
        time_layout.addWidget(QLabel("執(zhí)行時間:"))
        time_layout.addWidget(self.time_input)
        
        # 快速時間選擇按鈕
        quick_time_btn = QPushButton("快速選擇")
        quick_time_btn.clicked.connect(self.show_quick_time_menu)
        time_layout.addWidget(quick_time_btn)
        
        # 添加幫助按鈕
        help_btn = QPushButton("時間格式幫助")
        help_btn.clicked.connect(self.show_time_help)
        time_layout.addWidget(help_btn)
        
        # 間隔設(shè)置(默認(rèn)隱藏)
        self.interval_spin = QSpinBox()
        self.interval_spin.setRange(1, 1000)
        self.interval_unit = QComboBox()
        self.interval_unit.addItems(["秒", "分鐘", "小時", "天"])
        self.interval_spin.hide()
        self.interval_unit.hide()
        time_layout.addWidget(self.interval_spin)
        time_layout.addWidget(self.interval_unit)
        
        task_layout.addLayout(time_layout)
        
        # 第三行:附加選項
        options_layout = QHBoxLayout()
        
        # 優(yōu)先級
        self.priority = QComboBox()
        self.priority.addItems(["低", "中", "高"])
        options_layout.addWidget(QLabel("優(yōu)先級:"))
        options_layout.addWidget(self.priority)
        
        # 是否啟用日志
        self.enable_log = QCheckBox("啟用日志")
        options_layout.addWidget(self.enable_log)
        
        # 任務(wù)描述
        self.description = QLineEdit()
        options_layout.addWidget(QLabel("描述:"))
        options_layout.addWidget(self.description)
        
        task_layout.addLayout(options_layout)
        
        # 添加任務(wù)按鈕
        buttons_layout = QHBoxLayout()
        add_button = QPushButton("添加任務(wù)")
        add_button.clicked.connect(self.add_task)
        buttons_layout.addWidget(add_button)
        
        # 導(dǎo)入導(dǎo)出按鈕
        import_button = QPushButton("導(dǎo)入任務(wù)")
        export_button = QPushButton("導(dǎo)出任務(wù)")
        import_button.clicked.connect(self.import_tasks)
        export_button.clicked.connect(self.export_tasks)
        buttons_layout.addWidget(import_button)
        buttons_layout.addWidget(export_button)
        
        task_layout.addLayout(buttons_layout)
        
        layout.addWidget(task_group)
        
        # 任務(wù)列表
        self.task_table = QTableWidget()
        self.task_table.setColumnCount(7)
        self.task_table.setHorizontalHeaderLabels([
            "任務(wù)類型", "目標(biāo)路徑", "執(zhí)行時間", "優(yōu)先級", 
            "狀態(tài)", "描述", "操作"
        ])
        self.task_table.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
        self.task_table.customContextMenuRequested.connect(self.show_context_menu)
        layout.addWidget(self.task_table)
        
        # 日志區(qū)域
        log_group = QWidget()
        log_layout = QVBoxLayout(log_group)
        log_layout.addWidget(QLabel("執(zhí)行日志:"))
        self.log_text = QTextEdit()
        self.log_text.setReadOnly(True)
        log_layout.addWidget(self.log_text)
        layout.addWidget(log_group)
        
        # 設(shè)置日志控件
        self.log_manager.set_log_widget(self.log_text)
        
        # 啟動定時器
        self.timer = QTimer()
        self.timer.timeout.connect(self.check_tasks)
        self.timer.start(1000)
        
    def on_task_type_changed(self, task_type):
        if task_type == "系統(tǒng)操作":
            self.target_path.clear()
            self.target_path.setReadOnly(True)
            self.target_path.setPlaceholderText("系統(tǒng)操作無需設(shè)置路徑")
            self.browse_btn.setEnabled(False)
        elif task_type == "鍵鼠操作":
            self.target_path.clear()
            self.target_path.setReadOnly(True)
            self.target_path.setPlaceholderText("點擊編輯按鈕設(shè)置鍵鼠操作")
            self.browse_btn.setText("編輯")
            self.browse_btn.setEnabled(True)
            self.browse_btn.clicked.disconnect()
            self.browse_btn.clicked.connect(self.edit_mouse_keyboard)
        else:
            self.target_path.setReadOnly(False)
            self.target_path.setPlaceholderText("")
            self.browse_btn.setText("瀏覽...")
            self.browse_btn.setEnabled(True)
            self.browse_btn.clicked.disconnect()
            self.browse_btn.clicked.connect(self.browse_path)
            
    def on_time_type_changed(self, time_type):
        if time_type == "自定義間隔":
            self.time_input.hide()
            self.interval_spin.show()
            self.interval_unit.show()
        elif time_type == "文件觸發(fā)":
            self.time_input.hide()
            self.interval_spin.hide()
            self.interval_unit.hide()
        else:
            self.time_input.show()
            self.interval_spin.hide()
            self.interval_unit.hide()
            
            # 根據(jù)時間類型設(shè)置提示文本
            if time_type == "一次性":
                self.time_input.setPlaceholderText("示例:2024-03-20 15:30 或 15分鐘后")
            elif time_type == "每天":
                self.time_input.setPlaceholderText("示例:09:30(每天9點30分執(zhí)行)")
            elif time_type == "每周":
                self.time_input.setPlaceholderText("示例:星期一 09:30 或 1 09:30")
            elif time_type == "每月":
                self.time_input.setPlaceholderText("示例:1 09:30(每月1號9點30分)")
            elif time_type == "每年":
                self.time_input.setPlaceholderText("示例:03-01 09:30(每年3月1日9點30分)")
            
    def browse_path(self):
        task_type = self.task_type.currentText()
        if task_type in ["打開程序", "關(guān)閉程序"]:
            file_path, _ = QFileDialog.getOpenFileName(
                self, "選擇程序", "", 
                "可執(zhí)行文件 (*.exe *.bat *.cmd *.ps1);;所有文件 (*.*)"
            )
        else:
            file_path, _ = QFileDialog.getOpenFileName(self, "選擇文件")
        if file_path:
            self.target_path.setText(file_path)
            
    def add_task(self):
        try:
            task_type = self.task_type.currentText()
            target = self.target_path.text()
            time_type = self.time_type.currentText()
            
            # 驗證輸入
            if not target and task_type != "系統(tǒng)操作":
                QMessageBox.warning(self, "錯誤", "請輸入目標(biāo)路徑", QMessageBox.StandardButton.Ok)
                return
                
            # 設(shè)置執(zhí)行時間
            if time_type == "自定義間隔":
                interval = self.interval_spin.value()
                unit = self.interval_unit.currentText()
                if unit == "秒":
                    delta = timedelta(seconds=interval)
                elif unit == "分鐘":
                    delta = timedelta(minutes=interval)
                elif unit == "小時":
                    delta = timedelta(hours=interval)
                else:
                    delta = timedelta(days=interval)
                # 使用精確時間計算
                current_time = datetime.now()
                execute_time = current_time.replace(microsecond=0) + delta
            elif time_type == "文件觸發(fā)":
                execute_time = "文件觸發(fā)"
            elif time_type == "每年":
                # 處理每年的時間格式
                time_str = self.time_input.text().strip()
                if not time_str:
                    QMessageBox.warning(self, "錯誤", "請輸入執(zhí)行時間", QMessageBox.StandardButton.Ok)
                    return
                    
                try:
                    parts = time_str.split()
                    if len(parts) != 2:
                        raise ValueError("每年任務(wù)的時間格式應(yīng)為 'MM-DD HH:MM'")
                    
                    date_part, time_part = parts
                    month, day = map(int, date_part.split('-'))
                    hour, minute = map(int, time_part.split(':'))
                    
                    now = datetime.now()
                    try:
                        execute_time = now.replace(month=month, day=day, hour=hour, minute=minute, second=0, microsecond=0)
                        # 如果時間已過,設(shè)置為明年
                        if execute_time <= now:
                            execute_time = execute_time.replace(year=now.year + 1)
                    except ValueError as e:
                        if "day is out of range for month" in str(e):
                            raise ValueError("指定的日期超出了月份的有效范圍")
                        raise e
                except Exception as e:
                    raise ValueError(f"時間格式錯誤: {str(e)}")
            else:
                time_str = self.time_input.text().strip()
                if not time_str:
                    QMessageBox.warning(self, "錯誤", "請輸入執(zhí)行時間", QMessageBox.StandardButton.Ok)
                    return
                    
                try:
                    if "秒后" in time_str:
                        seconds = int(time_str.replace("秒后", "").strip())
                        current_time = datetime.now()
                        execute_time = current_time.replace(microsecond=0) + timedelta(seconds=seconds)
                    elif "分鐘后" in time_str:
                        minutes = int(time_str.replace("分鐘后", "").strip())
                        current_time = datetime.now()
                        execute_time = current_time.replace(microsecond=0) + timedelta(minutes=minutes)
                    elif time_type == "每天":
                        # 處理每天的時間格式 HH:MM
                        try:
                            hour, minute = map(int, time_str.split(':'))
                            now = datetime.now()
                            execute_time = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
                            # 如果時間已過,設(shè)置為明天
                            if execute_time <= now:
                                execute_time += timedelta(days=1)
                        except ValueError:
                            raise ValueError("每天任務(wù)的時間格式應(yīng)為 HH:MM")
                    elif time_type == "每周":
                        # 處理每周的時間格式
                        parts = time_str.split()
                        if len(parts) != 2:
                            raise ValueError("每周任務(wù)的時間格式應(yīng)為 '星期X HH:MM' 或 'X HH:MM'")
                        
                        weekday_str, time_part = parts
                        # 轉(zhuǎn)換星期為數(shù)字(0-6)
                        weekday_map = {
                            "星期一": 0, "星期二": 1, "星期三": 2, "星期四": 3,
                            "星期五": 4, "星期六": 5, "星期日": 6,
                            "周一": 0, "周二": 1, "周三": 2, "周四": 3,
                            "周五": 4, "周六": 5, "周日": 6,
                            "1": 0, "2": 1, "3": 2, "4": 3, "5": 4, "6": 5, "7": 6
                        }
                        if weekday_str not in weekday_map:
                            raise ValueError("無效的星期格式")
                        
                        target_weekday = weekday_map[weekday_str]
                        hour, minute = map(int, time_part.split(':'))
                        
                        # 計算下一個目標(biāo)星期的日期
                        now = datetime.now()
                        days_ahead = target_weekday - now.weekday()
                        if days_ahead <= 0:  # 如果目標(biāo)星期已過,設(shè)置為下周
                            days_ahead += 7
                        
                        execute_time = now.replace(hour=hour, minute=minute, second=0, microsecond=0) + timedelta(days=days_ahead)
                        
                    elif time_type == "每月":
                        # 處理每月的時間格式
                        parts = time_str.replace('日', '').split()
                        if len(parts) != 2:
                            raise ValueError("每月任務(wù)的時間格式應(yīng)為 'DD HH:MM' 或 'DD日 HH:MM'")
                        
                        day = int(parts[0])
                        hour, minute = map(int, parts[1].split(':'))
                        
                        now = datetime.now()
                        try:
                            execute_time = now.replace(day=day, hour=hour, minute=minute, second=0, microsecond=0)
                            # 如果時間已過,設(shè)置為下個月
                            if execute_time <= now:
                                if now.month == 12:
                                    execute_time = execute_time.replace(year=now.year + 1, month=1)
                                else:
                                    execute_time = execute_time.replace(month=now.month + 1)
                        except ValueError as e:
                            if "day is out of range for month" in str(e):
                                raise ValueError("指定的日期超出了月份的有效范圍")
                            raise e
                    else:
                        # 嘗試解析完整的日期時間格式
                        try:
                            execute_time = parser.parse(time_str)
                        except:
                            raise ValueError("無效的時間格式")
                except Exception as e:
                    raise ValueError(f"時間格式錯誤: {str(e)}")
            
            task = {
                "type": task_type,
                "target": target,
                "time_type": time_type,
                "time": str(execute_time),
                "priority": self.priority.currentText(),
                "description": self.description.text(),
                "status": "等待中",
                "enable_log": self.enable_log.isChecked()
            }
            
            # 驗證任務(wù)數(shù)據(jù)
            self.task_validator.validate_task_data(task)
            
            # 如果是文件觸發(fā)類型,設(shè)置文件監(jiān)控
            if time_type == "文件觸發(fā)":
                self.setup_file_observer(task)
            
            self.tasks.append(task)
            self.save_tasks()
            self.update_task_table()
            
            # 記錄日志
            self.log_manager.write_log(f"添加新任務(wù): {task['type']} - {task['description']}")
            
            # 清空輸入框
            self.time_input.clear()
            self.target_path.clear()
            self.description.clear()
            
        except Exception as e:
            QMessageBox.warning(self, "錯誤", f"添加任務(wù)失敗: {str(e)}", QMessageBox.StandardButton.Ok)
            
    def setup_file_observer(self, task):
        try:
            if task["target"] not in self.file_observers:
                event_handler = FileChangeHandler(lambda path: self.on_file_changed(task))
                observer = Observer()
                observer.schedule(event_handler, os.path.dirname(task["target"]), recursive=False)
                observer.start()
                self.file_observers[task["target"]] = observer
        except Exception as e:
            raise Exception(f"設(shè)置文件監(jiān)控失敗: {str(e)}")
            
    def cleanup_file_observer(self, task):
        if task["target"] in self.file_observers:
            try:
                self.file_observers[task["target"]].stop()
                self.file_observers[task["target"]].join()
                del self.file_observers[task["target"]]
            except Exception as e:
                print(f"清理文件監(jiān)控失敗: {str(e)}")
                
    def on_file_changed(self, task):
        self.execute_task(task)
        
    def show_context_menu(self, position):
        menu = QMenu()
        delete_action = menu.addAction("刪除任務(wù)")
        pause_action = menu.addAction("暫停任務(wù)")
        resume_action = menu.addAction("恢復(fù)任務(wù)")
        
        action = menu.exec(self.task_table.mapToGlobal(position))
        if action == delete_action:
            self.delete_selected_task()
        elif action == pause_action:
            self.pause_selected_task()
        elif action == resume_action:
            self.resume_selected_task()
            
    def delete_selected_task(self):
        current_row = self.task_table.currentRow()
        if current_row >= 0:
            task = self.tasks[current_row]
            # 清理文件監(jiān)控
            self.cleanup_file_observer(task)
            # 刪除任務(wù)
            del self.tasks[current_row]
            self.save_tasks()
            self.update_task_table()
            # 記錄日志
            self.log_manager.write_log(f"刪除任務(wù): {task['type']} - {task['description']}")
            
    def pause_selected_task(self):
        current_row = self.task_table.currentRow()
        if current_row >= 0:
            task = self.tasks[current_row]
            task["status"] = "已暫停"
            # 如果是文件觸發(fā)類型,暫停文件監(jiān)控
            if task["time_type"] == "文件觸發(fā)":
                self.cleanup_file_observer(task)
            self.save_tasks()
            self.update_task_table()
            # 記錄日志
            self.log_manager.write_log(f"暫停任務(wù): {task['type']} - {task['description']}")
            
    def resume_selected_task(self):
        current_row = self.task_table.currentRow()
        if current_row >= 0:
            task = self.tasks[current_row]
            task["status"] = "等待中"
            # 如果是文件觸發(fā)類型,重新啟動文件監(jiān)控
            if task["time_type"] == "文件觸發(fā)":
                self.setup_file_observer(task)
            self.save_tasks()
            self.update_task_table()
            # 記錄日志
            self.log_manager.write_log(f"恢復(fù)任務(wù): {task['type']} - {task['description']}")
            
    def save_tasks(self):
        with open("tasks.json", "w", encoding="utf-8") as f:
            json.dump(self.tasks, f, ensure_ascii=False, indent=2)
            
    def load_tasks(self):
        try:
            if os.path.exists("tasks.json"):
                with open("tasks.json", "r", encoding="utf-8") as f:
                    self.tasks = json.load(f)
                    
                # 重新設(shè)置文件監(jiān)控
                for task in self.tasks:
                    if task["time_type"] == "文件觸發(fā)":
                        self.setup_file_observer(task)
        except Exception as e:
            print(f"加載任務(wù)失敗: {str(e)}")
            
    def import_tasks(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "導(dǎo)入任務(wù)", "", "JSON文件 (*.json)")
        if file_path:
            try:
                with open(file_path, "r", encoding="utf-8") as f:
                    imported_tasks = json.load(f)
                    
                # 驗證所有導(dǎo)入的任務(wù)
                for task in imported_tasks:
                    self.task_validator.validate_task_data(task)
                    
                # 導(dǎo)入任務(wù)
                self.tasks.extend(imported_tasks)
                
                # 設(shè)置文件監(jiān)控
                for task in imported_tasks:
                    if task["time_type"] == "文件觸發(fā)" and task["status"] == "等待中":
                        self.setup_file_observer(task)
                        
                self.save_tasks()
                self.update_task_table()
                
                # 記錄日志
                self.log_manager.write_log(f"導(dǎo)入{len(imported_tasks)}個任務(wù)")
                QMessageBox.information(self, "成功", "任務(wù)導(dǎo)入成功", QMessageBox.StandardButton.Ok)
                
            except Exception as e:
                QMessageBox.warning(self, "錯誤", f"導(dǎo)入任務(wù)失敗: {str(e)}", QMessageBox.StandardButton.Ok)
                
    def export_tasks(self):
        file_path, _ = QFileDialog.getSaveFileName(self, "導(dǎo)出任務(wù)", "", "JSON文件 (*.json)")
        if file_path:
            try:
                with open(file_path, "w", encoding="utf-8") as f:
                    json.dump(self.tasks, f, ensure_ascii=False, indent=2)
                QMessageBox.information(self, "成功", "任務(wù)導(dǎo)出成功", QMessageBox.StandardButton.Ok)
            except Exception as e:
                QMessageBox.warning(self, "錯誤", f"導(dǎo)出任務(wù)失敗: {str(e)}", QMessageBox.StandardButton.Ok)
                
    def update_task_table(self):
        self.task_table.setRowCount(len(self.tasks))
        for i, task in enumerate(self.tasks):
            self.task_table.setItem(i, 0, QTableWidgetItem(task["type"]))
            self.task_table.setItem(i, 1, QTableWidgetItem(task["target"]))
            self.task_table.setItem(i, 2, QTableWidgetItem(str(task["time"])))
            self.task_table.setItem(i, 3, QTableWidgetItem(task["priority"]))
            self.task_table.setItem(i, 4, QTableWidgetItem(task["status"]))
            self.task_table.setItem(i, 5, QTableWidgetItem(task["description"]))
            
            # 添加操作按鈕
            btn_widget = QWidget()
            btn_layout = QHBoxLayout(btn_widget)
            delete_btn = QPushButton("刪除")
            delete_btn.clicked.connect(lambda checked, row=i: self.delete_task(row))
            btn_layout.addWidget(delete_btn)
            self.task_table.setCellWidget(i, 6, btn_widget)
            
    def check_tasks(self):
        current_time = datetime.now()
        for task in self.tasks:
            if task["status"] == "等待中":
                if task["time_type"] == "文件觸發(fā)":
                    continue  # 文件觸發(fā)類型由文件監(jiān)控處理
                    
                execute_time = parser.parse(task["time"])
                if current_time >= execute_time:
                    self.execute_task(task)
                    
                    # 根據(jù)時間類型更新下次執(zhí)行時間
                    if task["time_type"] == "每天":
                        next_time = execute_time + timedelta(days=1)
                    elif task["time_type"] == "每周":
                        next_time = execute_time + timedelta(weeks=1)
                    elif task["time_type"] == "每月":
                        if execute_time.month == 12:
                            next_time = execute_time.replace(year=execute_time.year + 1, month=1)
                        else:
                            next_time = execute_time.replace(month=execute_time.month + 1)
                    elif task["time_type"] == "每年":
                        next_time = execute_time.replace(year=execute_time.year + 1)
                    else:
                        task["status"] = "已完成"
                        continue
                        
                    task["time"] = str(next_time)
                    
        self.update_task_table()
        self.save_tasks()

    def execute_task(self, task):
        try:
            result = "執(zhí)行成功"
            
            # 驗證目標(biāo)路徑(鍵鼠操作除外)
            if task["type"] not in ["系統(tǒng)操作", "鍵鼠操作"]:
                if not os.path.exists(task["target"]):
                    raise FileNotFoundError(f"目標(biāo)路徑不存在: {task['target']}")
            
            if task["type"] == "打開程序":
                subprocess.Popen(task["target"])
            elif task["type"] == "關(guān)閉程序":
                process_name = os.path.basename(task["target"])
                for proc in psutil.process_iter(['name']):
                    if proc.info['name'] == process_name:
                        proc.kill()
            elif task["type"] == "讀取文件":
                with open(task["target"], 'r', encoding='utf-8') as f:
                    content = f.read()
                    print(content)
                    result = f"讀取內(nèi)容: {content[:100]}..."
            elif task["type"] == "寫入文件":
                with open(task["target"], 'w', encoding='utf-8') as f:
                    f.write("寫入測試內(nèi)容")
            elif task["type"] == "系統(tǒng)操作":
                if task["target"] == "關(guān)機(jī)":
                    os.system("shutdown /s /t 60")
                elif task["target"] == "重啟":
                    os.system("shutdown /r /t 60")
                elif task["target"] == "休眠":
                    os.system("rundll32.exe powrprof.dll,SetSuspendState 0,1,0")
            elif task["type"] == "鍵鼠操作":
                try:
                    action_data = json.loads(task["target"])
                    if action_data.get("type") == "wechat_login":
                        # 使用 wxauto 實現(xiàn)微信登錄
                        try:
                            # 檢查微信進(jìn)程是否存在
                            wechat_running = False
                            wechat_pid = None
                            for proc in psutil.process_iter(['name', 'pid']):
                                if proc.info['name'].lower() in ['wechat.exe', 'weixin.exe']:
                                    wechat_running = True
                                    wechat_pid = proc.info['pid']
                                    break

                            if wechat_running and wechat_pid:
                                # 如果微信已在運行,先關(guān)閉它
                                psutil.Process(wechat_pid).terminate()
                                time.sleep(2)  # 等待進(jìn)程完全關(guān)閉

                            # 啟動新的微信實例
                            wechat_path = None
                            possible_paths = [
                                os.path.expandvars(r"%ProgramFiles%\Tencent\WeChat\WeChat.exe"),
                                os.path.expandvars(r"%ProgramFiles(x86)%\Tencent\WeChat\WeChat.exe"),
                                r"C:\Program Files\Tencent\WeChat\WeChat.exe",
                                r"C:\Program Files (x86)\Tencent\WeChat\WeChat.exe"
                            ]
                            
                            for path in possible_paths:
                                if os.path.exists(path):
                                    wechat_path = path
                                    break
                            
                            if not wechat_path:
                                raise Exception("找不到微信安裝路徑")

                            # 啟動微信
                            subprocess.Popen(wechat_path)
                            time.sleep(8)  # 等待微信完全啟動
                            
                            # 使用wxauto處理登錄
                            retry_count = 0
                            success = False
                            while retry_count < 5:  # 最多嘗試5次
                                try:
                                    wx = WeChat()
                                    if wx.WindowStatus == 1:  # 窗口正常
                                        if wx.LoginStatus == 0:  # 未登錄
                                            wx.ClickLogin()  # 使用wxauto的方法點擊登錄
                                            success = True
                                            result = "微信登錄操作執(zhí)行完成"
                                            break
                                        else:
                                            success = True
                                            result = "微信已經(jīng)處于登錄狀態(tài)"
                                            break
                                except Exception as e:
                                    print(f"第{retry_count + 1}次嘗試失?。簕str(e)}")
                                    retry_count += 1
                                    time.sleep(2)
                            
                            if not success:
                                raise Exception("無法完成登錄操作,請手動檢查微信窗口狀態(tài)")
                                
                        except Exception as e:
                            raise Exception(f"微信登錄操作失敗: {str(e)}")
                    elif action_data.get("type") == "click":
                        # 添加短暫延時確保鼠標(biāo)移動到位
                        time.sleep(0.5)
                        # 先移動到目標(biāo)位置
                        pyautogui.moveTo(action_data["x"], action_data["y"], duration=0.2)
                        # 再執(zhí)行點擊
                        time.sleep(0.2)
                        pyautogui.click()
                        result = f"點擊坐標(biāo) ({action_data['x']}, {action_data['y']}) 完成"
                    elif action_data.get("type") == "type":
                        time.sleep(0.5)  # 等待輸入框準(zhǔn)備就緒
                        pyautogui.typewrite(action_data["text"], interval=0.1)  # 添加輸入間隔
                        result = f"輸入文本 '{action_data['text']}' 完成"
                    elif action_data.get("type") == "hotkey":
                        time.sleep(0.5)  # 等待系統(tǒng)準(zhǔn)備就緒
                        pyautogui.hotkey(*action_data["keys"])
                        result = f"執(zhí)行快捷鍵 {'+'.join(action_data['keys'])} 完成"
                    else:
                        raise ValueError(f"未知的鍵鼠操作類型: {action_data.get('type')}")
                except json.JSONDecodeError:
                    raise ValueError("無效的鍵鼠操作JSON格式")
                except pyautogui.FailSafeException:
                    raise Exception("操作被用戶中斷(鼠標(biāo)移動到屏幕角落觸發(fā)安全機(jī)制)")
                except Exception as e:
                    raise Exception(f"鍵鼠操作執(zhí)行失敗: {str(e)}")
            elif task["type"] == "網(wǎng)絡(luò)操作":
                # 這里可以添加網(wǎng)絡(luò)相關(guān)操作的實現(xiàn)
                pass
                
            # 記錄日志
            if task["enable_log"]:
                self.log_manager.write_log(f"執(zhí)行任務(wù): {task['type']} - {task['description']}: {result}")
                
        except Exception as e:
            error_msg = f"執(zhí)行任務(wù)失敗: {str(e)}"
            print(error_msg)
            if task["enable_log"]:
                self.log_manager.write_log(f"執(zhí)行任務(wù)失敗: {task['type']} - {task['description']}: {error_msg}")

    def show_quick_time_menu(self):
        menu = QMenu(self)
        time_type = self.time_type.currentText()
        
        if time_type == "一次性":
            # 添加秒選項
            for seconds in [5, 10, 30]:
                action = menu.addAction(f"{seconds}秒后")
                action.triggered.connect(lambda checked, s=seconds: self.time_input.setText(f"{s}秒后"))
            
            menu.addSeparator()
            
            # 添加相對時間選項
            for minutes in [1, 5, 10, 15, 30, 60]:
                action = menu.addAction(f"{minutes}分鐘后")
                action.triggered.connect(lambda checked, m=minutes: self.time_input.setText(f"{m}分鐘后"))
            
            menu.addSeparator()
            
            # 添加今明兩天的常用時間點
            now = datetime.now()
            today = now.date()
            tomorrow = today + timedelta(days=1)
            
            for hour in [9, 12, 15, 18, 21]:
                # 今天的時間點(只添加未來的時間點)
                time_point = now.replace(hour=hour, minute=0, second=0, microsecond=0)
                if time_point > now:
                    action = menu.addAction(f"今天 {hour:02d}:00")
                    action.triggered.connect(
                        lambda checked, t=time_point: self.time_input.setText(t.strftime("%Y-%m-%d %H:%M"))
                    )
                
                # 明天的時間點
                time_point = datetime.combine(tomorrow, datetime.min.time().replace(hour=hour))
                action = menu.addAction(f"明天 {hour:02d}:00")
                action.triggered.connect(
                    lambda checked, t=time_point: self.time_input.setText(t.strftime("%Y-%m-%d %H:%M"))
                )
                
        elif time_type == "每天":
            for hour in [9, 12, 15, 18, 21]:
                for minute in [0, 30]:
                    time_str = f"{hour:02d}:{minute:02d}"
                    action = menu.addAction(time_str)
                    action.triggered.connect(lambda checked, t=time_str: self.time_input.setText(t))
                    
        elif time_type == "每周":
            weekdays = ["星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"]
            for weekday in weekdays:
                submenu = menu.addMenu(weekday)
                for hour in [9, 12, 15, 18, 21]:
                    action = submenu.addAction(f"{hour:02d}:00")
                    action.triggered.connect(
                        lambda checked, w=weekday, h=hour: self.time_input.setText(f"{w} {h:02d}:00")
                    )
                    
        elif time_type == "每月":
            for day in [1, 5, 10, 15, 20, 25, 30]:
                submenu = menu.addMenu(f"{day}日")
                for hour in [9, 12, 15, 18, 21]:
                    action = submenu.addAction(f"{hour:02d}:00")
                    action.triggered.connect(
                        lambda checked, d=day, h=hour: self.time_input.setText(f"vvxyksv9kd {h:02d}:00")
                    )
        
        elif time_type == "每年":
            # 添加一些重要的年度日期
            special_dates = [
                ("元旦", "01-01"),
                ("春節(jié)", "02-01"),  # 這里使用陽歷示例
                ("勞動節(jié)", "05-01"),
                ("國慶節(jié)", "10-01"),
                ("元旦前夕", "12-31")
            ]
            
            for name, date in special_dates:
                submenu = menu.addMenu(name)
                for hour in [0, 8, 9, 12, 15, 18, 21]:
                    time_str = f"{date} {hour:02d}:00"
                    action = submenu.addAction(f"{hour:02d}:00")
                    action.triggered.connect(
                        lambda checked, t=time_str: self.time_input.setText(t)
                    )
            
            menu.addSeparator()
            
            # 添加每月第一天
            for month in range(1, 13):
                time_str = f"{month:02d}-01 09:00"
                action = menu.addAction(f"{month}月1日 09:00")
                action.triggered.connect(
                    lambda checked, t=time_str: self.time_input.setText(t)
                )
        
        menu.exec(QCursor.pos())

    def show_time_help(self):
        help_text = """
時間格式說明:

1. 一次性任務(wù):
   - 絕對時間:2024-03-20 15:30
   - 相對時間:
     * X秒后(如:30秒后)
     * X分鐘后(如:15分鐘后)
   - 支持格式:
     * YYYY-MM-DD HH:MM
     * YYYY/MM/DD HH:MM
     * X秒后(X為數(shù)字)
     * X分鐘后(X為數(shù)字)

2. 每天任務(wù):
   - 格式:HH:MM
   - 示例:09:30、15:00
   - 說明:每天在指定時間執(zhí)行

3. 每周任務(wù):
   - 格式一:星期X HH:MM
   - 格式二:周X HH:MM
   - 格式三:X HH:MM(X為1-7,表示周一到周日)
   - 示例:
     * 星期一 09:30
     * 周五 15:00
     * 1 09:30(周一 9:30)

4. 每月任務(wù):
   - 格式一:DD HH:MM
   - 格式二:DD日 HH:MM
   - 示例:
     * 1 09:30(每月1號9:30)
     * 15日 15:00(每月15號15:00)

5. 每年任務(wù):
   - 格式:MM-DD HH:MM
   - 示例:
     * 03-01 09:30(每年3月1日9:30)
     * 12-25 00:00(每年圣誕節(jié)零點)
   - 說明:月份和日期使用數(shù)字,用連字符分隔

6. 文件觸發(fā):
   - 無需填寫時間
   - 當(dāng)文件發(fā)生變化時自動觸發(fā)

7. 自定義間隔:
   - 使用下拉框選擇間隔時間和單位(秒/分鐘/小時/天)
   - 從當(dāng)前時間開始計算

提示:
- 使用24小時制
- 分鐘必須是兩位數(shù)(如:09:05,而不是9:5)
- 可以使用"快速選擇"按鈕選擇常用時間
"""
        msg = QMessageBox()
        msg.setWindowTitle("時間格式說明")
        msg.setText(help_text)
        msg.setIcon(QMessageBox.Icon.Information)
        msg.exec()

    def delete_task(self, row):
        """刪除指定行的任務(wù)"""
        if 0 <= row < len(self.tasks):
            task = self.tasks[row]
            # 清理文件監(jiān)控
            self.cleanup_file_observer(task)
            # 刪除任務(wù)
            del self.tasks[row]
            self.save_tasks()
            self.update_task_table()
            # 記錄日志
            self.log_manager.write_log(f"刪除任務(wù): {task['type']} - {task['description']}")

    def edit_mouse_keyboard(self):
        editor = MouseKeyboardEditor(self)
        if self.target_path.text():
            try:
                # 如果已有內(nèi)容,加載到編輯器中
                editor.code_editor.setPlainText(self.target_path.text())
            except:
                pass
                
        if editor.exec() == QDialog.DialogCode.Accepted:
            try:
                # 驗證JSON格式
                json_str = editor.get_code()
                json.loads(json_str)  # 驗證JSON是否有效
                self.target_path.setText(json_str)
            except json.JSONDecodeError:
                QMessageBox.warning(self, "錯誤", "無效的JSON格式", QMessageBox.StandardButton.Ok)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = TaskManager()
    window.show()
    sys.exit(app.exec()) 

到此這篇關(guān)于Python利用PyQt6開發(fā)一個全能的任務(wù)管理器的文章就介紹到這了,更多相關(guān)Python任務(wù)管理器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • python 利用Pyinstaller打包Web項目

    python 利用Pyinstaller打包Web項目

    這篇文章主要介紹了python 利用Pyinstaller打包Web項目,幫助大家更好的理解和使用python,感興趣的朋友可以了解下
    2020-10-10
  • Python+matplotlib實現(xiàn)華麗的文本框演示代碼

    Python+matplotlib實現(xiàn)華麗的文本框演示代碼

    這篇文章主要介紹了Python+matplotlib實現(xiàn)華麗的文本框演示代碼,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • python合并文本文件示例

    python合并文本文件示例

    這篇文章主要介紹了python合并文本文件示例,需要的朋友可以參考下
    2014-02-02
  • python中的項目目錄結(jié)構(gòu)

    python中的項目目錄結(jié)構(gòu)

    這篇文章主要介紹了python中的項目目錄結(jié)構(gòu),具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • 關(guān)于Python下的Matlab函數(shù)對應(yīng)關(guān)系(Numpy)

    關(guān)于Python下的Matlab函數(shù)對應(yīng)關(guān)系(Numpy)

    這篇文章主要介紹了關(guān)于Python下的Matlab函數(shù)對應(yīng)關(guān)系(Numpy),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • python tornado上傳文件功能實現(xiàn)(前端和后端)

    python tornado上傳文件功能實現(xiàn)(前端和后端)

    Tornado 是一個功能強大的 Web 框架,除了基本的請求處理能力之外,還提供了一些高級功能,在 Tornado web 框架中,上傳圖片通常涉及創(chuàng)建一個表單,讓用戶選擇文件并上傳,本文介紹tornado上傳文件功能,感興趣的朋友一起看看吧
    2024-03-03
  • Python反爬實戰(zhàn)掌握酷狗音樂排行榜加密規(guī)則

    Python反爬實戰(zhàn)掌握酷狗音樂排行榜加密規(guī)則

    最新的酷狗音樂反爬來襲,本文介紹如何利用Python掌握酷狗排行榜加密規(guī)則,本章內(nèi)容只限學(xué)習(xí),切勿用作其他用途?。。。?! 有需要的朋友可以借鑒參考下
    2021-10-10
  • 對Python通過pypyodbc訪問Access數(shù)據(jù)庫的方法詳解

    對Python通過pypyodbc訪問Access數(shù)據(jù)庫的方法詳解

    今天小編就為大家分享一篇對Python通過pypyodbc訪問Access數(shù)據(jù)庫的方法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • 解決python文件字符串轉(zhuǎn)列表時遇到空行的問題

    解決python文件字符串轉(zhuǎn)列表時遇到空行的問題

    下面小編就為大家?guī)硪黄鉀Qpython文件字符串轉(zhuǎn)列表時遇到空行的問題。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • Python命令行定時任務(wù)自動化工作流程

    Python命令行定時任務(wù)自動化工作流程

    本文介紹如何使用Python編寫定時任務(wù),以自動執(zhí)行命令行任務(wù)。您將學(xué)習(xí)如何安排定期的任務(wù),處理任務(wù)結(jié)果,以及如何使用Python自動化工作流程,從而提高工作效率。無需手動執(zhí)行重復(fù)任務(wù),Python幫您搞定
    2023-04-04

最新評論