【Python 原创】科技之星合同简约记录开源Python和PyQt6开发的合同管理系统

【Python 原创】科技之星合同简约记录开源Python和PyQt6开发的合同管理系统

【Python 原创】科技之星合同简约记录开源Python和PyQt6开发的合同管理系统 System

发表文章数:556

开通31天会员

月费会员折扣、会员尊享资源。

开通31天会员

开通90天会员

季费会员折扣、会员尊享资源。

开通90天会员

开通365天会员

年费会员折扣、会员尊享资源。

开通365天会员

热门标签

合同管理系统包含以下主要功能:

【Python 原创】科技之星合同简约记录开源Python和PyQt6开发的合同管理系统

数据库管理:

使用SQLite数据库存储合同信息
自动创建数据库和表结构
支持基本的CRUD操作

主要功能:

新增合同
编辑现有合同
删除合同
合同搜索功能
合同列表展示

界面特点:

使用表格展示合同列表
弹出式对话框进行合同编辑
直观的搜索栏
状态筛选功能
数据验证和错误处理

技术细节:

使用PyQt6的Model-View架构
自定义对话框组件
SQL查询参数化防止注入
日期选择控件

使用Python和PyQt6开发的合同管理系统

import sys
import sqlite3
from PyQt6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QLabel, QLineEdit, QPushButton, QTableWidget, QTableWidgetItem,
    QDateEdit, QComboBox, QMessageBox, QDialog, QFormLayout
)
from PyQt6.QtCore import Qt, QDate

class ContractDialog(QDialog):
    def __init__(self, parent=None, contract=None):
        super().__init__(parent)
        self.setWindowTitle("合同详情")
        self.setFixedSize(400, 300)

        layout = QFormLayout()

        self.contract_name = QLineEdit()
        self.client = QLineEdit()
        self.amount = QLineEdit()
        self.start_date = QDateEdit()
        self.end_date = QDateEdit()
        self.status = QComboBox()
        self.status.addItems(["有效", "过期", "终止", "完成"])

        layout.addRow("合同名称:", self.contract_name)
        layout.addRow("客户名称:", self.client)
        layout.addRow("合同金额:", self.amount)
        layout.addRow("开始日期:", self.start_date)
        layout.addRow("结束日期:", self.end_date)
        layout.addRow("合同状态:", self.status)

        self.buttons = QPushButton("保存")
        self.buttons.clicked.connect(self.accept)
        layout.addRow(self.buttons)

        self.setLayout(layout)

        if contract:
            self.fill_form(contract)

    def fill_form(self, contract):
        self.contract_name.setText(contract[1])
        self.client.setText(contract[2])
        self.amount.setText(str(contract[3]))
        self.start_date.setDate(QDate.fromString(contract[4], "yyyy-MM-dd"))
        self.end_date.setDate(QDate.fromString(contract[5], "yyyy-MM-dd"))
        self.status.setCurrentText(contract[6])

class ContractManager(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("合同管理系统")
        self.setGeometry(100, 100, 800, 600)

        self.db_connect()
        self.init_ui()
        self.load_contracts()

    def db_connect(self):
        self.conn = sqlite3.connect("contracts.db")
        self.cursor = self.conn.cursor()
        self.cursor.execute("""
            CREATE TABLE IF NOT EXISTS contracts (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                client TEXT NOT NULL,
                amount REAL,
                start_date DATE,
                end_date DATE,
                status TEXT
            )
        """)
        self.conn.commit()

    def init_ui(self):
        main_widget = QWidget()
        main_layout = QVBoxLayout()

        # 搜索栏
        search_layout = QHBoxLayout()
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("搜索合同...")
        self.search_input.textChanged.connect(self.search_contracts)
        search_layout.addWidget(self.search_input)

        # 操作按钮
        btn_layout = QHBoxLayout()
        self.add_btn = QPushButton("新增合同")
        self.add_btn.clicked.connect(self.add_contract)
        self.edit_btn = QPushButton("编辑合同")
        self.edit_btn.clicked.connect(self.edit_contract)
        self.delete_btn = QPushButton("删除合同")
        self.delete_btn.clicked.connect(self.delete_contract)

        btn_layout.addWidget(self.add_btn)
        btn_layout.addWidget(self.edit_btn)
        btn_layout.addWidget(self.delete_btn)

        # 表格
        self.table = QTableWidget()
        self.table.setColumnCount(6)
        self.table.setHorizontalHeaderLabels(
            ["ID", "合同名称", "客户", "金额", "开始日期", "结束日期", "状态"]
        )
        self.table.setColumnWidth(1, 200)
        self.table.setColumnWidth(2, 150)

        # 组合布局
        main_layout.addLayout(search_layout)
        main_layout.addLayout(btn_layout)
        main_layout.addWidget(self.table)

        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

    def load_contracts(self, search_text=""):
        query = """
            SELECT id, name, client, amount, start_date, end_date, status 
            FROM contracts 
            WHERE name LIKE ? OR client LIKE ?
        """
        self.cursor.execute(query, (f"%{search_text}%", f"%{search_text}%"))
        contracts = self.cursor.fetchall()

        self.table.setRowCount(len(contracts))
        for row, contract in enumerate(contracts):
            for col, data in enumerate(contract):
                item = QTableWidgetItem(str(data))
                item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsEditable)
                self.table.setItem(row, col, item)

    def get_selected_id(self):
        selected = self.table.selectedItems()
        return int(selected[0].text()) if selected else None

    def add_contract(self):
        dialog = ContractDialog(self)
        if dialog.exec():
            self.cursor.execute("""
                INSERT INTO contracts 
                (name, client, amount, start_date, end_date, status)
                VALUES (?, ?, ?, ?, ?, ?)
            """, (
                dialog.contract_name.text(),
                dialog.client.text(),
                float(dialog.amount.text()),
                dialog.start_date.date().toString("yyyy-MM-dd"),
                dialog.end_date.date().toString("yyyy-MM-dd"),
                dialog.status.currentText()
            ))
            self.conn.commit()
            self.load_contracts()

    def edit_contract(self):
        contract_id = self.get_selected_id()
        if not contract_id:
            QMessageBox.warning(self, "警告", "请先选择一个合同")
            return

        self.cursor.execute("SELECT * FROM contracts WHERE id=?", (contract_id,))
        contract = self.cursor.fetchone()

        dialog = ContractDialog(self, contract)
        if dialog.exec():
            self.cursor.execute("""
                UPDATE contracts SET
                name=?, client=?, amount=?, start_date=?, end_date=?, status=?
                WHERE id=?
            """, (
                dialog.contract_name.text(),
                dialog.client.text(),
                float(dialog.amount.text()),
                dialog.start_date.date().toString("yyyy-MM-dd"),
                dialog.end_date.date().toString("yyyy-MM-dd"),
                dialog.status.currentText(),
                contract_id
            ))
            self.conn.commit()
            self.load_contracts()

    def delete_contract(self):
        contract_id = self.get_selected_id()
        if not contract_id:
            QMessageBox.warning(self, "警告", "请先选择一个合同")
            return

        confirm = QMessageBox.question(
            self, "确认删除", "确定要删除这个合同吗?",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
        )
        if confirm == QMessageBox.StandardButton.Yes:
            self.cursor.execute("DELETE FROM contracts WHERE id=?", (contract_id,))
            self.conn.commit()
            self.load_contracts()

    def search_contracts(self):
        search_text = self.search_input.text()
        self.load_contracts(search_text)

    def closeEvent(self, event):
        self.conn.close()
        event.accept()

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

版本二,新增首页设置密码【默认密码:admin123】

增强版的合同管理系统具有以下特点:

【Python 原创】科技之星合同简约记录开源Python和PyQt6开发的合同管理系统
【Python 原创】科技之星合同简约记录开源Python和PyQt6开发的合同管理系统
密码保护:添加了登录验证功能,只有输入正确密码才能进入系统
密码管理:支持修改密码,密码采用 SHA-256 哈希存储

界面优化:

添加了菜单栏,包含文件、设置和视图菜单
表格根据合同状态显示不同颜色,便于快速识别
增加了列显示 / 隐藏功能
改进了按钮和输入框的样式

功能增强:

添加了高级搜索功能,可以按状态和日期范围筛选
合同详情增加了备注字段
表格支持按日期排序
状态栏显示当前加载的合同数量
初始密码为 admin123,登录后可以通过 "设置 -> 修改密码" 来更改。

科技之星开源提供

import sys
import sqlite3
import hashlib
from PyQt6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
    QLabel, QLineEdit, QPushButton, QTableWidget, QTableWidgetItem,
    QDateEdit, QComboBox, QMessageBox, QDialog, QFormLayout, QDialogButtonBox,
    QFrame, QSpinBox, QGroupBox, QTabWidget, QCheckBox, QGridLayout, QMenu
)
from PyQt6.QtCore import Qt, QDate, pyqtSignal
from PyQt6.QtGui import QAction, QIcon, QPalette, QColor, QFont

class PasswordManager:
    """密码管理类,负责密码的存储、验证和修改"""

    def __init__(self, db_path="contracts.db"):
        self.db_path = db_path
        self._initialize_db()

    def _initialize_db(self):
        """初始化密码存储表"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("""
            CREATE TABLE IF NOT EXISTS settings (
                id INTEGER PRIMARY KEY,
                key TEXT UNIQUE,
                value TEXT
            )
        """)
        # 检查是否已有密码
        cursor.execute("SELECT value FROM settings WHERE key='password_hash'")
        result = cursor.fetchone()
        if not result:
            # 设置默认密码
            self.set_password("admin123")
        conn.close()

    def set_password(self, new_password):
        """设置新密码"""
        password_hash = hashlib.sha256(new_password.encode()).hexdigest()
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute(
            "INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)",
            ("password_hash", password_hash)
        )
        conn.commit()
        conn.close()

    def verify_password(self, password):
        """验证密码"""
        conn = sqlite3.connect(self.db_path)
        cursor = conn.cursor()
        cursor.execute("SELECT value FROM settings WHERE key='password_hash'")
        result = cursor.fetchone()
        conn.close()

        if not result:
            return False

        stored_hash = result[0]
        input_hash = hashlib.sha256(password.encode()).hexdigest()
        return input_hash == stored_hash

class LoginDialog(QDialog):
    """登录对话框"""

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("系统登录")
        self.setFixedSize(300, 180)
        self.setWindowFlags(self.windowFlags() & ~Qt.WindowType.WindowContextHelpButtonHint)

        self.password_manager = PasswordManager()

        layout = QVBoxLayout(self)

        # 图标和标题
        title_label = QLabel("合同管理系统")
        title_font = QFont()
        title_font.setPointSize(16)
        title_font.setBold(True)
        title_label.setFont(title_font)
        title_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        layout.addWidget(title_label)

        # 分隔线
        line = QFrame()
        line.setFrameShape(QFrame.Shape.HLine)
        line.setFrameShadow(QFrame.Shadow.Sunken)
        layout.addWidget(line)

        # 密码输入
        form_layout = QFormLayout()
        self.password_input = QLineEdit()
        self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
        form_layout.addRow("管理员密码:", self.password_input)
        layout.addLayout(form_layout)

        # 记住密码选项
        self.remember_checkbox = QCheckBox("记住密码")
        layout.addWidget(self.remember_checkbox)

        # 按钮
        button_box = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
        )
        button_box.accepted.connect(self.accept)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)

        # 设置焦点
        self.password_input.setFocus()

    def accept(self):
        """验证密码并接受对话框"""
        password = self.password_input.text()
        if self.password_manager.verify_password(password):
            super().accept()
        else:
            QMessageBox.warning(self, "登录失败", "密码错误,请重试!")
            self.password_input.selectAll()
            self.password_input.setFocus()

class ChangePasswordDialog(QDialog):
    """修改密码对话框"""

    password_changed = pyqtSignal(str)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("修改密码")
        self.setFixedSize(300, 200)

        self.password_manager = PasswordManager()

        layout = QVBoxLayout(self)

        form_layout = QFormLayout()

        self.old_password = QLineEdit()
        self.old_password.setEchoMode(QLineEdit.EchoMode.Password)

        self.new_password = QLineEdit()
        self.new_password.setEchoMode(QLineEdit.EchoMode.Password)

        self.confirm_password = QLineEdit()
        self.confirm_password.setEchoMode(QLineEdit.EchoMode.Password)

        form_layout.addRow("当前密码:", self.old_password)
        form_layout.addRow("新密码:", self.new_password)
        form_layout.addRow("确认新密码:", self.confirm_password)

        layout.addLayout(form_layout)

        button_box = QDialogButtonBox(
            QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
        )
        button_box.accepted.connect(self.change_password)
        button_box.rejected.connect(self.reject)
        layout.addWidget(button_box)

    def change_password(self):
        """修改密码处理"""
        old_pwd = self.old_password.text()
        new_pwd = self.new_password.text()
        confirm_pwd = self.confirm_password.text()

        # 验证当前密码
        if not self.password_manager.verify_password(old_pwd):
            QMessageBox.warning(self, "修改失败", "当前密码不正确!")
            self.old_password.selectAll()
            self.old_password.setFocus()
            return

        # 验证新密码
        if len(new_pwd) < 6:
            QMessageBox.warning(self, "修改失败", "新密码长度至少需要6个字符!")
            self.new_password.selectAll()
            self.new_password.setFocus()
            return

        if new_pwd != confirm_pwd:
            QMessageBox.warning(self, "修改失败", "两次输入的新密码不一致!")
            self.confirm_password.selectAll()
            self.confirm_password.setFocus()
            return

        # 修改密码
        self.password_manager.set_password(new_pwd)
        QMessageBox.information(self, "修改成功", "密码已成功修改!")
        self.accept()

class ContractDialog(QDialog):
    """合同详情对话框"""

    def __init__(self, parent=None, contract=None):
        super().__init__(parent)
        self.setWindowTitle("合同详情")
        self.setFixedSize(400, 350)

        layout = QFormLayout()

        self.contract_name = QLineEdit()
        self.client = QLineEdit()
        self.amount = QLineEdit()
        self.start_date = QDateEdit()
        self.start_date.setCalendarPopup(True)
        self.start_date.setDate(QDate.currentDate())
        self.end_date = QDateEdit()
        self.end_date.setCalendarPopup(True)
        self.end_date.setDate(QDate.currentDate().addMonths(1))
        self.status = QComboBox()
        self.status.addItems(["有效", "过期", "终止", "完成"])

        layout.addRow("合同名称:", self.contract_name)
        layout.addRow("客户名称:", self.client)
        layout.addRow("合同金额:", self.amount)
        layout.addRow("开始日期:", self.start_date)
        layout.addRow("结束日期:", self.end_date)
        layout.addRow("合同状态:", self.status)

        # 备注信息
        self.notes = QLineEdit()
        layout.addRow("备注:", self.notes)

        self.buttons = QPushButton("保存")
        self.buttons.clicked.connect(self.accept)
        layout.addRow(self.buttons)

        self.setLayout(layout)

        if contract:
            self.fill_form(contract)

    def fill_form(self, contract):
        """填充表单数据"""
        self.contract_name.setText(contract[1])
        self.client.setText(contract[2])
        self.amount.setText(str(contract[3]))
        self.start_date.setDate(QDate.fromString(contract[4], "yyyy-MM-dd"))
        self.end_date.setDate(QDate.fromString(contract[5], "yyyy-MM-dd"))
        self.status.setCurrentText(contract[6])
        if len(contract) > 7:
            self.notes.setText(contract[7])

class ContractManager(QMainWindow):
    """合同管理主窗口"""

    def __init__(self):
        super().__init__()
        self.setWindowTitle("合同管理系统")
        self.setGeometry(100, 100, 1000, 600)

        # 密码管理器
        self.password_manager = PasswordManager()

        # 数据库连接
        self.db_connect()

        # 初始化UI
        self.init_ui()

        # 加载合同数据
        self.load_contracts()

    def db_connect(self):
        """连接数据库"""
        self.conn = sqlite3.connect("contracts.db")
        self.cursor = self.conn.cursor()

        # 创建合同表(如果不存在)
        self.cursor.execute("""
            CREATE TABLE IF NOT EXISTS contracts (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                name TEXT NOT NULL,
                client TEXT NOT NULL,
                amount REAL,
                start_date DATE,
                end_date DATE,
                status TEXT,
                notes TEXT
            )
        """)
        self.conn.commit()

    def init_ui(self):
        """初始化用户界面"""
        main_widget = QWidget()
        main_layout = QVBoxLayout()

        # 表格 - 先初始化表格
        self.table = QTableWidget()
        self.table.setColumnCount(7)
        self.table.setHorizontalHeaderLabels(
            ["ID", "合同名称", "客户", "金额", "开始日期", "结束日期", "状态"]
        )
        self.table.setColumnWidth(1, 200)
        self.table.setColumnWidth(2, 150)
        self.table.setColumnWidth(3, 100)
        self.table.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
        self.table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)

        # 顶部工具栏 - 现在可以安全地创建菜单栏,因为table已经初始化
        self.create_menu_bar()

        # 搜索栏
        search_layout = QHBoxLayout()
        self.search_input = QLineEdit()
        self.search_input.setPlaceholderText("搜索合同名称或客户...")
        self.search_input.setMinimumHeight(30)
        self.search_input.setStyleSheet("padding: 5px;")
        self.search_input.textChanged.connect(self.search_contracts)

        # 高级搜索按钮
        self.advanced_search_btn = QPushButton("高级搜索")
        self.advanced_search_btn.setMinimumHeight(30)
        self.advanced_search_btn.clicked.connect(self.show_advanced_search)

        search_layout.addWidget(self.search_input)
        search_layout.addWidget(self.advanced_search_btn)

        # 操作按钮
        btn_layout = QHBoxLayout()
        self.add_btn = QPushButton("新增合同")
        self.add_btn.setMinimumHeight(35)
        self.add_btn.setIcon(QIcon.fromTheme("list-add"))
        self.add_btn.clicked.connect(self.add_contract)

        self.edit_btn = QPushButton("编辑合同")
        self.edit_btn.setMinimumHeight(35)
        self.edit_btn.setIcon(QIcon.fromTheme("document-edit"))
        self.edit_btn.clicked.connect(self.edit_contract)

        self.delete_btn = QPushButton("删除合同")
        self.delete_btn.setMinimumHeight(35)
        self.delete_btn.setIcon(QIcon.fromTheme("edit-delete"))
        self.delete_btn.clicked.connect(self.delete_contract)

        # 导出按钮
        self.export_btn = QPushButton("导出数据")
        self.export_btn.setMinimumHeight(35)
        self.export_btn.setIcon(QIcon.fromTheme("document-export"))
        self.export_btn.clicked.connect(self.export_data)

        btn_layout.addWidget(self.add_btn)
        btn_layout.addWidget(self.edit_btn)
        btn_layout.addWidget(self.delete_btn)
        btn_layout.addStretch()
        btn_layout.addWidget(self.export_btn)

        # 状态栏
        self.statusBar().showMessage("就绪")

        # 组合布局
        main_layout.addLayout(search_layout)
        main_layout.addLayout(btn_layout)
        main_layout.addWidget(self.table)

        main_widget.setLayout(main_layout)
        self.setCentralWidget(main_widget)

    def create_menu_bar(self):
        """创建菜单栏"""
        menubar = self.menuBar()

        # 文件菜单
        file_menu = menubar.addMenu("文件")

        # 导出数据
        export_action = QAction("导出数据", self)
        export_action.setShortcut("Ctrl+E")
        export_action.triggered.connect(self.export_data)
        file_menu.addAction(export_action)

        file_menu.addSeparator()

        # 退出
        exit_action = QAction("退出", self)
        exit_action.setShortcut("Ctrl+Q")
        exit_action.triggered.connect(self.close)
        file_menu.addAction(exit_action)

        # 设置菜单
        settings_menu = menubar.addMenu("设置")

        # 修改密码
        change_pwd_action = QAction("修改密码", self)
        change_pwd_action.triggered.connect(self.change_password)
        settings_menu.addAction(change_pwd_action)

        # 视图菜单
        view_menu = menubar.addMenu("视图")

        # 显示/隐藏列
        self.column_actions = []
        for col in range(self.table.columnCount()):
            col_name = self.table.horizontalHeaderItem(col).text()
            action = QAction(col_name, self, checkable=True)
            action.setChecked(True)
            action.triggered.connect(lambda checked, c=col: self.toggle_column(c, checked))
            self.column_actions.append(action)
            view_menu.addAction(action)

    def toggle_column(self, column, visible):
        """显示或隐藏表格列"""
        if visible:
            self.table.showColumn(column)
        else:
            self.table.hideColumn(column)

    def load_contracts(self, search_text="", status_filter=None, date_range=None):
        """加载合同数据"""
        query = """
            SELECT id, name, client, amount, start_date, end_date, status, notes 
            FROM contracts 
            WHERE name LIKE ? OR client LIKE ?
        """
        params = [f"%{search_text}%", f"%{search_text}%"]

        # 状态筛选
        if status_filter and status_filter != "全部":
            query += " AND status = ?"
            params.append(status_filter)

        # 日期范围筛选
        if date_range and len(date_range) == 2:
            start_date, end_date = date_range
            query += " AND start_date >= ? AND end_date <= ?"
            params.extend([start_date, end_date])

        # 添加排序
        query += " ORDER BY start_date DESC"

        self.cursor.execute(query, params)
        contracts = self.cursor.fetchall()

        self.table.setRowCount(len(contracts))
        for row, contract in enumerate(contracts):
            for col, data in enumerate(contract[:7]):  # 只显示前7列
                item = QTableWidgetItem(str(data))
                item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsEditable)

                # 根据状态设置单元格颜色
                if col == 6:  # 状态列
                    if data == "有效":
                        item.setBackground(QColor(220, 255, 220))
                    elif data == "过期":
                        item.setBackground(QColor(255, 220, 220))
                    elif data == "终止":
                        item.setBackground(QColor(240, 240, 240))
                    elif data == "完成":
                        item.setBackground(QColor(220, 220, 255))

                self.table.setItem(row, col, item)

        self.statusBar().showMessage(f"共加载 {len(contracts)} 条合同数据")

    def get_selected_id(self):
        """获取选中的合同ID"""
        selected_items = self.table.selectedItems()
        if not selected_items:
            return None
        return int(selected_items[0].text())

    def add_contract(self):
        """添加新合同"""
        dialog = ContractDialog(self)
        if dialog.exec():
            try:
                self.cursor.execute("""
                    INSERT INTO contracts 
                    (name, client, amount, start_date, end_date, status, notes)
                    VALUES (?, ?, ?, ?, ?, ?, ?)
                """, (
                    dialog.contract_name.text(),
                    dialog.client.text(),
                    float(dialog.amount.text()),
                    dialog.start_date.date().toString("yyyy-MM-dd"),
                    dialog.end_date.date().toString("yyyy-MM-dd"),
                    dialog.status.currentText(),
                    dialog.notes.text()
                ))
                self.conn.commit()
                self.load_contracts()
                QMessageBox.information(self, "成功", "合同添加成功!")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"添加合同失败: {str(e)}")

    def edit_contract(self):
        """编辑选中的合同"""
        contract_id = self.get_selected_id()
        if not contract_id:
            QMessageBox.warning(self, "警告", "请先选择一个合同")
            return

        self.cursor.execute("SELECT * FROM contracts WHERE id=?", (contract_id,))
        contract = self.cursor.fetchone()

        dialog = ContractDialog(self, contract)
        if dialog.exec():
            try:
                self.cursor.execute("""
                    UPDATE contracts SET
                    name=?, client=?, amount=?, start_date=?, end_date=?, status=?, notes=?
                    WHERE id=?
                """, (
                    dialog.contract_name.text(),
                    dialog.client.text(),
                    float(dialog.amount.text()),
                    dialog.start_date.date().toString("yyyy-MM-dd"),
                    dialog.end_date.date().toString("yyyy-MM-dd"),
                    dialog.status.currentText(),
                    dialog.notes.text(),
                    contract_id
                ))
                self.conn.commit()
                self.load_contracts()
                QMessageBox.information(self, "成功", "合同更新成功!")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"更新合同失败: {str(e)}")

    def delete_contract(self):
        """删除选中的合同"""
        contract_id = self.get_selected_id()
        if not contract_id:
            QMessageBox.warning(self, "警告", "请先选择一个合同")
            return

        confirm = QMessageBox.question(
            self, "确认删除", "确定要删除这个合同吗?此操作不可撤销!",
            QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
        )
        if confirm == QMessageBox.StandardButton.Yes:
            try:
                self.cursor.execute("DELETE FROM contracts WHERE id=?", (contract_id,))
                self.conn.commit()
                self.load_contracts()
                QMessageBox.information(self, "成功", "合同已删除!")
            except Exception as e:
                QMessageBox.critical(self, "错误", f"删除合同失败: {str(e)}")

    def search_contracts(self):
        """搜索合同"""
        search_text = self.search_input.text()
        self.load_contracts(search_text)

    def show_advanced_search(self):
        """显示高级搜索对话框"""
        dialog = QDialog(self)
        dialog.setWindowTitle("高级搜索")
        dialog.setMinimumWidth(400)

        layout = QVBoxLayout()

        # 状态筛选
        status_layout = QHBoxLayout()
        status_label = QLabel("合同状态:")
        status_combo = QComboBox()
        status_combo.addItems(["全部", "有效", "过期", "终止", "完成"])
        status_layout.addWidget(status_label)
        status_layout.addWidget(status_combo)

        # 日期范围筛选
        date_layout = QHBoxLayout()
        date_label = QLabel("日期范围:")
        start_date = QDateEdit()
        start_date.setCalendarPopup(True)
        start_date.setDate(QDate.currentDate().addMonths(-1))
        end_label = QLabel("至")
        end_date = QDateEdit()
        end_date.setCalendarPopup(True)
        end_date.setDate(QDate.currentDate())

        date_layout.addWidget(date_label)
        date_layout.addWidget(start_date)
        date_layout.addWidget(end_label)
        date_layout.addWidget(end_date)

        # 按钮
        button_layout = QHBoxLayout()
        search_btn = QPushButton("搜索")
        search_btn.clicked.connect(lambda: self.advanced_search(
            status_combo.currentText(),
            (start_date.date().toString("yyyy-MM-dd"), end_date.date().toString("yyyy-MM-dd"))
        ))
        cancel_btn = QPushButton("取消")
        cancel_btn.clicked.connect(dialog.close)

        button_layout.addStretch()
        button_layout.addWidget(search_btn)
        button_layout.addWidget(cancel_btn)

        layout.addLayout(status_layout)
        layout.addLayout(date_layout)
        layout.addLayout(button_layout)

        dialog.setLayout(layout)
        dialog.exec()

    def advanced_search(self, status, date_range):
        """执行高级搜索"""
        self.load_contracts(status_filter=status, date_range=date_range)

    def export_data(self):
        """导出数据"""
        QMessageBox.information(self, "提示", "数据导出功能将在后续版本中实现")

    def change_password(self):
        """修改密码"""
        dialog = ChangePasswordDialog(self)
        dialog.exec()

    def closeEvent(self, event):
        """关闭事件处理"""
        self.conn.close()
        event.accept()

def main():
    """主函数"""
    app = QApplication(sys.argv)

    # 先显示登录对话框
    login_dialog = LoginDialog()
    if login_dialog.exec() != QDialog.DialogCode.Accepted:
        sys.exit()

    # 登录成功后显示主窗口
    window = ContractManager()
    window.show()
    sys.exit(app.exec())

if __name__ == "__main__":
    main()

未经允许不得转载作者: System, 转载或复制请以 超链接形式 并注明出处 科技之星网站
原文地址: 《 【Python 原创】科技之星合同简约记录开源Python和PyQt6开发的合同管理系统》 发布于 2025-5-19


扫描二维码,在手机上阅读
资源下载
抱歉,下载地址 评论 后刷新可见
收藏
    分享到:
    打赏

    评论 2

    评论前必须登录!

      注册

    1. #1

      谢谢谢

      MvMzmQrT 5 个月前 回复
      • 非常感谢您的关注和支持!很高兴您对我们的Python和PyQt6开发的合同管理系统感兴趣。有任何建议或疑问,随时欢迎提出,我们将竭诚为您提供帮助。期待您的反馈来促进我们产品的不断完善。祝您用得顺手!

        AI助手 5 个月前 回复
    切换注册

    登录

    忘记密码?

    您也可以使用第三方帐号快捷登录

    切换登录

    注册

    觉得文章有用就打赏一下文章作者

    支付宝扫一扫打赏

    微信扫一扫打赏

    Inno Setup 可视化图形界面快速制作专业Windows安装程序
    一款基于Inno Setup的可视化打包工具,无需手动编写脚本,通过图形界面即可快速制作专业的Windows安装程序,支持安装模板,适合各类软件开发者快速打包发布应用。

    特此说明:

    1、所有资源均经过本站在筛选发布,拒绝恶意行为,请各位回帖下载切勿恶意灌水回复,本站以纯净绿色为主发布。拒绝捆绑等恶意行为,请各位回帖请勿恶意灌水回复,有任何问题Q群留言:561116458
    我已阅读