简介这份Qt工资管理系统源码包面向学习C与Qt桌面开发的学生及初级开发者用于完成课程设计或练手项目。系统实现了职工工资管理的基本流程包含录入、注册、登录、搜索、数据显示、修改以及总工资与平均工资统计并配有登录、注册、主界面、录入四个界面适合作为GUI编程与数据库操作的入门参考。压缩包共73个文件、约21.3MB其中5个cpp与4个h构成核心逻辑4个ui描述界面布局27个dll与21个qm为Qt运行库和多语言翻译文件另有exe可执行程序、qrc资源文件及db数据库文件结构完整可直接运行。目前已有1427人学习下载。读者可借此理解Qt信号槽、界面跳转与SQLite数据读写的组织方式并参考其工程配置与目录结构进行二次开发。需注意db文件为空时会影响登录可修改main直接进入主界面或自行添加数据。1. 一个桌面工资管理系统的真实落地场景如果你手头正好有一份 Qt 工资管理系统.zip想把它跑起来、看懂、再改成自己能用的版本那这篇拆解就是写给你的。这项目本质上是一个基于 Qt 的桌面端工资管理工具核心解决的是中小团队每月工资录入、计算、查询和导出这一整套流程。它不依赖浏览器双击 exe 就能用数据落在本地数据库里适合行政、财务或者小团队负责人直接上手。很多人第一次拿到这类源码包卡在环境配置和数据库连接上其实只要把 Qt 版本、编译套件和数据库驱动这三件事对齐后面就是顺着目录读代码的事。我拆过不少类似的 Qt 项目这个系统的结构算是比较典型的界面层、业务层、数据层分得清楚改起来不费劲。2. 技术选型与目录结构先看清这套 Qt 工程怎么搭的2.1 为什么是 Qt Widgets 而不是 QML这个项目用的是 Qt Widgets不是 QML。原因很直接工资管理是典型的表单密集型应用表格、输入框、下拉框、日期选择器这些控件Widgets 生态里现成的东西多QTableWidget、QTableView 配合 QSqlTableModel 能省掉大量手写代码。QML 做动画和移动端适配更顺手但放到这种以数据录入和查询为主的桌面工具上反而增加学习成本。项目里主窗口继承自 QMainWindow中间区域用 QTabWidget 分页把员工信息、工资录入、工资查询、报表导出分成几个独立页面每个页面一个独立的类互不干扰。常见做法是每个功能页对应一个 .ui 文件加一个 .h/.cpp 对编译时 uic 自动生成 ui_xxx.h。这样界面和逻辑分离改布局不用动业务代码。2.2 目录结构逐层拆解压后典型的目录长这样QtSalaryManager/ ├── QtSalaryManager.pro # qmake 工程文件 ├── main.cpp # 程序入口 ├── mainwindow.h / .cpp / .ui # 主窗口框架 ├── employee/ │ ├── employeedialog.h/.cpp/.ui # 员工增删改对话框 │ └── employeepage.h/.cpp/.ui # 员工列表页 ├── salary/ │ ├── salaryinputpage.h/.cpp/.ui # 工资录入页 │ ├── salaryquerypage.h/.cpp/.ui # 工资查询页 │ └── salarycalc.h/.cpp # 工资计算核心逻辑 ├── db/ │ ├── dbmanager.h/.cpp # 数据库连接与初始化 │ └── salarydao.h/.cpp # 数据访问对象 ├── export/ │ └── exporter.h/.cpp # 导出 Excel/CSV └── resources/ └── icons/ # 界面图标这个分层的好处是db 目录只管数据库salary 目录只管业务export 独立出来方便替换导出格式。你如果要加个「社保公积金自动计算」只需要在 salarycalc 里加方法界面层调一下就行不会牵一发动全身。2.3 .pro 文件里的关键配置QT core gui sql widgets greaterThan(QT_MAJOR_VERSION, 4): QT widgets TARGET QtSalaryManager TEMPLATE app SOURCES main.cpp \ mainwindow.cpp \ db/dbmanager.cpp \ salary/salarycalc.cpp HEADERS mainwindow.h \ db/dbmanager.h \ salary/salarycalc.h FORMS mainwindow.uiQT sql这行必须要有否则 QSqlDatabase 相关类编译不过。greaterThan(QT_MAJOR_VERSION, 4)是兼容 Qt4 和 Qt5 的写法如果你用 Qt6widgets 模块默认包含但 sql 还是要显式加。TARGET 是生成的 exe 名字TEMPLATE app 表示这是应用程序而不是库。注意Qt6 里 QTextCodec 被移除了如果项目里有中文编码转换的代码需要换成 QStringConverter 或者直接用 QString::fromUtf8。3. 数据库层与工资计算核心模块代码逐段讲3.1 数据库连接与建表dbmanager.cpp 里通常有一个单例或者静态方法负责打开 SQLite 数据库并建表。SQLite 的好处是零配置一个 .db 文件跟着程序走拷到 U 盘就能带走。// db/dbmanager.cpp bool DbManager::initDatabase(const QString dbPath) { QSqlDatabase db QSqlDatabase::addDatabase(QSQLITE); db.setDatabaseName(dbPath); // 例如 salary.db if (!db.open()) { qDebug() 打开数据库失败: db.lastError().text(); return false; } QSqlQuery query; // 员工表 query.exec(CREATE TABLE IF NOT EXISTS employee ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, dept TEXT, base_salary REAL DEFAULT 0, join_date TEXT)); // 工资记录表 query.exec(CREATE TABLE IF NOT EXISTS salary_record ( id INTEGER PRIMARY KEY AUTOINCREMENT, employee_id INTEGER, month TEXT, base REAL, bonus REAL, deduction REAL, actual REAL, FOREIGN KEY(employee_id) REFERENCES employee(id))); return true; }这里有两个关键点一是QSQLITE驱动名不能写错写错会提示 driver not loaded二是外键约束在 SQLite 里默认不生效需要执行PRAGMA foreign_keys ON;很多项目忘了这步删员工时工资记录变成孤儿数据。我一般会在 open 之后立刻执行这条 pragma。3.2 工资计算逻辑salarycalc.cpp 是业务核心负责根据基本工资、奖金、扣款算出实发。别看公式简单坑在浮点精度和四舍五入上。// salary/salarycalc.cpp double SalaryCalc::calcActual(double base, double bonus, double deduction) { double gross base bonus; // 应发 double actual gross - deduction; // 实发 // 保留两位小数避免 0.10.20.30000000000000004 return qRound(actual * 100.0) / 100.0; } // 批量计算某月所有员工 QListSalaryRecord SalaryCalc::calcMonth(const QString month) { QListSalaryRecord result; QSqlQuery query; query.prepare(SELECT e.id, e.name, e.base_salary, COALESCE(s.bonus,0), COALESCE(s.deduction,0) FROM employee e LEFT JOIN salary_record s ON e.id s.employee_id AND s.month ?); query.addBindValue(month); query.exec(); while (query.next()) { SalaryRecord rec; rec.employeeId query.value(0).toInt(); rec.name query.value(1).toString(); rec.base query.value(2).toDouble(); rec.bonus query.value(3).toDouble(); rec.deduction query.value(4).toDouble(); rec.actual calcActual(rec.base, rec.bonus, rec.deduction); result.append(rec); } return result; }qRound(actual * 100.0) / 100.0是 Qt 里常用的保留两位小数写法比 QString::number 再转回来更直接。LEFT JOIN 保证没有工资记录的员工也能出现在列表里奖金和扣款用 COALESCE 兜底为 0。参数用 addBindValue 绑定避免 SQL 注入也省去手动拼字符串的麻烦。3.3 界面层怎么调数据层以工资录入页为例点击「保存」按钮后界面层不直接写 SQL而是调 SalaryDao 的方法// salary/salaryinputpage.cpp void SalaryInputPage::onSaveClicked() { SalaryRecord rec; rec.employeeId ui-comboEmployee-currentData().toInt(); rec.month ui-dateMonth-date().toString(yyyy-MM); rec.base ui-spinBase-value(); rec.bonus ui-spinBonus-value(); rec.deduction ui-spinDeduction-value(); rec.actual SalaryCalc::calcActual(rec.base, rec.bonus, rec.deduction); SalaryDao dao; if (dao.insertOrUpdate(rec)) { QMessageBox::information(this, 提示, 保存成功); refreshTable(); } else { QMessageBox::warning(this, 错误, 保存失败请检查数据); } }这里 comboEmployee 用 currentData 拿员工 id而不是 currentText 拿名字因为名字可能重复。insertOrUpdate 内部先查该员工该月是否已有记录有则 UPDATE无则 INSERT避免同月重复录入。3.4 导出模块导出 CSV 是最简单的用 QFile 和 QTextStream 就能写。导出 Excel 则需要 QAxObjectWindows 限定或者第三方库。项目里如果只做了 CSV改起来也容易。// export/exporter.cpp bool Exporter::exportCsv(const QString filePath, const QListSalaryRecord records) { QFile file(filePath); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return false; QTextStream out(file); out.setCodec(UTF-8); // Qt5 写法Qt6 用 setEncoding out 姓名,月份,基本工资,奖金,扣款,实发\n; for (const auto r : records) { out r.name , r.month , r.base , r.bonus , r.deduction , r.actual \n; } file.close(); return true; }CSV 用 UTF-8 编码Excel 打开可能乱码解决办法是加 BOM 头或者导出时让用户选 GBK。我一般会在文件开头写\xEF\xBB\xBF三个字节Excel 就能正确识别中文。4. 编译运行与常见问题排查4.1 环境准备清单组件推荐版本说明Qt5.15 LTS 或 6.55.15 最稳6.x 注意 API 变化编译器MinGW 8.1 / MSVC 2019与 Qt 套件匹配IDEQt Creator直接打开 .pro 即可数据库SQLiteQt 自带驱动无需额外安装安装 Qt 时记得勾选 Qt Script 以外的默认组件SQL 模块在 Qt 5.15 里是默认包含的。如果用的是在线安装器把 MinGW 和 Sources 都勾上方便调试时看源码。4.2 从零跑起来的步骤第一步用 Qt Creator 打开 .pro 文件选择对应的 Kit。如果 Kit 前面有黄色感叹号说明编译器或 Qt 版本没配好去「工具-选项-Kits」里检查。第二步点左下角锤子图标编译。如果报cannot find -lQt5Sql说明 Qt 安装时没装 SQL 模块重新运行安装器补上。第三步编译通过后点绿色三角运行。首次运行会在 exe 同目录生成 salary.db 文件。如果程序闪退在 main.cpp 的 QApplication 之前加qDebug()输出或者用 Debug 模式跑看最后停在哪一行。第四步录入几条测试数据验证增删改查和导出是否正常。4.3 避坑记录我踩过的五个坑现象一编译报错QSqlDatabase: QSQLITE driver not loaded。原因Qt 安装目录下 plugins/sqldrivers 里没有 qsqlite.dll或者 exe 运行时找不到这个插件。 解决把 Qt 安装路径下的plugins/sqldrivers/qsqlite.dll拷到 exe 同目录的 sqldrivers 文件夹里或者用 windeployqt 工具自动打包依赖。现象二中文界面显示乱码。原因源文件编码和 Qt 解释编码不一致MSVC 默认按 GBK 读源码是 UTF-8。 解决在 .pro 里加QMAKE_CXXFLAGS /utf-8MSVC或QMAKE_CXXFLAGS -finput-charsetUTF-8MinGW并在 main.cpp 里设置QTextCodec::setCodecForLocale(QTextCodec::codecForName(UTF-8))。现象三工资计算出现 0.01 的误差。原因double 累加时的浮点精度问题。 解决所有金额在数据库里用整数存「分」显示时除以 100或者像前面那样用 qRound 统一处理。别用 float精度更差。现象四删除员工后工资查询里还能看到该员工的记录。原因SQLite 外键约束没开删员工时没级联删除工资记录。 解决在 initDatabase 里执行PRAGMA foreign_keys ON;建表时给 employee_id 加ON DELETE CASCADE。现象五导出 CSV 用 Excel 打开全是乱码。原因UTF-8 无 BOMExcel 默认按本地编码解析。 解决在写文件前先写入 BOM 头out \xEF\xBB\xBF;或者导出时提供 GBK 选项。提示每次改完 .pro 文件记得在 Qt Creator 里右键项目选「执行 qmake」否则新加的源文件不会参与编译。5. 二次开发从能跑到好用我改过的地方拿到这个系统后最值得动手改的有三个方向加社保公积金计算、换导出格式、做数据备份。我重点说第一个因为它涉及业务逻辑和数据库表结构的同时调整。5.1 加一个社保计算模块先在 salarycalc 里加一个方法按固定比例算个人缴纳部分// salary/salarycalc.cpp double SalaryCalc::calcSocialInsurance(double base) { const double pensionRate 0.08; // 养老 8% const double medicalRate 0.02; // 医疗 2% const double unemploymentRate 0.005; // 失业 0.5% double total base * (pensionRate medicalRate unemploymentRate); return qRound(total * 100.0) / 100.0; }然后在 salary_record 表里加一列social_insurance REAL DEFAULT 0录入界面加一个只读的显示框保存时自动算好写入。注意比例因地区而异我一般把比例做成配置项存在一个 settings 表里而不是硬编码。5.2 验证改造是否成功改完之后用一组已知数据手工验算基本工资 10000奖金 2000扣款 500社保按上面比例算出来是 1050实发应该是 100002000-500-105010450。在界面里录入同样的数看结果是否一致。再查数据库里的原始记录确认 social_insurance 字段有值。最后导出 CSV用文本编辑器打开确认列顺序和数值都对。5.3 一个让我长记性的教训有次我改完表结构直接覆盖了原来的 salary.db结果测试数据全没了。从那以后我每次动数据库结构之前都强制走一遍备份流程先把 salary.db 复制成 salary.db.bak再写一个 migrate 函数用ALTER TABLE ... ADD COLUMN增量修改而不是删表重建。增量迁移的代码大概长这样void DbManager::migrate() { QSqlQuery query; query.exec(PRAGMA table_info(salary_record)); bool hasSocial false; while (query.next()) { if (query.value(1).toString() social_insurance) hasSocial true; } if (!hasSocial) { query.exec(ALTER TABLE salary_record ADD COLUMN social_insurance REAL DEFAULT 0); } }这段代码先查表里有没有目标列没有才加重复运行也不会报错。配合备份文件就算改崩了也能五分钟内恢复。希望这个思路帮到你改别人的项目稳比快重要。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?