很多中小企业在资产管理上仍依赖Excel手工台账,不仅录入效率低、数据易出错,资产领用、报废等变动也很难系统化追溯。对于计算机专业的同学而言,开发一套轻量化桌面资产管理系统,既是贴合实际需求的毕设选题,也能完整锻炼工程开发能力。

本文基于Python+PyQt5+SQLite技术栈,从架构设计到核心代码实现,完整讲解一套资产管理系统的工程化落地过程,所有代码均来自实际项目,可直接参考复用。

1. 项目概览与技术栈

本系统是面向中小企业的轻量级桌面资产管理应用,覆盖资产全生命周期管理,支持资产信息维护、变动跟踪、用户权限控制、统计可视化等核心功能。系统遵循MVC设计模式,实现业务逻辑与界面的解耦,具备部署成本低、跨平台、易上手的特点。

技术模块

选型

说明

开发语言

Python 3.9

语法简洁,第三方生态丰富,原生支持跨平台

GUI框架

PyQt5 5.15.9

组件丰富,信号槽机制成熟,界面开发效率高

数据库

SQLite

嵌入式零配置,无需独立服务,适配轻量应用

数据可视化

matplotlib 3.7.1

支持多类型统计图表,可无缝嵌入PyQt界面

设计模式

MVC架构

分层解耦,提升代码可维护性与扩展性

2. 系统整体架构与核心流程

基于MVC设计模式,系统采用三层架构,各层职责明确,单向依赖,有效降低模块耦合度:

  1. 视图层:基于PyQt5实现所有交互界面,包括登录窗口、主窗口、各功能标签页、操作对话框等,仅负责接收用户操作与结果展示,不包含业务逻辑。

  2. 控制层:各模块的控制类,负责处理界面触发的事件,调用模型层接口完成数据操作,并将结果同步回视图层。

  3. 模型层:封装SQLite数据库的所有交互操作,实现数据增删改查、业务规则校验、安全逻辑处理,向上提供统一调用接口。

业务主流程为:用户通过登录验证后进入主界面,根据权限等级使用对应功能;所有数据操作均由控制层调用模型层完成,执行结果最终反馈到界面进行展示。

3. 核心功能实现(附核心代码)

3.1 模型层:数据库交互统一封装

模型层的核心是DatabaseManager类,统一收敛所有数据库操作,避免SQL语句散落在业务代码中。类内置了自动建表、密码加密、登录防暴力破解等工程化能力,是整个系统的数据底座。

import sqlite3
import hashlib
import random
from datetime import datetime, timedelta

class DatabaseManager:
    def __init__(self):
        """初始化数据库管理器,自动创建表结构与测试数据"""
        self.db_name = "./database/company_assets.db"
        self.init_database()
        self.insert_sample_data()

    def get_connection(self):
        """获取带行工厂的数据库连接,支持按列名访问数据"""
        conn = sqlite3.connect(self.db_name)
        conn.row_factory = sqlite3.Row
        return conn

    def init_database(self):
        """初始化核心数据表结构"""
        conn = self.get_connection()
        cursor = conn.cursor()

        # 创建用户表:存储账号、加密密码、角色、登录锁定状态
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS users (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                username TEXT UNIQUE NOT NULL,
                password TEXT NOT NULL,
                role TEXT NOT NULL DEFAULT 'employee',
                locked INTEGER DEFAULT 0,
                lock_time TEXT,
                login_attempts INTEGER DEFAULT 0,
                created_time TEXT DEFAULT CURRENT_TIMESTAMP
            )
        ''')

        # 创建资产表:存储资产核心基础信息
        cursor.execute('''
            CREATE TABLE IF NOT EXISTS assets (
                asset_id TEXT PRIMARY KEY,
                name TEXT NOT NULL,
                category TEXT NOT NULL,
                model TEXT,
                purchase_date TEXT NOT NULL,
                price REAL NOT NULL,
                location TEXT NOT NULL,
                status TEXT NOT NULL,
                supplier TEXT,
                note TEXT,
                created_time TEXT DEFAULT CURRENT_TIMESTAMP,
                updated_time TEXT DEFAULT CURRENT_TIMESTAMP
            )
        ''')
        conn.commit()
        conn.close()

    def hash_password(self, password):
        """使用SHA256加密用户密码,避免明文存储"""
        return hashlib.sha256(password.encode()).hexdigest()

    def validate_user(self, username, password):
        """用户登录验证,包含密码校验、失败次数限制、账户锁定逻辑"""
        conn = self.get_connection()
        cursor = conn.cursor()
        cursor.execute('SELECT * FROM users WHERE username = ?', (username,))
        user = cursor.fetchone()

        if user:
            # 校验账户锁定状态,超时自动解锁
            if user['locked'] == 1:
                lock_time = datetime.fromisoformat(user['lock_time'])
                if datetime.now() - lock_time < timedelta(minutes=10):
                    conn.close()
                    return False, "账户已被锁定,请10分钟后再试"
                else:
                    cursor.execute('UPDATE users SET locked = 0, login_attempts = 0 WHERE username = ?', (username,))
                    conn.commit()
            
            # 密码校验与失败计数
            if user['password'] == self.hash_password(password):
                cursor.execute('UPDATE users SET login_attempts = 0 WHERE username = ?', (username,))
                conn.commit()
                user_dict = {key: user[key] for key in user.keys()}
                conn.close()
                return True, user_dict
            else:
                attempts = user['login_attempts'] + 1
                if attempts >= 3:
                    cursor.execute('UPDATE users SET locked = 1, lock_time = ?, login_attempts = ? WHERE username = ?',
                                   (datetime.now().isoformat(), attempts, username))
                    conn.commit()
                    conn.close()
                    return False, "连续输错3次密码,账户已被锁定10分钟"
                else:
                    cursor.execute('UPDATE users SET login_attempts = ? WHERE username = ?', (attempts, username))
                    conn.commit()
                    conn.close()
                    return False, f"密码错误,还剩{3 - attempts}次机会"
        else:
            conn.close()
            return False, "用户名不存在"

该封装的优势在于:上层业务无需关心SQL实现细节;内置密码加密与登录防护逻辑,提升系统安全性;统一的连接管理也避免了资源泄漏问题。

3.2 视图层:登录窗口实现

视图层基于PyQt5开发,采用信号与槽机制实现界面与逻辑的解耦。登录窗口是系统入口,集成登录与注册双标签页,兼顾安全性与易用性。

from PyQt5.QtWidgets import (QWidget, QTabWidget, QFormLayout, QLineEdit, 
                             QPushButton, QLabel, QMessageBox, QVBoxLayout)
from PyQt5.QtCore import pyqtSignal, Qt

class LoginWindow(QWidget):
    # 登录成功信号,传递用户信息字典
    login_success = pyqtSignal(dict)

    def __init__(self):
        super().__init__()
        self.db = DatabaseManager()
        self.init_ui()

    def init_ui(self):
        """初始化登录窗口界面与全局样式"""
        self.setWindowTitle('资产管理系统 - 登录')
        self.setFixedSize(400, 430)
        
        layout = QVBoxLayout()
        # 系统标题
        title_label = QLabel('资产管理系统')
        title_label.setAlignment(Qt.AlignCenter)
        title_label.setStyleSheet("font-size: 24px; font-weight: bold; color: #343a40; margin: 20px;")
        layout.addWidget(title_label)

        # 登录/注册选项卡
        self.tabs = QTabWidget()
        login_tab = QWidget()
        self.setup_login_tab(login_tab)
        self.tabs.addTab(login_tab, "登录")
        
        register_tab = QWidget()
        self.setup_register_tab(register_tab)
        self.tabs.addTab(register_tab, "注册")
        
        layout.addWidget(self.tabs)
        self.setLayout(layout)

    def setup_login_tab(self, tab):
        """构建登录标签页表单"""
        layout = QFormLayout()
        layout.setSpacing(15)
        layout.setContentsMargins(30, 30, 30, 30)
        
        self.login_username = QLineEdit()
        self.login_username.setPlaceholderText("请输入用户名")
        layout.addRow("用户名:", self.login_username)
        
        self.login_password = QLineEdit()
        self.login_password.setPlaceholderText("请输入密码")
        self.login_password.setEchoMode(QLineEdit.Password)
        layout.addRow("密码:", self.login_password)
        
        login_btn = QPushButton('登录')
        login_btn.clicked.connect(self.handle_login)
        layout.addRow(login_btn)
        tab.setLayout(layout)

    def handle_login(self):
        """处理登录点击事件,调用数据库验证"""
        username = self.login_username.text().strip()
        password = self.login_password.text().strip()
        
        if not username or not password:
            QMessageBox.warning(self, '输入错误', '请输入用户名和密码')
            return
        
        success, result = self.db.validate_user(username, password)
        if success:
            if not isinstance(result, dict):
                result = {key: result[key] for key in result.keys()}
            result['login_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            self.login_success.emit(result)
            self.close()
        else:
            QMessageBox.warning(self, '登录失败', result)

4. 系统功能与界面展示

系统主界面采用标签页式布局,包含首页仪表盘、资产管理、条形码管理、资产操作、资产盘点、统计分析、系统设置七大模块,根据用户权限动态显示可用功能。

首页仪表盘以卡片形式直观展示总资产数、在用/闲置/维修/报废资产数量、资产总价值等核心指标;资产管理模块支持资产信息的增删改查与多条件组合查询;统计分析模块可生成状态分布、类别分布、部门分布等多维度可视化图表,支持一键导出。

完整的系统功能演示与操作流程,可在B站搜索:兵慌码乱,查看对应视频讲解。

5. 本地部署与运行步骤

  1. 环境准备:安装Python 3.9版本,配置好系统环境变量。

  2. 依赖安装:执行以下命令安装第三方依赖库

pip install pyqt5==5.15.9
pip install matplotlib==3.7.1
  1. 项目部署:按规范放置数据库目录、资源文件与源码模块,确保路径匹配。

  2. 启动运行:运行主程序入口文件,默认管理员账号:admin,默认密码:admin123

6. 项目总结与扩展方向

这套系统基于纯Python技术栈开发,开发效率高、部署成本低,非常适合作为计算机专业的毕设或课设项目。在此基础上,还可扩展二维码扫码盘点、资产折旧自动计算、云数据库同步、细粒度权限控制等功能,进一步提升项目亮点。

更多推荐