前言

对于计算机专业的同学来说,毕设选题常常纠结于功能复杂度与实现难度之间,尤其是GUI桌面类项目,既要保证功能完整,又要兼顾界面可用性。很多同学在网上找的免费源码要么结构混乱跑不通,要么缺少核心业务逻辑,难以满足毕设要求。 本文分享一套基于Python+PyQt5+SQLite实现的药房管理系统,覆盖药品进销存、销售管理、效期预警、数据统计等完整业务流程,代码结构清晰,非常适合用作Python方向的课程设计或毕业设计参考。

一、项目概述与技术栈

本系统是面向中小型药房的轻量级桌面管理工具,围绕药房日常运营核心流程,实现了用户认证、药品信息管理、销售登记与查询、效期智能预警、销售数据可视化统计五大核心模块,能够有效提升药品管理效率,降低人工出错概率。

核心技术栈

技术组件

版本/说明

作用

Python

3.8+

核心开发语言

PyQt5

5.15.9

图形界面框架,实现窗口与控件布局

SQLite

内置

嵌入式数据库,零配置单文件存储

PyQtChart

5.15.6

图表组件,实现销售趋势可视化

QSS样式表

-

统一界面风格,自定义控件外观

项目优势亮点

  • 轻量易部署:无需安装数据库服务,单文件即可运行,跨Windows/Linux平台兼容

  • 架构清晰:采用三层架构设计,业务逻辑与界面、数据层分离,便于二次开发

  • 功能完整:覆盖药房核心业务流程,包含数据统计与效期预警等增值功能

  • 界面友好:统一QSS美化,交互逻辑符合日常操作习惯,新手易上手

二、系统整体架构与核心流程

系统采用经典的三层软件架构,各层职责明确,耦合度低,便于维护与扩展。

  1. 表示层:由登录窗口、主窗口及各功能标签页组成,负责接收用户操作与展示数据。主窗口通过QTabWidget整合药品管理、销售管理、效期管理、数据统计四大功能模块,所有界面交互通过信号/槽机制与业务层通信。

  2. 业务逻辑层:封装核心业务规则校验与流程控制,例如库存充足性校验、销售事务协调、效期数据筛选等,是连接表示层与数据层的中间枢纽。

  3. 数据访问层:由独立的DatabaseManager类实现,封装所有SQLite数据库操作,对外提供标准化接口,内部使用参数化查询保证安全性,通过事务保证数据一致性。

此外还有工具函数模块与样式管理模块,分别提供通用日期计算、金额格式化等工具方法,以及全局样式统一定义,实现样式与逻辑解耦。

核心业务流程以销售登记为例:用户在界面选择药品与销售数量 → 业务层校验库存是否充足 → 调用数据层事务接口 → 同时扣减药品库存、写入销售历史记录 → 返回结果后同步刷新所有关联页面数据。

三、核心功能实现(附核心代码)

3.1 数据库事务性销售处理

销售操作涉及药品库存更新与销售记录写入两个步骤,必须保证原子性,否则容易出现库存已扣减但记录丢失,或记录已生成但库存未变的数据不一致问题。系统通过SQLite事务机制,将两个操作放在同一事务中执行,异常时自动回滚。

核心代码(DatabaseManager类record_sale方法):

def record_sale(self, drug_id, sell_quantity, sell_price, sell_amount, sell_date):
    """
    事务性记录销售:更新药品库存与累计销售,同时写入销售历史
    """
    with self.get_connection() as conn:
        cursor = conn.cursor()
        
        # 1. 查询当前药品库存与信息
        cursor.execute("SELECT stock, drug_name, spec, batch_no FROM drugs WHERE id = ?", (drug_id,))
        drug = cursor.fetchone()
        if not drug:
            raise ValueError("药品不存在")
        
        original_stock = drug['stock']
        if original_stock < sell_quantity:
            raise ValueError("库存不足")
        
        remaining_stock = original_stock - sell_quantity
        
        # 2. 更新药品表:扣减库存,更新累计销售数据
        cursor.execute("""
            UPDATE drugs 
            SET stock = stock - ?,
                sell_quantity = sell_quantity + ?,
                sell_amount = sell_amount + ?,
                sell_date = ?
            WHERE id = ?
        """, (sell_quantity, sell_quantity, sell_amount, sell_date, drug_id))
        
        # 3. 写入销售历史记录,冗余存储药品信息便于追溯
        cursor.execute("""
            INSERT INTO sales_history 
            (drug_id, drug_name, spec, batch_no, sell_quantity, sell_price, sell_amount, 
             sell_date, original_stock, remaining_stock)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
        """, (drug_id, drug['drug_name'], drug['spec'], drug['batch_no'],
              sell_quantity, sell_price, sell_amount, sell_date,
              original_stock, remaining_stock))
        
        # 上下文管理器退出时自动提交,异常则自动回滚
        return True

3.2 效期预警与表格高亮逻辑

效期管理是药房系统的核心实用功能,系统通过计算有效期与当前日期的差值,自动筛选临期药品,并根据剩余天数为表格行设置不同背景色,实现视觉化预警。

核心工具函数与渲染逻辑:

def calculate_expiry_days(valid_date_str):
    """计算距离有效期的剩余天数,正数为未过期,负数为已过期"""
    try:
        valid_date = datetime.strptime(valid_date_str, "%Y-%m-%d").date()
        today = date.today()
        return (valid_date - today).days
    except ValueError:
        return -1

# 表格行渲染逻辑片段
remaining_days = calculate_expiry_days(drug['valid_date'])
# 根据剩余天数设置背景色
if remaining_days < 0:
    # 已过期:红色背景
    for col in range(table.columnCount()):
        table.item(row, col).setBackground(QColor("#f8d7da"))
elif 0 <= remaining_days <= 7:
    # 7天内过期:黄色背景
    for col in range(table.columnCount()):
        table.item(row, col).setBackground(QColor("#fff3cd"))
elif 8 <= remaining_days <= 30:
    # 30天内过期:橙色背景
    for col in range(table.columnCount()):
        table.item(row, col).setBackground(QColor("#ffe5d0"))

3.3 基于信号/槽的模块间解耦

PyQt的信号/槽机制是实现模块解耦的核心,系统通过自定义信号实现登录窗口与主窗口的通信,以及主窗口内各标签页的数据同步刷新,避免模块间直接依赖。

登录成功信号定义与触发:

from PyQt5.QtCore import pyqtSignal, QMainWindow

class LoginWindow(QMainWindow):
    # 自定义登录成功信号,传递用户名
    login_success = pyqtSignal(str)
    
    def handle_login(self):
        username = self.login_username_input.text().strip()
        password = self.login_password_input.text().strip()
        
        if not username or not password:
            QMessageBox.warning(self, '登录失败', '用户名和密码不能为空!')
            return
        
        if self.db_manager.authenticate_user(username, password):
            self.current_user = username
            # 发射登录成功信号,通知主窗口打开
            self.login_success.emit(username)
            self.close()
        else:
            QMessageBox.warning(self, '登录失败', '用户名或密码错误!')

四、系统功能界面展示

  1. 登录注册模块:支持新用户注册与已注册用户登录验证,输入校验完善,界面简洁直观,注册时自动校验用户名唯一性与密码格式。

  2. 药品信息管理:表格化展示所有药品信息,支持按名称、批号模糊搜索,可完成药品信息的添加、编辑、删除操作,库存与效期异常时自动标红提示。

  3. 销售管理:左侧完成销售登记,选择药品后自动显示规格、单价与库存,输入数量自动计算金额;右侧支持按日期、金额、药品名多条件查询销售记录,可导出CSV文件。

  4. 效期管理:支持按30天/60天/90天内过期、已过期等条件筛选,表格行自动着色预警,一眼识别临期药品,支持导出效期数据存档。

  5. 数据统计:自定义统计日期范围,通过卡片展示药品种类数、总销量、总销售额、销售次数,同时展示药品销售排行榜与每日销售趋势柱状图,经营数据一目了然。

对应的系统全功能操作演示、部署步骤实拍视频,我也同步更新在了B站账号兵慌码乱,想看动态运行效果、跟着视频一步步部署的同学,可以自行搜索查看。

五、本地部署与运行步骤

环境要求

  • Python 3.8 及以上版本

  • Windows / Linux / macOS 系统均可运行

部署步骤

  1. 安装项目依赖

pip install PyQt5==5.15.9
pip install PyQtChart==5.15.6
  1. 将项目源码下载到本地,进入项目根目录

  2. 执行主程序启动

python main.py
  1. 首次运行可调用测试数据生成方法,快速体验完整功能

六、项目总结与扩展方向

项目总结

本系统完整实现了中小型药房的核心管理需求,技术选型贴合Python技术栈,架构设计规范,代码模块化程度高,既可以直接作为课程设计、毕业设计的参考项目,也可以根据实际业务需求进行二次功能扩展。

可扩展方向

  • 密码安全升级:引入哈希加盐算法存储用户密码,提升系统安全性

  • 角色权限管理:增加管理员、普通员工角色,区分操作权限

  • 进货与利润统计:增加入库管理模块,记录进货价,自动计算销售利润

  • 报表打印功能:集成打印组件,支持销售日报、月报的打印输出

文末总结

完整的全量源码、配套资料已整理完毕,开箱即用,适合直接用作毕设或课程设计;需要完整版本的同学,也可以留意我的主页简介信息。

更多推荐