基于 Qt 的智慧社区物业管理系统
项目描述
这是一个面向物业公司的社区管理桌面软件,实现了业主信息管理、房屋管理、车位管理、缴费管理、报修管理等核心业务功能。系统支持管理员、员工、业主三种角色登录,不同角色拥有不同权限。
项目描述:
基于 Qt 框架开发的桌面端物业管理系统,支持业主、管理员、工作人员三端登录
实现业主信息管理、房屋管理、物业费缴纳、报修工单流转、车位申请等核心功能
采用 MVC 设计模式,使用 QSqlTableModel 实现数据与界面分离
使用 SHA-256 加密用户密码,防止 SQL 注入,保证数据安全
运用 Qt 样式表(QSS)美化界面,提升用户体验
个人贡献:
独立完成数据库表设计和核心业务逻辑开发
实现了业主管理、缴费管理、报修管理 3 个核心模块
优化了数据库查询性能,支持 10000+ 条数据流畅显示
编写了完整的代码注释和技术文档
系统版本
技术栈:Qt 6.10.3 / C++ / SQLite / SQL
核心职责
负责登录模块开发:实现三种角色(管理员/员工/业主)的身份认证和权限控制。
负责业主管理模块:实现业主信息的增删改查功能,使用QTableWidget展示数据列表,通过QDialog弹出编辑窗口。
负责数据库设计:设计并创建 SQLite 数据库,包含 `worker`、`owner`、`house`、`carstation`、`pay`、`issue` 等数据表,使用 `QSqlDatabase` 和 `QSqlQuery` 进行操作。
负责界面优化:使用 Qt Designer 设计友好的用户界面,优化用户体验。
项目功能演示
1. 登录界面
2. 尝试登录
你可以尝试以下默认账号(具体看数据库中有什么数据):
角色 用户名 密码 管理员 admin 123456(或 admin) 业主 1001 123456 没有注册账号的话会显示没有此账号
3. 探索功能模块
登录后,尝试以下操作:
业主管理 - 添加、编辑、删除业主
缴费管理 - 查看缴费记录
自助缴费 - 输入金额,选择类型,点击确认
核心功能测试清单
功能 测试步骤 预期结果 登录 输入正确的用户名密码 进入主界面 添加业主 点击"添加"→输入信息→保存 列表中出现新业主 自助缴费 选择类型→输入金额→点击确认 弹出"缴费成功"提示 退出 点击退出按钮 关闭窗口
代码
1.登录功能模块
logindialog.h
原始版本一
cpp#ifndef LOGINDIALOG_H #define LOGINDIALOG_H #include <QDialog> #include <QMessageBox> #include <QButtonGroup> #include <QSqlQuery> #include <QSqlTableModel> #include <QSqlRecord> #include <QDebug> #include "managermanage.h" #include "workermanage.h" #include "ownermanage.h" namespace Ui { class LoginDialog; } //登录对话框LoginDialog类,公有继承自QDialog类 class LoginDialog : public QDialog { Q_OBJECT public: /***************explicit关键字******************** * explicit是C++语言关键字,用于组织函数的隐式转换 * 调用。使用此关键词的构造函数,就不能再使用隐式转换 * 了。 * 在C++中,一个带参构造函数有两个作用,第一个充当 * 构造器;第二个是默认且隐含的类型转换操作符。为了 * 避免构造错误,很多时候我们需要禁止。 * ************************************************/ explicit LoginDialog(QWidget *parent = 0); //构造函数 ~LoginDialog(); //析构函数 void clearAll(); //清除窗口用户输入内容函数 bool judgeEmpty(); //判断用户输入内容是否为空函数 private: Ui::LoginDialog *ui; /***************主界面***************************** * 从登录对话框进入的界面,就三种,分别是管理员界面、 *工作人员界面和用户界面,不同身份登陆不同的系统界面, *完成不同的应用功能。 *************************************************/ //定义指向 管理界面类对象 的指针manager ManagerManage *manager; //定义指向 工作人员界面类对象 的指针worker WorkerManage *worker; //定义指向 业主界面类对象 的指针owner OwnerManage *owner; /*定义按键组指针radioGroup,指向登陆对话框中, *由管理者、工作人员和用户共同组成的按键组**/ QButtonGroup *radioGroup; QSqlTableModel *model;//该模式并未使用???????????????? signals: void toManagerManage(QString,QString); void toWorkerManage(QString,QString); void toOwnnerManage(QString,QString); private slots: void exitbtnSlot(); //退出按键按下信号触发的槽函数 void loginbtnSlot();//登录按键按下信号触发的槽函数 }; #endif // LOGINDIALOG_H修复版本二
无注释版
cpp#ifndef LOGINDIALOG_H #define LOGINDIALOG_H #include <QDialog> #include <QButtonGroup> #include <QSqlQuery> #include <QSettings> class ManagerManage; class WorkerManage; class OwnerManage; namespace Ui { class LoginDialog; } class LoginDialog : public QDialog { Q_OBJECT public: explicit LoginDialog(QWidget *parent = 0); ~LoginDialog(); void clearAll(); bool judgeEmpty(); private slots: void exitbtnSlot(); void loginbtnSlot(); private: Ui::LoginDialog *ui; ManagerManage *manager; WorkerManage *worker; OwnerManage *owner; QButtonGroup *radioGroup; void loginAsAdmin(const QString &username, const QString &password); void loginAsWorker(const QString &username, const QString &password); void loginAsOwner(const QString &username, const QString &password); void clearInput(); void loadSettings(); void saveSettings(); }; #endif // LOGINDIALOG_H有注释版
cpp// ============================================================ // 文件:logindialog.h // 功能:登录对话框类的头文件声明 // 说明:定义了登录对话框的类结构、成员变量和函数接口 // ============================================================ #ifndef LOGINDIALOG_H // 作用:防止头文件被多次包含(Include Guard) // 原理:如果 LOGINDIALOG_H 未定义,则定义它并包含头文件内容 // 如果已经定义,则跳过整个头文件,避免重复定义错误 // 这是 C/C++ 头文件的标准写法,避免编译错误 #define LOGINDIALOG_H // 定义宏 LOGINDIALOG_H // 与 #ifndef 配对,表示这个头文件已经被包含过一次 // 如果再次包含,由于 LOGINDIALOG_H 已定义,会跳过整个文件内容 // ============================================================ // 头文件包含 // ============================================================ #include <QDialog> // 包含 QDialog 基类 // QDialog 是 Qt 中对话框的基类,提供模态/非模态显示、返回值(exec())等功能 // 继承自 QWidget,所以也拥有所有 QWidget 的特性(信号、槽、事件等) // 本类 LoginDialog 需要继承 QDialog 来实现登录对话框 #include <QButtonGroup> // 包含 QButtonGroup 类 // QButtonGroup 用于管理一组按钮,实现单选互斥效果 // 在本类中用于管理"管理员/工作人员/业主"三个单选按钮 // 通过 checkedId() 可以获取用户选中的角色 ID #include <QSqlQuery> // 包含 QSqlQuery 类 // QSqlQuery 用于执行 SQL 查询和操作数据库 // 在头文件中包含是为了类型完整性,实际使用在 .cpp 中 // 虽然不一定要在头文件中包含,但为了方便保留 #include <QSettings> // 包含 QSettings 类,用于读写配置文件 // QSettings 是 Qt 提供的跨平台配置管理类 // Windows: 存储在注册表 HKEY_CURRENT_USER/Software/MyCompany/AppName // Linux: 存储在 ~/.config/MyCompany/AppName.conf // macOS: 存储在 ~/Library/Preferences/MyCompany/AppName.plist // 本类用于实现"记住密码"功能 // ============================================================ // 前向声明(Forward Declaration) // 作用:告诉编译器这些类存在,但不需要知道它们的完整定义 // 优点: // 1. 减少编译依赖,加快编译速度 // 2. 避免循环包含(A 包含 B,B 又包含 A) // 3. 降低头文件之间的耦合度 // 4. 因为这里只使用指针,不需要知道类的完整定义 // ============================================================ class ManagerManage; // 前向声明 ManagerManage 类(管理员管理界面) // 这里只需要知道它是一个类,用于声明指针 // 完整的定义在 managermanage.h 中,在 .cpp 中才包含 // 如果在这里包含 managermanage.h,会拖慢编译速度 class WorkerManage; // 前向声明 WorkerManage 类(工作人员管理界面) // 用于声明 WorkerManage 类型的指针 worker // 同样,完整定义在 workermanage.h 中 class OwnerManage; // 前向声明 OwnerManage 类(业主管理界面) // 用于声明 OwnerManage 类型的指针 owner // 完整定义在 ownermanage.h 中 // ============================================================ // UI 命名空间声明 // ============================================================ namespace Ui { // 定义 Ui 命名空间,用于存放由 .ui 文件生成的类 // 这样可以将界面相关代码与业务逻辑代码分离 class LoginDialog; // 声明 UI 类 LoginDialog // 这个类由 Qt 的 uic 工具根据 logindialog.ui 文件自动生成 // 包含了界面上所有控件的指针(按钮、输入框、标签等) // 通过 Ui::LoginDialog *ui 访问界面控件 // 例如:ui->userLine, ui->passwordLine, ui->loginBtn 等 } // ============================================================ // LoginDialog 类定义 // 继承自 QDialog,所以拥有对话框的所有特性 // ============================================================ class LoginDialog : public QDialog // class LoginDialog : 定义一个名为 LoginDialog 的类 // public QDialog : 公有继承自 QDialog 基类 // 公有继承意味着 QDialog 的所有公有成员在 LoginDialog 中也是公有的 // QDialog 提供 exec() 方法以模态方式显示对话框 { Q_OBJECT // Qt 元对象宏(Meta-Object Macro) // 作用:启用 Qt 的元对象系统(Meta-Object System) // 具体功能: // 1. 支持信号(signals)和槽(slots)机制 // 2. 支持运行时类型信息(RTTI):qobject_cast<> // 3. 支持属性系统(Q_PROPERTY) // 4. 支持动态翻译(tr()) // 5. 支持对象树内存管理 // 注意:任何使用信号槽的类都必须包含 Q_OBJECT 宏 // 且需要由 moc(元对象编译器)处理 // 如果忘记写 Q_OBJECT,编译时会出现信号槽相关的错误 public: // ============================================================ // public 区域:对外公开的接口 // 其他类可以访问这些成员 // ============================================================ explicit LoginDialog(QWidget *parent = 0); // 构造函数 // explicit: 禁止隐式类型转换 // 例如:LoginDialog d = 0; 会编译错误 // 必须显式调用:LoginDialog d(0); 或 new LoginDialog(this) // 这是 C++ 的最佳实践,避免意外的类型转换 // QWidget *parent = 0: 父窗口指针,默认值为 nullptr(0) // 父对象为 nullptr 时,窗口独立显示 // 父对象不为 nullptr 时,窗口作为子窗口,随父窗口一起销毁 // 在 Qt 中,对象树由父对象管理内存 ~LoginDialog(); // 析构函数 // 当对象被销毁时自动调用 // 负责释放资源(如 delete ui) // 在 Qt 中,析构函数还会自动销毁所有子对象(Qt 对象树机制) void clearAll(); // 清空所有输入框的内容 // 公共函数,外部可以调用 // 用于在登录失败或需要重置时清空用户输入 // 实现:ui->userLine->clear() + ui->passwordLine->clear() // 并将焦点设置到用户名输入框 bool judgeEmpty(); // 判断用户名和密码是否为空 // 返回值:true - 都不为空,false - 至少有一个为空 // 公共函数,外部可以调用 // 用于在登录前验证输入 // 会弹出警告框提示用户输入完整信息 private slots: // ============================================================ // private slots 区域:私有的槽函数 // 特点: // 1. 只能在类内部被调用(外部不能直接调用) // 2. 可以连接到信号,当信号触发时被自动调用 // 3. 在 Qt 中,槽函数可以是 public/protected/private // 4. 建议使用 private slots 来封装内部逻辑 // (外部可以通过信号间接调用,但无法直接调用) // ============================================================ void exitbtnSlot(); // 退出按钮的槽函数 // 当用户点击"退出"按钮时,此函数被调用 // 功能:显示确认对话框 → 用户确认后关闭登录对话框,退出程序 // 通过 QMessageBox::question() 询问用户是否确认退出 // 如果用户点击"是",则调用 this->close() 关闭窗口 void loginbtnSlot(); // 登录按钮的槽函数 // 当用户点击"登录"按钮时,此函数被调用 // 功能:验证用户名密码,根据角色跳转到对应的主界面 // 这是整个登录流程的核心函数 // 流程: // 1. 调用 judgeEmpty() 验证输入 // 2. 获取用户名、密码、角色 ID // 3. 使用 switch 根据角色分发到三个具体登录函数 // 4. 登录成功后隐藏登录对话框,显示主界面 private: // ============================================================ // private 区域:私有的成员变量和函数 // 只能在类内部访问,外部不可见 // 体现了面向对象的封装性(Encapsulation) // 隐藏内部实现细节,只暴露必要的接口 // ============================================================ // ============================================================ // UI 对象指针 // ============================================================ Ui::LoginDialog *ui; // UI 对象指针 // 指向由 uic 工具生成的 UI 类对象 // 通过这个指针可以访问界面上所有的控件 // 例如:ui->userLine(用户名输入框)、ui->passwordLine(密码输入框) // ui->loginBtn(登录按钮)、ui->exitBtn(退出按钮) // ui->managerRadio(管理员单选按钮) // ui->rememberPwdCheckBox(记住密码复选框) // 注意:这个指针需要在构造函数中用 new 创建,在析构函数中用 delete 释放 // 这是 Qt 中 UI 指针的标准用法 // ============================================================ // 主界面指针(多态用法) // ============================================================ ManagerManage *manager; // 管理员管理界面的指针 // 当管理员登录成功后,创建 ManagerManage 对象 // 指向管理员的主窗口 // ManagerManage 是管理员功能的主界面,包含:业主管理、缴费管理、工作人员管理等 // 类型为 ManagerManage*,实际指向一个 QWidget 子类对象 WorkerManage *worker; // 工作人员管理界面的指针 // 当工作人员登录成功后,创建 WorkerManage 对象 // 指向工作人员的主窗口 // WorkerManage 是工作人员功能的主界面,包含:工单处理、任务查看等 // 类型为 WorkerManage*,实际指向一个 QWidget 子类对象 OwnerManage *owner; // 业主管理界面的指针 // 当业主登录成功后,创建 OwnerManage 对象 // 指向业主的主窗口 // OwnerManage 是业主功能的主界面,包含:信息查看、缴费、报修等 // 类型为 OwnerManage*,实际指向一个 QWidget 子类对象 // ============================================================ // 按钮组 // ============================================================ QButtonGroup *radioGroup; // 角色选择按钮组 // 管理三个单选按钮:管理员、工作人员、业主 // 功能: // 1. 实现单选互斥(同一时间只能选一个) // 2. 通过 checkedId() 获取当前选中的角色 ID // 3. ID 值:0-管理员,1-工作人员,2-业主 // 在构造函数中初始化: // radioGroup->addButton(ui->managerRadio, 0); // radioGroup->addButton(ui->workerRadio, 1); // radioGroup->addButton(ui->ownerRadio, 2); // ============================================================ // 私有辅助函数 // 用于将复杂的登录逻辑拆分为多个小函数 // 遵循单一职责原则(Single Responsibility Principle),每个函数只做一件事 // ============================================================ void loginAsAdmin(const QString &username, const QString &password); // 管理员登录逻辑 // 参数:username - 用户名,password - 密码 // const QString&:使用常量引用,避免复制,提高性能 // 功能: // 1. 在 worker 表中查询用户(SELECT * FROM worker WHERE workernum = ?) // 2. 验证密码是否正确 // 3. 验证是否为管理员(workertype = "是") // 4. 验证通过后创建 ManagerManage 主窗口 // 5. 调用 saveSettings() 保存记住密码设置 // 如果任何验证失败,弹出对应的错误提示 void loginAsWorker(const QString &username, const QString &password); // 工作人员登录逻辑 // 参数:username - 用户名,password - 密码 // 功能: // 1. 在 worker 表中查询用户(SELECT * FROM worker WHERE workernum = ?) // 2. 验证密码是否正确 // 3. 验证通过后创建 WorkerManage 主窗口 // 4. 调用 saveSettings() 保存记住密码设置 // 注意:不需要检查 workertype,任何 worker 表中的用户都可以登录为工作人员 void loginAsOwner(const QString &username, const QString &password); // 业主登录逻辑 // 参数:username - 用户名,password - 密码 // 功能: // 1. 在 houseowner 表中查询用户(SELECT * FROM houseowner WHERE ownername = ?) // 2. 验证密码是否正确 // 3. 验证通过后创建 OwnerManage 主窗口 // 4. 调用 saveSettings() 保存记住密码设置 // houseowner 表结构与 worker 表不同,单独查询 void clearInput(); // 清空输入框并设置焦点 // 功能: // 1. 清空用户名输入框(ui->userLine->clear()) // 2. 清空密码输入框(ui->passwordLine->clear()) // 3. 将焦点设置到用户名输入框(ui->userLine->setFocus()) // 使用场景:密码错误时调用,让用户重新输入 // 与 clearAll() 的区别:clearAll() 是公共接口,clearInput() 是内部辅助 // ============================================================ // ✅ 新增:记住密码相关函数 // ============================================================ void loadSettings(); // 加载保存的登录信息 // 使用 QSettings 从配置文件/注册表读取: // - username: 上次登录的用户名 // - password: 上次登录的密码 // - remember: 是否勾选了"记住密码" // 在构造函数中被调用,实现自动填充用户名和密码 // 如果 remember 为 true,则自动填入密码并勾选复选框 // 如果 remember 为 false,只填入用户名(不自动登录) void saveSettings(); // 保存登录信息到配置文件 // 使用 QSettings 写入配置文件/注册表: // - 如果勾选了"记住密码":保存 username、password、remember=true // - 如果取消了"记住密码":清除 username、password,保存 remember=false // 在登录成功后被调用,由三个登录函数触发 // 保证用户下次打开程序时能自动填充 }; #endif // LOGINDIALOG_H // 结束 #ifndef LOGINDIALOG_H 条件编译 // 如果头文件被重复包含,从 #ifndef 到 #endif 之间的内容会被跳过 // 这是 C/C++ 头文件的标准写法,确保头文件只被编译一次1.logindialog.cpp
原始版本一
cpp#include "logindialog.h" #include "ui_logindialog.h" /************登录对话框类LoginDialog的构造函数****************/ LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog) { ui->setupUi(this); //新建一个按键组空间并赋值给radioGroup。父类为登录对话框 radioGroup=new QButtonGroup(this); //添加"管理者" 按键,ID设置为0. radioGroup->addButton(ui->managerRadio,0); //添加"工作人员"按键,ID设置为1. radioGroup->addButton(ui->workerRadio,1); //添加"业主" 按键,ID设置为2. radioGroup->addButton(ui->ownerRadio,2); //为登录按钮和退出按钮的"按下信号",设置对应槽函数。 connect(ui->loginBtn,SIGNAL(clicked()),this,SLOT(loginbtnSlot())); connect(ui->exitBtn,SIGNAL(clicked()),this,SLOT(exitbtnSlot())); } /************登录对话框类LoginDialog的析构函数****************/ LoginDialog::~LoginDialog() { delete ui; } /************《槽函数》登录窗口的用户登录操作*****************/ void LoginDialog::loginbtnSlot() { if(!this->judgeEmpty()) //判断用户名和密码输入是否为空 { ui->passwordLine->clear(); //有一个为空,则清除密码区内容 return; } //输出当前身份按键的ID编号,管理者为0,工作人员为1,业主为2 qDebug() << "radioGroup->checkedId() :" << radioGroup->checkedId(); //判断身份为"管理员"登录 if(radioGroup->checkedId()==0) { //创建数据库操作对象,操作的数据库为默认数据库 QSqlQuery query; //使用位置绑定方式,将userLine账号内容放入select语句的?位置做替换 query.prepare("select * from worker where workernum=?"); query.addBindValue(ui->userLine->text().trimmed()); query.exec(); //执行SQL语句,将用户输入名与数据库中一致的数据筛选出来。 if(query.next())//select筛选的结果中,一直有数据取出 { /*********worker表结构********************************** * 数据库中worker表共有4字段(列),从左向右依此表示为 * workernum workerpass workerphone workertypr * 用户名 密码 电话 是/否管理员 *******************************************************/ //判断用户输入密码与数据库中该用户密码是否一致。是,进入执行语句 if (query.value(1).toString() == ui->passwordLine->text()) { //如果账户和密码正确,则判断一下,该账户是否是管理员账户 if(query.value(3).toString()=="否") { //虽然账户密码正确,但不是管理员账户,则输出警告窗口 QMessageBox::warning(this, tr("此用户非管理员"), tr("请选择合适权限用户登录"), QMessageBox::Ok); return; } //账号密码正确,且是管理员账户。则创建管理员登录窗口 manager=new ManagerManage; //创建管理员窗口 manager->show(); //显示管理员窗口 this->hide(); //隐藏当前登录对话框 return; } //判断账号或密码不一致 else { //输出警告窗口,提示账号或密码错误信息 QMessageBox::warning(this, tr("账号密码错误"), tr("请输入正确的账号密码再登录!"), QMessageBox::Ok); ui->userLine->clear(); //清空用户在账户区输入内容 ui->passwordLine->clear();//清空用户在密码区输入的内容 ui->userLine->setFocus(); //将光标定位到用户名输入区 } } else //select筛选的结果中,已经没有数据取出,则显示信息窗口,提示没有账号。 QMessageBox::information(this,tr("提示"),tr("没有此账号!"),QMessageBox::Ok); } //判断是"工作人员"登录 else if(radioGroup->checkedId()==1) { QSqlQuery query; query.prepare("select * from worker where workernum=?"); query.addBindValue(ui->userLine->text()); query.exec(); if(query.next()) { if (query.value(1).toString() == ui->passwordLine->text()) { //创建工作人员登录窗口 worker=new WorkerManage; worker->setWindowTitle(ui->userLine->text()); worker->show(); this->hide(); return; } else { QMessageBox::warning(this, tr("账号密码错误"), tr("请输入正确的账号密码再登录!"), QMessageBox::Ok); ui->userLine->clear(); ui->passwordLine->clear(); ui->userLine->setFocus(); } } else QMessageBox::information(this,tr("提示"),tr("没有此账号!"),QMessageBox::Ok); } //判断是业主登录 else if(radioGroup->checkedId()==2) { QSqlQuery query; query.prepare("select * from houseowner where ownername=?"); query.addBindValue(ui->userLine->text()); query.exec(); if(query.next()) { if (query.value(1).toString() == ui->passwordLine->text()) { //创建业主登录窗口 owner=new OwnerManage; owner->setWindowTitle(ui->userLine->text()); owner->show(); this->hide(); return; } else { QMessageBox::warning(this, tr("账号密码错误"), tr("请输入正确的账号密码再登录!"), QMessageBox::Ok); ui->userLine->clear(); ui->passwordLine->clear(); ui->userLine->setFocus(); } } else QMessageBox::information(this,tr("提示"),tr("没有此账号!"),QMessageBox::Ok); } else QMessageBox::warning(this,"警告","请选择登录方式",QMessageBox::Yes); } /************《槽函数》关闭登录窗口**************************/ void LoginDialog::exitbtnSlot() { this->close(); //关闭串口 } /************清除登录窗口中用户输入的内容************/ void LoginDialog::clearAll() { ui->userLine->clear(); //清除ui中"userLine"对象的数据内容 ui->passwordLine->clear(); //清除密码 } /************判断用户输入的内容是否为空**************/ bool LoginDialog::judgeEmpty() { if(ui->userLine->text().isEmpty()) //如果用户名内容为空 { //为登录对话框,创建警告窗口,内容为:"用户名不能为空" QMessageBox::warning(this,"警告","用户名不能为空"); return false; //返回错误 } if(ui->passwordLine->text().isEmpty()) //密码为空 { QMessageBox::warning(this,"警告","密码不能为空"); return false; } else //如果用户名区域和密码区域都有内容,返回true return true; }修复版本二
无注释版
cpp#include "logindialog.h" #include "ui_logindialog.h" #include <QSqlQuery> #include <QSqlError> #include <QMessageBox> #include <QDebug> #include "managermanage.h" #include "workermanage.h" #include "ownermanage.h" #include <QSettings> LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), ui(new Ui::LoginDialog) { ui->setupUi(this); radioGroup = new QButtonGroup(this); radioGroup->addButton(ui->managerRadio, 0); radioGroup->addButton(ui->workerRadio, 1); radioGroup->addButton(ui->ownerRadio, 2); connect(ui->loginBtn, &QPushButton::clicked, this, &LoginDialog::loginbtnSlot); connect(ui->exitBtn, &QPushButton::clicked, this, &LoginDialog::exitbtnSlot); ui->managerRadio->setChecked(true); ui->passwordLine->setEchoMode(QLineEdit::Password); ui->passwordLine->setPlaceholderText("请输入密码"); ui->userLine->setPlaceholderText("请输入用户名"); loadSettings(); } LoginDialog::~LoginDialog() { delete ui; } void LoginDialog::loadSettings() { QSettings settings("MyCompany", "IntelligentCommunity"); QString username = settings.value("username", "").toString(); QString password = settings.value("password", "").toString(); bool remember = settings.value("remember", false).toBool(); if (!username.isEmpty()) { ui->userLine->setText(username); } if (remember) { ui->passwordLine->setText(password); ui->rememberPwdCheckBox->setChecked(true); } qDebug() << "加载配置: 用户名=" << username << ", 记住密码=" << remember; } void LoginDialog::saveSettings() { QSettings settings("MyCompany", "IntelligentCommunity"); if (ui->rememberPwdCheckBox->isChecked()) { settings.setValue("username", ui->userLine->text().trimmed()); settings.setValue("password", ui->passwordLine->text().trimmed()); settings.setValue("remember", true); qDebug() << "保存密码到配置"; } else { settings.remove("username"); settings.remove("password"); settings.setValue("remember", false); qDebug() << "清除保存的密码"; } } void LoginDialog::loginbtnSlot() { if (!judgeEmpty()) { ui->passwordLine->clear(); ui->passwordLine->setFocus(); return; } QString username = ui->userLine->text().trimmed(); QString password = ui->passwordLine->text().trimmed(); int roleId = radioGroup->checkedId(); qDebug() << "当前选中角色 ID:" << roleId; switch (roleId) { case 0: loginAsAdmin(username, password); break; case 1: loginAsWorker(username, password); break; case 2: loginAsOwner(username, password); break; default: QMessageBox::warning(this, "警告", "请选择登录身份!", QMessageBox::Ok); break; } } void LoginDialog::loginAsAdmin(const QString &username, const QString &password) { QSqlQuery query; query.prepare("SELECT * FROM worker WHERE workernum = ?"); query.addBindValue(username); if (!query.exec()) { qDebug() << "SQL 查询失败:" << query.lastError().text(); QMessageBox::critical(this, "错误", "数据库查询失败!"); return; } if (!query.next()) { QMessageBox::information(this, "提示", "没有此账号!", QMessageBox::Ok); return; } if (query.value(1).toString() != password) { QMessageBox::warning(this, "账号密码错误", "请输入正确的账号密码再登录!", QMessageBox::Ok); clearInput(); return; } if (query.value(3).toString() == "否") { QMessageBox::warning(this, "权限不足", "该账号不是管理员,请选择合适权限登录!", QMessageBox::Ok); return; } saveSettings(); manager = new ManagerManage; manager->show(); this->hide(); qDebug() << "管理员登录成功:" << username; } void LoginDialog::loginAsWorker(const QString &username, const QString &password) { QSqlQuery query; query.prepare("SELECT * FROM worker WHERE workernum = ?"); query.addBindValue(username); if (!query.exec()) { qDebug() << "SQL 查询失败:" << query.lastError().text(); QMessageBox::critical(this, "错误", "数据库查询失败!"); return; } if (!query.next()) { QMessageBox::information(this, "提示", "没有此账号!", QMessageBox::Ok); return; } if (query.value(1).toString() != password) { QMessageBox::warning(this, "账号密码错误", "请输入正确的账号密码再登录!", QMessageBox::Ok); clearInput(); return; } saveSettings(); worker = new WorkerManage; worker->setWindowTitle(username); worker->show(); this->hide(); qDebug() << "工作人员登录成功:" << username; } void LoginDialog::loginAsOwner(const QString &username, const QString &password) { QSqlQuery query; query.prepare("SELECT * FROM houseowner WHERE ownername = ?"); query.addBindValue(username); if (!query.exec()) { qDebug() << "SQL 查询失败:" << query.lastError().text(); QMessageBox::critical(this, "错误", "数据库查询失败!"); return; } if (!query.next()) { QMessageBox::information(this, "提示", "没有此账号!", QMessageBox::Ok); return; } if (query.value(1).toString() != password) { QMessageBox::warning(this, "账号密码错误", "请输入正确的账号密码再登录!", QMessageBox::Ok); clearInput(); return; } saveSettings(); owner = new OwnerManage; owner->setWindowTitle(username); owner->show(); this->hide(); qDebug() << "业主登录成功:" << username; } void LoginDialog::exitbtnSlot() { int ret = QMessageBox::question(this, "确认退出", "确定要退出程序吗?", QMessageBox::Yes | QMessageBox::No); if (ret == QMessageBox::Yes) { this->close(); } } void LoginDialog::clearAll() { ui->userLine->clear(); ui->passwordLine->clear(); ui->userLine->setFocus(); } bool LoginDialog::judgeEmpty() { if (ui->userLine->text().trimmed().isEmpty()) { QMessageBox::warning(this, "警告", "用户名不能为空!"); ui->userLine->setFocus(); return false; } if (ui->passwordLine->text().isEmpty()) { QMessageBox::warning(this, "警告", "密码不能为空!"); ui->passwordLine->setFocus(); return false; } return true; } void LoginDialog::clearInput() { ui->userLine->clear(); ui->passwordLine->clear(); ui->userLine->setFocus(); }有注释版
cpp// ============================================================ // 文件:logindialog.cpp // 功能:登录对话框实现 - 支持三种角色登录 // 作者:IntelligentCommunity 项目 // 说明:管理员、工作人员、业主三种身份登录验证 // ============================================================ // ============================================================ // 头文件包含 // ============================================================ #include "logindialog.h" // 包含自己的头文件声明 #include "ui_logindialog.h" // 包含由 .ui 文件生成的 UI 类头文件 #include <QSqlQuery> // SQL 查询类,用于执行 SQL 语句 #include <QSqlError> // SQL 错误类,用于获取错误信息 #include <QMessageBox> // 消息框类,用于显示提示/警告/错误对话框 #include <QDebug> // 调试输出类,用于在控制台打印调试信息 // ============================================================ // ✅ 新增:包含主窗口类的完整定义 // ============================================================ #include "managermanage.h" #include "workermanage.h" #include "ownermanage.h" // ✅ 新增:配置文件读写 #include <QSettings> // ============================================================ // 构造函数 - 初始化界面和按钮组 // 参数:parent - 父窗口指针,默认 nullptr // ============================================================ LoginDialog::LoginDialog(QWidget *parent) : QDialog(parent), // 调用父类 QDialog 的构造函数,传入父窗口 ui(new Ui::LoginDialog) // 创建 UI 对象(由 Qt Designer 生成的界面) { // -------------------------------------------------------- // 1. 设置 UI 界面 // setupUi() 会创建所有控件并设置布局 // 相当于调用 ui->setupUi(this),把界面加载到当前对话框 // -------------------------------------------------------- ui->setupUi(this); // -------------------------------------------------------- // 2. 创建按钮组(实现单选互斥) // QButtonGroup 可以将多个单选按钮逻辑分组 // 同一组内只能选中一个按钮,实现互斥效果 // 父对象设置为 this,由 Qt 自动管理内存 // -------------------------------------------------------- radioGroup = new QButtonGroup(this); // addButton(按钮指针, ID号) // 将"管理员"单选按钮加入组,分配 ID 为 0 radioGroup->addButton(ui->managerRadio, 0); // 将"工作人员"单选按钮加入组,分配 ID 为 1 radioGroup->addButton(ui->workerRadio, 1); // 将"业主"单选按钮加入组,分配 ID 为 2 radioGroup->addButton(ui->ownerRadio, 2); // 这样通过 checkedId() 就能知道用户选了哪个身份 // -------------------------------------------------------- // 3. 信号槽连接(Qt 5 新语法) // 将按钮的 clicked() 信号连接到对应的槽函数 // 当按钮被点击时,槽函数会被自动调用 // 优点:编译期检查,类型安全 // -------------------------------------------------------- // 登录按钮的 clicked 信号 → 连接到 loginbtnSlot 槽函数 // 用户点击登录按钮时,执行登录验证逻辑 connect(ui->loginBtn, &QPushButton::clicked, this, &LoginDialog::loginbtnSlot); // 退出按钮的 clicked 信号 → 连接到 exitbtnSlot 槽函数 // 用户点击退出按钮时,关闭程序 connect(ui->exitBtn, &QPushButton::clicked, this, &LoginDialog::exitbtnSlot); // 注意:下面这行是 Qt 4 旧语法,已被注释掉 // 旧语法使用 SIGNAL 和 SLOT 宏,运行时字符串匹配,不安全 // connect(ui->loginBtn, SIGNAL(clicked()), this, SLOT(loginbtnSlot())); // -------------------------------------------------------- // 4. 设置默认选中状态 // 默认选中"管理员"单选按钮 // 这样用户打开对话框时,管理员身份已经被选中 // 提升用户体验,减少操作步骤 // -------------------------------------------------------- ui->managerRadio->setChecked(true); // -------------------------------------------------------- // 5. 设置密码输入框的掩码 // setEchoMode() 设置文本显示模式 // Password 模式:输入时显示为 ● 符号 // 保护密码不被旁边的人看到 // -------------------------------------------------------- ui->passwordLine->setEchoMode(QLineEdit::Password); // 额外优化:设置密码框的提示文本 ui->passwordLine->setPlaceholderText("请输入密码"); // 额外优化:设置用户框的提示文本 ui->userLine->setPlaceholderText("请输入用户名"); // ============================================================ // ✅ 新增:6. 加载记住的密码 // ============================================================ loadSettings(); } // ============================================================ // 析构函数 - 释放 UI 资源 // 当 LoginDialog 对象被销毁时自动调用 // ============================================================ LoginDialog::~LoginDialog() { // 删除 UI 对象,释放界面上所有控件的内存 // 这是必须的,因为 ui 是在构造函数中用 new 创建的 delete ui; // 注意:radioGroup、manager、worker、owner 不需要手动 delete // 原因:它们都有父对象 this(在构造函数中设置了 parent) // Qt 的对象树机制会在父对象销毁时自动删除所有子对象 // 这是 Qt 自动内存管理的重要特性,避免了内存泄漏 } // ============================================================ // ✅ 新增:加载记住的密码 // ============================================================ void LoginDialog::loadSettings() { // QSettings: 跨平台的配置文件管理 // 参数1:公司名 参数2:应用名 // Windows 上保存位置:注册表 HKEY_CURRENT_USER/Software/MyCompany/IntelligentCommunity // Linux 上保存位置:~/.config/MyCompany/IntelligentCommunity.conf QSettings settings("MyCompany", "IntelligentCommunity"); // 读取保存的用户名和密码 QString username = settings.value("username", "").toString(); QString password = settings.value("password", "").toString(); bool remember = settings.value("remember", false).toBool(); // 如果有保存的用户名,填入输入框 if (!username.isEmpty()) { ui->userLine->setText(username); } // 如果勾选了"记住密码",填入密码并勾选复选框 if (remember) { ui->passwordLine->setText(password); ui->rememberPwdCheckBox->setChecked(true); } qDebug() << "加载配置: 用户名=" << username << ", 记住密码=" << remember; } // ============================================================ // ✅ 新增:保存密码到配置文件 // ============================================================ void LoginDialog::saveSettings() { QSettings settings("MyCompany", "IntelligentCommunity"); // 判断是否勾选了"记住密码" if (ui->rememberPwdCheckBox->isChecked()) { // 保存用户名、密码、记住状态 settings.setValue("username", ui->userLine->text().trimmed()); settings.setValue("password", ui->passwordLine->text().trimmed()); settings.setValue("remember", true); qDebug() << "保存密码到配置"; } else { // 清除保存的信息 settings.remove("username"); settings.remove("password"); settings.setValue("remember", false); qDebug() << "清除保存的密码"; } } // ============================================================ // 登录按钮槽函数 - 核心登录逻辑 // 当用户点击"登录"按钮时,此函数被调用 // ============================================================ void LoginDialog::loginbtnSlot() { // -------------------------------------------------------- // 1. 输入验证 // 调用 judgeEmpty() 检查用户名和密码是否为空 // 如果为空,judgeEmpty() 会弹出警告框并返回 false // -------------------------------------------------------- if (!judgeEmpty()) { // 密码为空或用户名为空,清空密码框 ui->passwordLine->clear(); // 将焦点设置到密码框,让用户重新输入 ui->passwordLine->setFocus(); // 退出函数,不继续执行登录逻辑 return; } // -------------------------------------------------------- // 2. 获取用户输入 // text() 获取输入框中的文本 // trimmed() 去除字符串首尾的空白字符(空格、制表符等) // -------------------------------------------------------- QString username = ui->userLine->text().trimmed(); QString password = ui->passwordLine->text().trimmed(); // -------------------------------------------------------- // 3. 获取选中的角色 ID // checkedId() 返回当前选中按钮的 ID // 如果没有任何按钮被选中,返回 -1 // -------------------------------------------------------- int roleId = radioGroup->checkedId(); // qDebug() 是 Qt 的调试输出工具 // 在控制台打印信息,方便开发和调试 // 正式发布时可以关闭 qDebug() << "当前选中角色 ID:" << roleId; // -------------------------------------------------------- // 4. 根据角色执行登录验证 // 使用 switch 语句根据不同的角色 ID 执行不同的登录逻辑 // -------------------------------------------------------- switch (roleId) { case 0: // ========== 管理员登录 ========== // 调用管理员登录函数,传入用户名和密码 loginAsAdmin(username, password); break; // 跳出 switch case 1: // ========== 工作人员登录 ========== // 调用工作人员登录函数 loginAsWorker(username, password); break; case 2: // ========== 业主登录 ========== // 调用业主登录函数 loginAsOwner(username, password); break; default: // ========== 未选择任何角色 ========== // roleId 为 -1 或其他值,说明用户没有选择身份 // 弹出警告框提示用户 QMessageBox::warning(this, "警告", "请选择登录身份!", QMessageBox::Ok); break; } } // ============================================================ // 管理员登录逻辑 // 参数:username - 用户名,password - 密码 // ============================================================ void LoginDialog::loginAsAdmin(const QString &username, const QString &password) { // -------------------------------------------------------- // 1. 创建 SQL 查询对象 // QSqlQuery 用于执行 SQL 语句和获取结果 // -------------------------------------------------------- QSqlQuery query; // -------------------------------------------------------- // 2. 准备 SQL 查询语句 // prepare() 预编译 SQL 语句,提高性能和安全性 // ? 是占位符,后续用 addBindValue() 绑定值 // 使用参数绑定可以有效防止 SQL 注入攻击 // -------------------------------------------------------- query.prepare("SELECT * FROM worker WHERE workernum = ?"); // -------------------------------------------------------- // 3. 绑定查询参数 // addBindValue() 将用户名绑定到 ? 占位符 // 这样即使用户名包含特殊字符,也不会被当作 SQL 执行 // -------------------------------------------------------- query.addBindValue(username); // -------------------------------------------------------- // 4. 执行 SQL 查询 // exec() 执行准备好的 SQL 语句 // 如果执行失败,返回 false // -------------------------------------------------------- if (!query.exec()) { // 查询失败,打印错误信息到控制台 qDebug() << "SQL 查询失败:" << query.lastError().text(); // 弹出错误对话框 QMessageBox::critical(this, "错误", "数据库查询失败!"); return; // 退出函数 } // -------------------------------------------------------- // 5. 检查查询结果 // next() 移动到结果集的下一行 // 第一次调用时移动到第一行 // 如果没有数据,返回 false // -------------------------------------------------------- if (!query.next()) { // 没有找到该用户名的记录 QMessageBox::information(this, "提示", "没有此账号!", QMessageBox::Ok); return; // 退出函数 } /*********worker表结构********************************** * 数据库中worker表共有4字段(列),从左向右依此表示为 * workernum workerpass workerphone workertype * 用户名 密码 电话 是/否管理员 *******************************************************/ // -------------------------------------------------------- // 6. 验证密码 // query.value(列索引) 获取当前行的指定列数据 // value(0) 是 workernum (用户名) // value(1) 是 workerpass (密码) // value(2) 是 workerphone (电话) // value(3) 是 workertype (是否管理员:"是"/"否") // 将数据库中存储的密码与用户输入的密码进行比较 // -------------------------------------------------------- if (query.value(1).toString() != password) { // 密码不匹配 QMessageBox::warning(this, "账号密码错误", "请输入正确的账号密码再登录!", QMessageBox::Ok); // 清空输入框,让用户重新输入 // clearInput() 是私有辅助函数,清空用户名和密码框 clearInput(); return; // 退出函数 } // -------------------------------------------------------- // 7. 检查是否为管理员 // value(3) 是 workertype 字段 // 值为"是"表示管理员,"否"表示普通工作人员 // -------------------------------------------------------- if (query.value(3).toString() == "否") { // 账号和密码正确,但不是管理员 QMessageBox::warning(this, "权限不足", "该账号不是管理员,请选择合适权限登录!", QMessageBox::Ok); return; // 退出函数 } // -------------------------------------------------------- // 8. ✅ 登录成功 // 创建管理员主界面对象 // ManagerManage 是管理员的主窗口类 // -------------------------------------------------------- // ✅ 新增:登录成功:保存密码到配置文件 saveSettings(); manager = new ManagerManage; // 显示管理员主窗口 manager->show(); // 隐藏当前登录对话框 // 注意:不是关闭,是隐藏,这样登录对话框还在内存中 // 当主窗口关闭时,可以重新显示登录对话框 this->hide(); // 在控制台打印登录成功信息 qDebug() << "管理员登录成功:" << username; } // ============================================================ // 工作人员登录逻辑 // 参数:username - 用户名,password - 密码 // ============================================================ void LoginDialog::loginAsWorker(const QString &username, const QString &password) { // -------------------------------------------------------- // 1. 创建 SQL 查询对象并准备查询 // 从 worker 表中查询匹配 workernum 的记录 // 使用 ? 占位符防止 SQL 注入 // -------------------------------------------------------- QSqlQuery query; query.prepare("SELECT * FROM worker WHERE workernum = ?"); query.addBindValue(username); // -------------------------------------------------------- // 2. 执行查询并检查错误 // -------------------------------------------------------- if (!query.exec()) { qDebug() << "SQL 查询失败:" << query.lastError().text(); QMessageBox::critical(this, "错误", "数据库查询失败!"); return; } // -------------------------------------------------------- // 3. 检查用户是否存在 // -------------------------------------------------------- if (!query.next()) { QMessageBox::information(this, "提示", "没有此账号!", QMessageBox::Ok); return; } // -------------------------------------------------------- // 4. 验证密码 // value(1) 是密码字段 // -------------------------------------------------------- if (query.value(1).toString() != password) { QMessageBox::warning(this, "账号密码错误", "请输入正确的账号密码再登录!", QMessageBox::Ok); clearInput(); // 清空输入框 return; } // -------------------------------------------------------- // 5. ✅ 登录成功 // 创建工作人员主界面 // setWindowTitle() 设置窗口标题为当前用户名 // 这样工作人员可以在标题栏看到自己的名字 // -------------------------------------------------------- // ✅ 新增:登录成功:保存密码到配置文件 saveSettings(); worker = new WorkerManage; worker->setWindowTitle(username); // 将用户名设为窗口标题 worker->show(); // 显示工作人员主窗口 this->hide(); // 隐藏登录对话框 qDebug() << "工作人员登录成功:" << username; } // ============================================================ // 业主登录逻辑 // 参数:username - 用户名,password - 密码 // ============================================================ void LoginDialog::loginAsOwner(const QString &username, const QString &password) { // -------------------------------------------------------- // 1. 创建 SQL 查询对象 // 从 houseowner 表中查询匹配 ownername 的记录 // houseowner 是业主信息表 // -------------------------------------------------------- QSqlQuery query; query.prepare("SELECT * FROM houseowner WHERE ownername = ?"); query.addBindValue(username); // -------------------------------------------------------- // 2. 执行查询并检查错误 // -------------------------------------------------------- if (!query.exec()) { qDebug() << "SQL 查询失败:" << query.lastError().text(); QMessageBox::critical(this, "错误", "数据库查询失败!"); return; } // -------------------------------------------------------- // 3. 检查用户是否存在 // -------------------------------------------------------- if (!query.next()) { QMessageBox::information(this, "提示", "没有此账号!", QMessageBox::Ok); return; } // -------------------------------------------------------- // 4. 验证密码 // 假设 houseowner 表结构: // value(0): ownername (业主姓名) // value(1): password (密码) // value(2): phone (电话) // value(3): house_id (房屋编号) // 这里用 value(1) 获取密码进行比较 // -------------------------------------------------------- if (query.value(1).toString() != password) { QMessageBox::warning(this, "账号密码错误", "请输入正确的账号密码再登录!", QMessageBox::Ok); clearInput(); return; } // -------------------------------------------------------- // 5. ✅ 登录成功 // 创建业主主界面 // -------------------------------------------------------- // ✅ 新增:登录成功:保存密码到配置文件 saveSettings(); owner = new OwnerManage; owner->setWindowTitle(username); // 窗口标题显示用户名 owner->show(); // 显示业主主窗口 this->hide(); // 隐藏登录对话框 qDebug() << "业主登录成功:" << username; } // ============================================================ // 退出按钮槽函数 // 当用户点击"退出"按钮时调用 // ============================================================ void LoginDialog::exitbtnSlot() { // -------------------------------------------------------- // 显示确认退出对话框 // question() 是 QMessageBox 的静态方法,用于显示询问对话框 // 参数说明: // this: 父窗口 // "确认退出": 对话框标题 // "确定要退出程序吗?": 对话框内容 // QMessageBox::Yes | QMessageBox::No: 显示"是"和"否"两个按钮 // 返回值:用户点击的按钮(Yes 或 No) // -------------------------------------------------------- int ret = QMessageBox::question(this, "确认退出", "确定要退出程序吗?", QMessageBox::Yes | QMessageBox::No); // -------------------------------------------------------- // 判断用户的选择 // 如果用户点击了"是"(Yes),则关闭对话框 // 如果用户点击了"否"(No),什么也不做 // -------------------------------------------------------- if (ret == QMessageBox::Yes) { // close() 关闭当前对话框 // 由于这是主窗口,关闭对话框会导致程序退出 this->close(); } } // ============================================================ // 清空所有输入框 // 公共函数,外部可以调用 // ============================================================ void LoginDialog::clearAll() { // 清空用户名输入框 ui->userLine->clear(); // 清空密码输入框 ui->passwordLine->clear(); // 将焦点设置到用户名输入框 // 方便用户直接输入 ui->userLine->setFocus(); } // ============================================================ // 判断输入是否为空 // 返回值:true - 用户名和密码都不为空 // false - 用户名或密码为空 // ============================================================ bool LoginDialog::judgeEmpty() { // -------------------------------------------------------- // 1. 检查用户名是否为空 // trimmed() 去除首尾空格后再判断 // 如果用户只输入了空格,也被视为空 // -------------------------------------------------------- if (ui->userLine->text().trimmed().isEmpty()) { // 用户名空,弹出警告框 QMessageBox::warning(this, "警告", "用户名不能为空!"); // 将焦点设置到用户名输入框,让用户输入 ui->userLine->setFocus(); return false; // 返回 false 表示验证失败 } // -------------------------------------------------------- // 2. 检查密码是否为空 // 注意:密码不 trim(),因为密码可能包含空格 // 但实际项目中密码通常不允许空格 // -------------------------------------------------------- if (ui->passwordLine->text().isEmpty()) { // 密码为空,弹出警告框 QMessageBox::warning(this, "警告", "密码不能为空!"); // 将焦点设置到密码输入框 ui->passwordLine->setFocus(); return false; // 返回 false 表示验证失败 } // -------------------------------------------------------- // 3. 用户名和密码都不为空 // 返回 true 表示验证通过 // -------------------------------------------------------- return true; } // ============================================================ // 私有辅助函数:清空输入并聚焦 // 在密码错误时调用,让用户重新输入 // ============================================================ void LoginDialog::clearInput() { // 清空用户名输入框 ui->userLine->clear(); // 清空密码输入框 ui->passwordLine->clear(); // 将焦点设置到用户名输入框 // 用户可以直接重新输入,不需要用鼠标点击 ui->userLine->setFocus(); }1.logindialog.ui
原始版
修复版
业主管理模块
2.ownermanage.h
原始版本一
cpp#ifndef OWNERMANAGE_H #define OWNERMANAGE_H #include <QMainWindow> #include <QTableView> #include <QSqlTableModel> #include <QSqlQuery> #include <QSqlQueryModel> #include "issueinfo.h" #include "applycarstation.h" #include "ownerpayself.h" #include "issueassessment.h" namespace Ui { class OwnerManage; } //业主管理类,共有继承QMainWindow //使用UI设计师设计界面 class OwnerManage : public QMainWindow { Q_OBJECT public: explicit OwnerManage(QWidget *parent = 0); ~OwnerManage(); private: Ui::OwnerManage *ui; //表预览 QTableView *ownerTableView; //创建表格预览对象指针 QSqlQueryModel *ownerQueryModel;//创建SQL查询模型对象指针 QSqlTableModel *ownerModel; //创建SQL表格模型对象指针 ApplyCarStation *applyCarStation; //创建车位申请窗口对象指针 ownerPaySelf *pPay; //创建自助缴费窗口对象指针 IssueInfo *issue; //创建故障报修窗口对象指针 issueAssessment *p; //创建用户评价窗口对象指针 int ownerState; //业主是否查看维修进度,是=2 signals: //void EmitToManagerManage(); void EmitOwnerChanged(); private slots: void on_applyCarStationAct_triggered(); //"车位申请"按钮槽函数 void on_showcCarStationAct_triggered(); //"车位查看"按键槽函数 void on_payShowAct_triggered(); //"缴费查询"按键槽函数 void on_payAct_triggered(); //"自助缴费"按键槽函数 void on_issueReportAct_triggered(); //"故障保修"按键槽函数 void on_issueProcessAct_triggered(); //"故障进度"按键槽函数 void on_issueEvaluateAct_triggered(); //"维修评价"按键槽函数 }; #endif // OWNERMANAGE_H修复版本二
无注释版
cpp#ifndef OWNERMANAGE_H #define OWNERMANAGE_H #include <QMainWindow> #include <QTableView> #include <QSqlTableModel> #include <QSqlQuery> #include <QSqlQueryModel> #include "issueinfo.h" #include "applycarstation.h" #include "ownerpayself.h" #include "issueassessment.h" namespace Ui { class OwnerManage; } class OwnerManage : public QMainWindow { Q_OBJECT public: explicit OwnerManage(QWidget *parent = 0); ~OwnerManage(); private: Ui::OwnerManage *ui; QTableView *ownerTableView; QSqlQueryModel *ownerQueryModel; QSqlTableModel *ownerModel; ApplyCarStation *applyCarStation; ownerPaySelf *pPay; IssueInfo *issue; issueAssessment *p; int ownerState; signals: void EmitOwnerChanged(); private slots: void on_applyCarStationAct_triggered(); void on_showcCarStationAct_triggered(); void on_payShowAct_triggered(); void on_payAct_triggered(); void on_issueReportAct_triggered(); void on_issueProcessAct_triggered(); void on_issueEvaluateAct_triggered(); }; #endif // OWNERMANAGE_H有注释版
cpp// ============================================================ // 文件:ownermanage.h // 功能:业主管理界面的头文件声明 // 说明:业主登录后的主界面,包含车位申请、缴费、报修等功能 // ============================================================ #ifndef OWNERMANAGE_H // 作用:防止头文件被多次包含(Include Guard) // 如果 OWNERMANAGE_H 未定义,则定义它并包含头文件内容 // 如果已定义,则跳过整个头文件内容 #define OWNERMANAGE_H // 定义宏 OWNERMANAGE_H,标记这个头文件已经被包含 // ============================================================ // 头文件包含 // ============================================================ #include <QMainWindow> // 包含 QMainWindow 基类 // QMainWindow 是 Qt 中主窗口的基类,提供菜单栏、工具栏、状态栏等 // 业主管理界面是一个主窗口,所以继承 QMainWindow #include <QTableView> // 包含 QTableView 类 // QTableView 是表格视图,用于以表格形式显示数据 // 本类中用于显示业主信息列表 #include <QSqlTableModel> // 包含 QSqlTableModel 类 // QSqlTableModel 是可读写的数据库表模型 // 用于在表格中显示和编辑数据库表中的数据 #include <QSqlQuery> // 包含 QSqlQuery 类 // 用于执行 SQL 查询语句 #include <QSqlQueryModel> // 包含 QSqlQueryModel 类 // QSqlQueryModel 是只读的 SQL 查询模型 // 用于执行自定义 SQL 查询并显示结果 // ============================================================ // 包含其他功能模块的头文件 // ============================================================ #include "issueinfo.h" // 包含报修信息模块 // issueinfo.h 定义了 IssueInfo 类 // 用于故障报修功能 #include "applycarstation.h" // 包含车位申请模块 // applycarstation.h 定义了 ApplyCarStation 类 // 用于车位申请功能 #include "ownerpayself.h" // 包含业主自助缴费模块 // ownerpayself.h 定义了 ownerPaySelf 类 // 用于业主自助缴费功能 #include "issueassessment.h" // 包含报修评估模块 // issueassessment.h 定义了 issueAssessment 类 // 用于维修评价功能 // ============================================================ // UI 命名空间声明 // ============================================================ namespace Ui { class OwnerManage; // 声明 UI 类 // 这个类由 Qt 的 uic 工具根据 ownermanage.ui 文件自动生成 // 包含了界面上所有控件的指针 } // ============================================================ // OwnerManage 类定义 // 业主管理主窗口,继承自 QMainWindow // ============================================================ class OwnerManage : public QMainWindow // class OwnerManage : 定义一个名为 OwnerManage 的类 // public QMainWindow : 公有继承自 QMainWindow 基类 // QMainWindow 提供主窗口的完整功能:菜单栏、工具栏、状态栏、中央部件 { Q_OBJECT // Qt 元对象宏 // 启用信号槽机制、运行时类型信息等 Qt 元对象功能 // 因为类中使用了 signals 和 private slots,必须包含此宏 public: // ============================================================ // public 区域:对外公开的接口 // ============================================================ explicit OwnerManage(QWidget *parent = 0); // 构造函数 // explicit: 防止隐式类型转换 // QWidget *parent = 0: 父窗口指针,默认值为 nullptr ~OwnerManage(); // 析构函数 // 当对象被销毁时自动调用,释放资源 private: // ============================================================ // private 区域:私有的成员变量和函数 // 只能在类内部访问,外部不可见 // ============================================================ Ui::OwnerManage *ui; // UI 对象指针 // 指向由 uic 工具生成的 UI 类对象 // 通过这个指针可以访问界面上所有的控件 // ============================================================ // 表格相关成员变量 // ============================================================ QTableView *ownerTableView; // 表格视图对象指针 // 用于在界面上以表格形式显示业主数据 // 通过 setModel() 绑定数据模型 QSqlQueryModel *ownerQueryModel; // SQL 查询模型对象指针(只读) // 用于执行自定义 SQL 查询 // 适用于不需要编辑数据的场景 QSqlTableModel *ownerModel; // SQL 表格模型对象指针(可读写) // 用于与数据库表直接绑定 // 支持增删改查操作 // ============================================================ // 功能模块窗口指针 // ============================================================ ApplyCarStation *applyCarStation; // 车位申请窗口对象指针 // 当用户点击"车位申请"时,创建并显示此窗口 ownerPaySelf *pPay; // 自助缴费窗口对象指针 // 当用户点击"自助缴费"时,创建并显示此窗口 IssueInfo *issue; // 故障报修窗口对象指针 // 当用户点击"故障报修"时,创建并显示此窗口 issueAssessment *p; // 用户评价窗口对象指针 // 当用户点击"维修评价"时,创建并显示此窗口 int ownerState; // 业主状态标记 // 用于记录业主是否正在查看维修进度 // 值 2 表示正在查看维修进度 signals: // ============================================================ // 信号区域 // ============================================================ //void EmitToManagerManage(); // 已注释掉的信号 // 推测:用于向管理员管理界面发送信号 // 但目前未被使用 void EmitOwnerChanged(); // 业主信息变更信号 // 当业主信息发生变化时发射此信号 // 用于通知其他模块更新数据 private slots: // ============================================================ // 私有槽函数区域 // 响应菜单/按钮的点击事件 // ============================================================ void on_applyCarStationAct_triggered(); // "车位申请"菜单/按钮的槽函数 // 当用户点击"车位申请"时被调用 // 功能:创建并显示 ApplyCarStation 窗口 void on_showcCarStationAct_triggered(); // "车位查看"菜单/按钮的槽函数 // 当用户点击"车位查看"时被调用 // 功能:显示当前业主的车位信息 void on_payShowAct_triggered(); // "缴费查询"菜单/按钮的槽函数 // 当用户点击"缴费查询"时被调用 // 功能:显示业主的缴费记录 void on_payAct_triggered(); // "自助缴费"菜单/按钮的槽函数 // 当用户点击"自助缴费"时被调用 // 功能:创建并显示 ownerPaySelf 缴费窗口 void on_issueReportAct_triggered(); // "故障报修"菜单/按钮的槽函数 // 当用户点击"故障报修"时被调用 // 功能:创建并显示 IssueInfo 报修窗口 void on_issueProcessAct_triggered(); // "故障进度"菜单/按钮的槽函数 // 当用户点击"故障进度"时被调用 // 功能:查看当前报修的处理进度 void on_issueEvaluateAct_triggered(); // "维修评价"菜单/按钮的槽函数 // 当用户点击"维修评价"时被调用 // 功能:创建并显示 issueAssessment 评价窗口 }; #endif // OWNERMANAGE_H // 结束条件编译块2.ownermanage.cpp
原始版本一
cpp#include "ownermanage.h" #include "ui_ownermanage.h" #include "ownerpayself.h" #include "issueassessment.h" /********业主管理类OwnerManage构造函数************************************************/ OwnerManage::OwnerManage(QWidget *parent) : QMainWindow(parent), ui(new Ui::OwnerManage) { ui->setupUi(this); ui->toolBar->setIconSize(QSize(50,50)); //设置工具栏图标大小 ownerTableView=new QTableView; //创建一个文本编辑器 //textEdit=new QPlainTextEdit; setCentralWidget(ownerTableView); //设置文本编辑器为中心部件 //问题?业主窗口,有没有必要显示业主的详细信息,单独建一个表.............................? ownerModel=new QSqlTableModel(this); //创建SQL表格模型 ownerQueryModel = new QSqlQueryModel; //创建SQL查询模型 ownerModel->setTable("owner"); //设置连接数据表"owner" ownerModel->setEditStrategy(QSqlTableModel::OnManualSubmit); //设置编辑模式 ownerModel->removeColumns(5,5);/*?*/ } /********业主管理类OwnerManage析构函数************************************************/ OwnerManage::~OwnerManage() { delete ui; } /********《槽函数》"车位申请"按键执行函数*******************************************/ void OwnerManage::on_applyCarStationAct_triggered() { applyCarStation=new ApplyCarStation; //创建车位申请窗口对象 applyCarStation->show(); //显示对象 } /********《槽函数》"车位查看"按键执行函数*******************************************/ void OwnerManage::on_showcCarStationAct_triggered() { ownerModel->setTable("carstation"); //设置连接数据表"carstation" //获取当前业主名 QString strFilter = QString("ownername = '%1'").arg(this->windowTitle().trimmed()); qDebug() << "strFilter:" << strFilter; //输出业主名信息 ownerModel->setFilter(strFilter); //设置过滤器 ownerModel->select(); //数据库查询 ownerModel->setHeaderData(0,Qt::Horizontal,tr("车位号")); //设置字段名,0为最左边位置 ownerModel->setHeaderData(1,Qt::Horizontal,tr("地上/地下")); ownerModel->setHeaderData(2,Qt::Horizontal,tr("大/小")); ownerModel->setHeaderData(3,Qt::Horizontal,tr("能否充电")); ownerModel->setHeaderData(4,Qt::Horizontal,tr("所属业主")); ownerModel->setHeaderData(5,Qt::Horizontal,tr("缴费状态")); ownerTableView->setModel(ownerModel); } /********《槽函数》"缴费查询"按键执行函数*******************************************/ void OwnerManage::on_payShowAct_triggered() { ownerModel->setTable("priceRecord"); QString strFilter = QString("ownername = '%1'").arg(this->windowTitle().trimmed()); ownerModel->setFilter(strFilter); ownerModel->select(); ownerModel->setHeaderData(0,Qt::Horizontal,tr("缴费人")); ownerModel->setHeaderData(1,Qt::Horizontal,tr("缴费类型")); ownerModel->setHeaderData(2,Qt::Horizontal,tr("缴费金额")); ownerModel->setHeaderData(3,Qt::Horizontal,tr("缴费时间")); ownerTableView->setModel(ownerModel); } /********《槽函数》"自助缴费"按键执行函数*******************************************/ void OwnerManage::on_payAct_triggered() { pPay = new ownerPaySelf(); //创建自助缴费窗口对象 QString strOwner = this->windowTitle(); //获取业主名 pPay->setWindowTitle(strOwner); //设置窗口标题为业主名 pPay->show(); //窗口显示 } /********《槽函数》"故障报修"按键执行函数*******************************************/ void OwnerManage::on_issueReportAct_triggered() { issue=new IssueInfo; //创建故障报修窗口对象 issue->setUserName(this->windowTitle().trimmed()); //设置业主名为当前登录名 issue->show(); //窗口显示 } /********《槽函数》"维修进度"按键执行函数*******************************************/ void OwnerManage::on_issueProcessAct_triggered() { ownerState = 2; //标识2,标识业主已查看维修进度 QString strSql = QString("owner = '%1'").arg(this->windowTitle().trimmed()); ownerModel->setTable("errorinfo"); //设置连接数据表"errorinfo" ownerModel->setFilter(strSql); //设置过滤器 ownerModel->select(); //数据查询 ownerModel->setHeaderData(0,Qt::Horizontal,tr("序号")); //设置字段,0为最左边 ownerModel->setHeaderData(1,Qt::Horizontal,tr("申请人")); ownerModel->setHeaderData(2,Qt::Horizontal,tr("故障描述")); ownerModel->setHeaderData(3,Qt::Horizontal,tr("申请时间")); ownerModel->setHeaderData(4,Qt::Horizontal,tr("维修进度")); ownerModel->setHeaderData(4,Qt::Horizontal,tr("维修评价")); ownerTableView->setEditTriggers(QAbstractItemView::NoEditTriggers);//设置编辑模式 ownerTableView->setModel(ownerModel); //显示数据表 } /********《槽函数》"维修评价"按键执行函数*******************************************/ void OwnerManage::on_issueEvaluateAct_triggered() { if(2 == ownerState) //业主已查看维修进度 { int n = ownerTableView->currentIndex().row(); //获取当前指向的行索引 //获取当前行errornum字段数据 QString strInfo = ownerModel->record(n).value("errornum").toString(); p = new issueAssessment(this); //创建用户评价对象 p->setMessageIndex(strInfo); //传递行索引 p->exec(); //设置窗口为模态对话框 } ownerModel->select(); //数据查询 }修复版本二
无注释版
cpp#include "ownermanage.h" #include "ui_ownermanage.h" #include "ownerpayself.h" #include "issueassessment.h" OwnerManage::OwnerManage(QWidget *parent) : QMainWindow(parent), ui(new Ui::OwnerManage) { ui->setupUi(this); ui->toolBar->setIconSize(QSize(50,50)); ownerTableView = new QTableView; setCentralWidget(ownerTableView); ownerModel = new QSqlTableModel(this); ownerQueryModel = new QSqlQueryModel; ownerModel->setTable("owner"); ownerModel->setEditStrategy(QSqlTableModel::OnManualSubmit); ownerModel->removeColumns(5,5); } OwnerManage::~OwnerManage() { delete ui; } void OwnerManage::on_applyCarStationAct_triggered() { applyCarStation = new ApplyCarStation; applyCarStation->show(); } void OwnerManage::on_showcCarStationAct_triggered() { ownerModel->setTable("carstation"); QString strFilter = QString("ownername = '%1'").arg(this->windowTitle().trimmed()); qDebug() << "strFilter:" << strFilter; ownerModel->setFilter(strFilter); ownerModel->select(); ownerModel->setHeaderData(0, Qt::Horizontal, tr("车位号")); ownerModel->setHeaderData(1, Qt::Horizontal, tr("地上/地下")); ownerModel->setHeaderData(2, Qt::Horizontal, tr("大/小")); ownerModel->setHeaderData(3, Qt::Horizontal, tr("能否充电")); ownerModel->setHeaderData(4, Qt::Horizontal, tr("所属业主")); ownerModel->setHeaderData(5, Qt::Horizontal, tr("缴费状态")); ownerTableView->setModel(ownerModel); } void OwnerManage::on_payShowAct_triggered() { ownerModel->setTable("priceRecord"); QString strFilter = QString("ownername = '%1'").arg(this->windowTitle().trimmed()); ownerModel->setFilter(strFilter); ownerModel->select(); ownerModel->setHeaderData(0, Qt::Horizontal, tr("缴费人")); ownerModel->setHeaderData(1, Qt::Horizontal, tr("缴费类型")); ownerModel->setHeaderData(2, Qt::Horizontal, tr("缴费金额")); ownerModel->setHeaderData(3, Qt::Horizontal, tr("缴费时间")); ownerTableView->setModel(ownerModel); } void OwnerManage::on_payAct_triggered() { pPay = new ownerPaySelf(); QString strOwner = this->windowTitle(); pPay->setWindowTitle(strOwner); pPay->show(); } void OwnerManage::on_issueReportAct_triggered() { issue = new IssueInfo; issue->setUserName(this->windowTitle().trimmed()); issue->show(); } void OwnerManage::on_issueProcessAct_triggered() { ownerState = 2; QString strSql = QString("owner = '%1'").arg(this->windowTitle().trimmed()); ownerModel->setTable("errorinfo"); ownerModel->setFilter(strSql); ownerModel->select(); ownerModel->setHeaderData(0, Qt::Horizontal, tr("序号")); ownerModel->setHeaderData(1, Qt::Horizontal, tr("申请人")); ownerModel->setHeaderData(2, Qt::Horizontal, tr("故障描述")); ownerModel->setHeaderData(3, Qt::Horizontal, tr("申请时间")); ownerModel->setHeaderData(4, Qt::Horizontal, tr("维修进度")); ownerModel->setHeaderData(4, Qt::Horizontal, tr("维修评价")); ownerTableView->setEditTriggers(QAbstractItemView::NoEditTriggers); ownerTableView->setModel(ownerModel); } void OwnerManage::on_issueEvaluateAct_triggered() { if (2 == ownerState) { int n = ownerTableView->currentIndex().row(); QString strInfo = ownerModel->record(n).value("errornum").toString(); p = new issueAssessment(this); p->setMessageIndex(strInfo); p->exec(); } ownerModel->select(); }有注释版
cpp// ============================================================ // 文件:ownermanage.cpp // 功能:业主管理界面的实现 // 说明:业主登录后的主界面,包含车位、缴费、报修等功能 // ============================================================ #include "ownermanage.h" // 包含自己的头文件声明 // 让编译器知道类 OwnerManage 的结构、成员函数和成员变量 #include "ui_ownermanage.h" // 包含由 .ui 文件生成的 UI 类头文件 // 包含了 Ui::OwnerManage 类的定义,其中有所有控件的指针 #include "ownerpayself.h" // 包含自助缴费模块的头文件 // 用于创建 ownerPaySelf 缴费窗口对象 #include "issueassessment.h" // 包含报修评估模块的头文件 // 用于创建 issueAssessment 评价窗口对象 // ============================================================ // 构造函数 - 初始化业主管理界面 // 参数:parent - 父窗口指针,默认 nullptr // 当业主登录成功后,此构造函数被调用 // ============================================================ OwnerManage::OwnerManage(QWidget *parent) : QMainWindow(parent), // 调用父类 QMainWindow 的构造函数,传入父窗口指针 // QMainWindow 提供菜单栏、工具栏、状态栏等主窗口功能 ui(new Ui::OwnerManage) // 创建 UI 对象(由 Qt Designer 生成的界面类) // 使用 new 在堆上分配内存,必须在析构函数中用 delete 释放 { ui->setupUi(this); // setupUi() 加载 .ui 文件,创建所有控件并设置布局 // 相当于把 UI 设计师设计的界面加载到当前窗口 ui->toolBar->setIconSize(QSize(50,50)); // 设置工具栏中图标的大小为 50x50 像素 // QSize(50,50) 表示宽度和高度都是 50 像素 // 让工具栏图标更大,方便触摸操作 ownerTableView = new QTableView; // 创建 QTableView 对象(表格视图) // 用于以表格形式显示各种数据(车位、缴费、报修等) // 在堆上分配内存,由 Qt 对象树管理 //textEdit=new QPlainTextEdit; // 已注释:原本可能用文本编辑器 setCentralWidget(ownerTableView); // setCentralWidget() 设置窗口的中央部件 // QMainWindow 有中央区域,只能有一个中央部件 // 这里将表格视图设置为中央部件,占据窗口主要区域 // 所有数据显示在这个表格中 //问题?业主窗口,有没有必要显示业主的详细信息,单独建一个表.............................? // 这是开发者的注释:考虑是否需要单独显示业主信息 ownerModel = new QSqlTableModel(this); // 创建 SQL 表格模型(可读写) // 参数 this 表示父对象是当前窗口,由 Qt 自动管理内存 // 用于与数据库表绑定,支持增删改查操作 ownerQueryModel = new QSqlQueryModel; // 创建 SQL 查询模型(只读) // 用于执行自定义 SQL 查询 // ⚠️ 问题:从未被使用,是死代码 ownerModel->setTable("owner"); // setTable() 设置要操作的数据库表名 // 初始绑定到 "owner" 表 // 后续会根据用户点击动态切换到其他表 ownerModel->setEditStrategy(QSqlTableModel::OnManualSubmit); // setEditStrategy() 设置编辑策略 // OnManualSubmit: 手动提交模式 // 修改后需要调用 submitAll() 才会保存到数据库 // 优点:可以批量修改,确认后再提交 // 缺点:需要手动调用 submitAll() ownerModel->removeColumns(5,5); // removeColumns(列索引, 列数) // 从第 5 列开始,移除 5 列(隐藏这些列) // 例如:移除第 5、6、7、8、9 列 // ⚠️ 问题:开发者自己加了 "/*?*/" 表示不确定为什么这样做 // 可能因为某些列不需要显示给业主看 } // ============================================================ // 析构函数 - 释放资源 // 当窗口关闭时自动调用 // ============================================================ OwnerManage::~OwnerManage() { delete ui; // 删除 UI 对象,释放界面上所有控件的内存 // 这是必须的,因为 ui 是在构造函数中用 new 创建的 // Qt 的对象树机制会自动释放子对象,但 ui 本身需要手动释放 } // ============================================================ // "车位申请"按钮槽函数 // 当用户点击工具栏/菜单的"车位申请"时被调用 // ============================================================ void OwnerManage::on_applyCarStationAct_triggered() { applyCarStation = new ApplyCarStation; // 创建车位申请窗口对象 // 在堆上分配内存 // ⚠️ 问题:没有设置父对象,可能导致内存泄漏 // 建议:添加 this 作为父对象,或设置 WA_DeleteOnClose applyCarStation->show(); // 显示车位申请窗口 // show() 是非模态显示,不阻塞主窗口 // 用户可以在两个窗口间切换 } // ============================================================ // "车位查看"按钮槽函数 // 当用户点击"车位查看"时被调用 // 功能:显示当前业主的车位信息 // ============================================================ void OwnerManage::on_showcCarStationAct_triggered() { ownerModel->setTable("carstation"); // 切换数据表到 "carstation"(车位表) // 之前绑定的是 "owner" 表,现在切换到车位表 // 获取当前业主名 QString strFilter = QString("ownername = '%1'").arg(this->windowTitle().trimmed()); // 构建查询条件:筛选该业主的车位 // this->windowTitle() 获取窗口标题,即业主名 // trimmed() 去除首尾空格 // 例如:窗口标题是 "张三",则 strFilter = "ownername = '张三'" // ⚠️ SQL 注入风险!使用字符串拼接 qDebug() << "strFilter:" << strFilter; // 输出过滤条件到控制台 // 用于调试,检查生成的 SQL 条件是否正确 ownerModel->setFilter(strFilter); // 设置过滤条件 // 相当于执行:SELECT * FROM carstation WHERE ownername = '张三' ownerModel->select(); // 执行查询,从数据库获取数据 // 查询结果存储在 ownerModel 中 // 设置表头显示名称(用户看到的列名) ownerModel->setHeaderData(0, Qt::Horizontal, tr("车位号")); // 第0列显示为"车位号" // Qt::Horizontal 表示水平方向(列) ownerModel->setHeaderData(1, Qt::Horizontal, tr("地上/地下")); // 第1列显示为"地上/地下" ownerModel->setHeaderData(2, Qt::Horizontal, tr("大/小")); // 第2列显示为"大/小" ownerModel->setHeaderData(3, Qt::Horizontal, tr("能否充电")); // 第3列显示为"能否充电" ownerModel->setHeaderData(4, Qt::Horizontal, tr("所属业主")); // 第4列显示为"所属业主" ownerModel->setHeaderData(5, Qt::Horizontal, tr("缴费状态")); // 第5列显示为"缴费状态" ownerTableView->setModel(ownerModel); // 将数据模型设置到表格视图 // 表格现在显示车位信息 } // ============================================================ // "缴费查询"按钮槽函数 // 当用户点击"缴费查询"时被调用 // 功能:显示当前业主的缴费记录 // ============================================================ void OwnerManage::on_payShowAct_triggered() { ownerModel->setTable("priceRecord"); // 切换到 "priceRecord"(缴费记录表) QString strFilter = QString("ownername = '%1'").arg(this->windowTitle().trimmed()); // 构建过滤条件:筛选该业主的缴费记录 // ⚠️ 同样的 SQL 注入风险 ownerModel->setFilter(strFilter); // 设置过滤条件 ownerModel->select(); // 执行查询 // 设置表头 ownerModel->setHeaderData(0, Qt::Horizontal, tr("缴费人")); ownerModel->setHeaderData(1, Qt::Horizontal, tr("缴费类型")); ownerModel->setHeaderData(2, Qt::Horizontal, tr("缴费金额")); ownerModel->setHeaderData(3, Qt::Horizontal, tr("缴费时间")); ownerTableView->setModel(ownerModel); // 表格现在显示缴费记录 } // ============================================================ // "自助缴费"按钮槽函数 // 当用户点击"自助缴费"时被调用 // 功能:打开自助缴费窗口 // ============================================================ void OwnerManage::on_payAct_triggered() { pPay = new ownerPaySelf(); // 创建自助缴费窗口对象 // ⚠️ 没有设置父对象,可能内存泄漏 QString strOwner = this->windowTitle(); // 获取业主名 pPay->setWindowTitle(strOwner); // 将业主名设置为缴费窗口的标题 // 这样缴费窗口知道是谁在缴费 pPay->show(); // 显示缴费窗口(非模态) } // ============================================================ // "故障报修"按钮槽函数 // 当用户点击"故障报修"时被调用 // 功能:打开故障报修窗口 // ============================================================ void OwnerManage::on_issueReportAct_triggered() { issue = new IssueInfo; // 创建故障报修窗口对象 // ⚠️ 没有设置父对象 issue->setUserName(this->windowTitle().trimmed()); // 将业主名传递给报修窗口 // 报修窗口知道是谁在报修 issue->show(); // 显示报修窗口 } // ============================================================ // "维修进度"按钮槽函数 // 当用户点击"维修进度"时被调用 // 功能:查看当前业主的报修处理进度 // ============================================================ void OwnerManage::on_issueProcessAct_triggered() { ownerState = 2; // 设置状态标记为 2 // 表示"业主已查看维修进度" // ⚠️ 问题:使用硬编码数字 2,不清晰 // 建议:使用枚举,如 enum { NotViewed, Viewed } QString strSql = QString("owner = '%1'").arg(this->windowTitle().trimmed()); // 构建查询条件 // ⚠️ SQL 注入风险 ownerModel->setTable("errorinfo"); // 切换到 "errorinfo"(报修信息表) ownerModel->setFilter(strSql); // 设置过滤条件 ownerModel->select(); // 执行查询 ownerModel->setHeaderData(0, Qt::Horizontal, tr("序号")); // 第0列显示为"序号" ownerModel->setHeaderData(1, Qt::Horizontal, tr("申请人")); // 第1列显示为"申请人" ownerModel->setHeaderData(2, Qt::Horizontal, tr("故障描述")); // 第2列显示为"故障描述" ownerModel->setHeaderData(3, Qt::Horizontal, tr("申请时间")); // 第3列显示为"申请时间" ownerModel->setHeaderData(4, Qt::Horizontal, tr("维修进度")); // 第4列显示为"维修进度" ownerModel->setHeaderData(4, Qt::Horizontal, tr("维修评价")); // ❌ BUG!再次设置第4列,覆盖了上一行 // 第4列应该显示"维修评价",但被设置为"维修评价"(重复) // 应该是第5列设置"维修评价" ownerTableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 禁止用户编辑表格内容 // NoEditTriggers:任何操作都不能触发编辑 // 用户只能查看,不能修改 ownerTableView->setModel(ownerModel); // 表格现在显示报修进度 } // ============================================================ // "维修评价"按钮槽函数 // 当用户点击"维修评价"时被调用 // 功能:对完成的维修进行评价 // 前提:必须先查看过维修进度(ownerState == 2) // ============================================================ void OwnerManage::on_issueEvaluateAct_triggered() { if (2 == ownerState) { // 检查是否已查看维修进度 // 只有查看过进度才能评价 // ⚠️ 使用硬编码数字 2 int n = ownerTableView->currentIndex().row(); // 获取当前选中的行索引 // currentIndex() 返回当前选中的单元格索引 // row() 获取行号 QString strInfo = ownerModel->record(n).value("errornum").toString(); // 获取当前行中 "errornum" 字段的值 // record(n) 获取第 n 行的记录 // value("errornum") 获取该字段的值 // toString() 转换为字符串 // 这个值用于标识是哪条报修记录 p = new issueAssessment(this); // 创建评价窗口对象 // ✅ 设置了父对象 this,由 Qt 管理内存 p->setMessageIndex(strInfo); // 传递报修记录编号给评价窗口 // 评价窗口知道要评价哪条记录 p->exec(); // 模态显示评价窗口 // exec() 会阻塞当前窗口,直到评价窗口关闭 // 用户必须先完成评价才能继续操作 } ownerModel->select(); // 刷新数据 // 重新查询数据库,更新表格显示 }业主界面功能流程图
cpp业主登录成功 ↓ 显示 OwnerManage 主窗口 ↓ ┌─────────────────────────────────────────────────────────────┐ │ 菜单/工具栏 │ │ │ │ 车位申请 → ApplyCarStation(车位申请窗口) │ │ 车位查看 → 显示当前业主的车位信息 │ │ 缴费查询 → 显示缴费记录列表 │ │ 自助缴费 → ownerPaySelf(缴费窗口) │ │ 故障报修 → IssueInfo(报修窗口) │ │ 故障进度 → 查看报修处理进度 │ │ 维修评价 → issueAssessment(评价窗口) │ └─────────────────────────────────────────────────────────────┘整体运行流程图
cpp用户登录成功 ↓ 创建 OwnerManage 主窗口 ↓ ┌─────────────────────────────────────────────────────────────────┐ │ 主窗口显示 │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 菜单栏/工具栏:车位申请 | 车位查看 | 缴费查询 │ │ │ │ 自助缴费 | 故障报修 | 故障进度 | 维修评价 │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ │ │ │ │ 中央表格区域 (空) │ │ │ │ 等待用户点击功能按钮 │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘详细运行过程
阶段一:启动初始化(构造函数执行)
cpp// ============================================================ // 第1步:用户登录成功,创建 OwnerManage 对象 // ============================================================ // 在 logindialog.cpp 中 void LoginDialog::loginAsOwner(const QString &username, const QString &password) { // ... 验证通过 ... owner = new OwnerManage; // ← 第1步:创建对象 owner->setWindowTitle(username); // 设置窗口标题为业主名 owner->show(); // ← 第2步:显示窗口 this->hide(); }构造函数内部执行过程:
cppOwnerManage::OwnerManage(QWidget *parent) ↓ 1. QMainWindow(parent) // 调用父类构造函数 ↓ 2. ui(new Ui::OwnerManage) // 创建 UI 对象 ↓ 3. ui->setupUi(this) // 加载 .ui 界面文件 ↓ 4. ui->toolBar->setIconSize(QSize(50,50)) // 设置工具栏图标大小 ↓ 5. ownerTableView = new QTableView // 创建表格视图 ↓ 6. setCentralWidget(ownerTableView) // 设置为中央部件 ↓ 7. ownerModel = new QSqlTableModel(this) // 创建数据模型 ↓ 8. ownerQueryModel = new QSqlQueryModel // 创建查询模型(未使用) ↓ 9. ownerModel->setTable("owner") // 设置表名为 owner ↓ 10. ownerModel->setEditStrategy(OnManualSubmit) // 手动提交模式 ↓ 11. ownerModel->removeColumns(5,5) // 隐藏第5-9列 ↓ 12. 构造函数结束,窗口显示此时窗口状态:
cpp┌─────────────────────────────────────────────────────────────────┐ │ IntelligentCommunity - 张三(业主) │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 车位申请 │ 车位查看 │ 缴费查询 │ 自助缴费 │ 故障报修 │ │ │ │ 故障进度 │ 维修评价 │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ │ │ │ │ (中央表格区域为空) │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────┘ │ │ 状态栏:就绪 │ └─────────────────────────────────────────────────────────────────┘阶段二:用户操作 - 车位查看
用户点击"车位查看"按钮
cpp┌─────────────────────────────────────────────────────────────────┐ │ 用户点击 "车位查看" 按钮 │ │ ↓ │ │ 触发 clicked() 信号 │ │ ↓ │ │ 自动调用 on_showcCarStationAct_triggered() 槽函数 │ └─────────────────────────────────────────────────────────────────┘槽函数执行过程:
cppvoid OwnerManage::on_showcCarStationAct_triggered() { // ============================================================ // 第1步:切换数据表 // ============================================================ ownerModel->setTable("carstation"); // 原来 ownerModel 绑定的是 "owner" 表 // 现在切换到 "carstation" 表 // ============================================================ // 第2步:构建查询条件(⚠️ SQL 注入风险) // ============================================================ QString strFilter = QString("ownername = '%1'") .arg(this->windowTitle().trimmed()); // 假设窗口标题是 "张三" // strFilter = "ownername = '张三'" qDebug() << "strFilter:" << strFilter; // ============================================================ // 第3步:设置过滤条件并查询 // ============================================================ ownerModel->setFilter(strFilter); // 相当于执行:SELECT * FROM carstation WHERE ownername = '张三' ownerModel->select(); // 执行查询,从数据库获取数据 // ============================================================ // 第4步:设置表头显示名称 // ============================================================ ownerModel->setHeaderData(0, Qt::Horizontal, tr("车位号")); ownerModel->setHeaderData(1, Qt::Horizontal, tr("地上/地下")); ownerModel->setHeaderData(2, Qt::Horizontal, tr("大/小")); ownerModel->setHeaderData(3, Qt::Horizontal, tr("能否充电")); ownerModel->setHeaderData(4, Qt::Horizontal, tr("所属业主")); ownerModel->setHeaderData(5, Qt::Horizontal, tr("缴费状态")); // ============================================================ // 第5步:将模型绑定到表格视图 // ============================================================ ownerTableView->setModel(ownerModel); // 表格显示查询结果 }运行后的界面变化:
cpp┌─────────────────────────────────────────────────────────────────┐ │ IntelligentCommunity - 张三(业主) │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 车位申请 │ 车位查看 │ 缴费查询 │ 自助缴费 │ 故障报修 │ │ │ │ 故障进度 │ 维修评价 │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ │ │ │ │ 车位号 │ 地上/地下 │ 大/小 │ 能否充电 │ 所属业主 │ 缴费状态│ │ │ ──────┼─────────┼──────┼─────────┼─────────┼─────────┤ │ │ │ A001 │ 地下 │ 大 │ 是 │ 张三 │ 已缴费 │ │ │ │ A002 │ 地上 │ 小 │ 否 │ 张三 │ 未缴费 │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘阶段三:用户操作 - 缴费查询
cpp用户点击 "缴费查询" ↓ on_payShowAct_triggered() 被调用 ↓ 切换到 priceRecord 表 ↓ 过滤:ownername = '张三' ↓ 显示缴费记录界面变化:
cpp┌─────────────────────────────────────────────────────────────────┐ │ IntelligentCommunity - 张三(业主) │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 车位申请 │ 车位查看 │ 缴费查询 │ 自助缴费 │ 故障报修 │ │ │ │ 故障进度 │ 维修评价 │ │ │ ├─────────────────────────────────────────────────────────┤ │ │ │ │ │ │ │ 缴费人 │ 缴费类型 │ 缴费金额 │ 缴费时间 │ │ │ │ ──────┼─────────┼─────────┼─────────────────────── │ │ │ │ 张三 │ 物业费 │ 500.00 │ 2026-08-01 10:30:00 │ │ │ │ 张三 │ 车位费 │ 200.00 │ 2026-08-15 14:20:00 │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘阶段四:用户操作 - 自助缴费
cpp用户点击 "自助缴费" ↓ on_payAct_triggered() 被调用 ↓ 创建 ownerPaySelf 窗口 ↓ 设置窗口标题为业主名 ↓ 显示缴费窗口(不阻塞主窗口)弹出新窗口:
cpp┌─────────────────────────────────────────────────────────────────┐ │ IntelligentCommunity - 张三(业主) ┌──────────────┐│ │ ┌─────────────────────────────────────────┐ │ 自助缴费 ││ │ │ 车位申请 │ 车位查看 │ 缴费查询 │ 自助缴费 │ 业主: 张三 ││ │ │ 故障进度 │ 维修评价 │ │ 类型: 物业费 ││ │ ├─────────────────────────────────────────┤ │ 金额: [___] ││ │ │ 主窗口 │ │ [确认] [取消] ││ │ │ 仍然可以操作 │ └──────────────┘│ │ └─────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘阶段五:用户操作 - 维修进度 → 维修评价(联动流程)
cpp┌─────────────────────────────────────────────────────────────────┐ │ 用户点击 "故障进度" │ │ ↓ │ │ on_issueProcessAct_triggered() 被调用 │ │ ↓ │ │ ownerState = 2(标记已查看进度) │ │ ↓ │ │ 切换到 errorinfo 表,显示报修记录 │ │ ↓ │ │ 用户选择一行,点击 "维修评价" │ │ ↓ │ │ on_issueEvaluateAct_triggered() 被调用 │ │ ↓ │ │ 检查 ownerState == 2(必须查看过进度) │ │ ↓ │ │ 获取当前选中的 errornum │ │ ↓ │ │ 创建 issueAssessment 评价窗口 │ └─────────────────────────────────────────────────────────────────┘阶段六:窗口关闭
cpp用户点击窗口右上角 "×" ↓ 触发 QMainWindow 的关闭事件 ↓ 调用析构函数 ~OwnerManage() ↓ delete ui(释放 UI 对象) ↓ 由于 Qt 对象树机制,所有子对象自动释放 ↓ 窗口关闭,返回登录对话框完整数据流图
cpp┌─────────────────────────────────────────────────────────────────┐ │ 用户交互 │ │ ↓ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 工具栏按钮点击 │ │ │ └─────────────────────┬───────────────────────────────────┘ │ │ ↓ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ 槽函数被调用 │ │ │ │ 1. 切换表:setTable() │ │ │ │ 2. 设置过滤:setFilter() │ │ │ │ 3. 执行查询:select() │ │ │ │ 4. 设置表头:setHeaderData() │ │ │ └─────────────────────┬───────────────────────────────────┘ │ │ ↓ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ QSqlTableModel │ │ │ │ 1. 生成 SQL:SELECT * FROM carstation WHERE ... │ │ │ │ 2. 执行查询 │ │ │ │ 3. 返回数据 │ │ │ └─────────────────────┬───────────────────────────────────┘ │ │ ↓ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ QTableView(显示数据) │ │ │ │ 1. 从 Model 获取数据 │ │ │ │ 2. 按表头格式显示 │ │ │ │ 3. 用户看到结果 │ │ │ └─────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────┘函数调用关系图
cpp用户点击工具栏按钮 ↓ ┌─────────────────────────────────────────────────────────────────┐ │ 槽函数被调用 │ ├─────────────────────────────────────────────────────────────────┤ │ │ │ ① 车位申请 → on_applyCarStationAct_triggered() │ │ ↓ │ │ new ApplyCarStation → show() │ │ │ │ ② 车位查看 → on_showcCarStationAct_triggered() │ │ ↓ │ │ setTable("carstation") → setFilter() → select() │ │ → setHeaderData() → setModel() │ │ │ │ ③ 缴费查询 → on_payShowAct_triggered() │ │ ↓ │ │ setTable("priceRecord") → setFilter() → select() │ │ → setHeaderData() → setModel() │ │ │ │ ④ 自助缴费 → on_payAct_triggered() │ │ ↓ │ │ new ownerPaySelf() → setWindowTitle() → show() │ │ │ │ ⑤ 故障报修 → on_issueReportAct_triggered() │ │ ↓ │ │ new IssueInfo() → setUserName() → show() │ │ │ │ ⑥ 维修进度 → on_issueProcessAct_triggered() │ │ ↓ │ │ ownerState = 2 → setTable("errorinfo") → setFilter() │ │ → select() → setHeaderData() → setModel() │ │ │ │ ⑦ 维修评价 → on_issueEvaluateAct_triggered() │ │ ↓ │ │ if (ownerState == 2) → 获取选中行 → 获取 errornum │ │ → new issueAssessment() → setMessageIndex() → exec() │ │ │ └─────────────────────────────────────────────────────────────────┘3.ownerinfo.h
原始版本一
cpp#ifndef OWNERINFO_H #define OWNERINFO_H #include <QWidget> #include <QSqlTableModel> #include <QMessageBox> #include <QSqlRecord> #include <QDebug> namespace Ui { class OwnerInfo; } //业主信息登记类,共有集成QWidget类。 class OwnerInfo : public QWidget { Q_OBJECT public: explicit OwnerInfo(QWidget *parent = 0); ~OwnerInfo(); private: Ui::OwnerInfo *ui; QSqlTableModel *model; //SQL表格读写模型指针 bool judgeEmpty(); //判断工作人员输入"姓名"和"密码"是否为空 void clearAll(); //清除所有工作人员输入内容 signals: void EmitWorkerChanged(); private slots: void on_ownerInfoConfirmBtn_clicked(); //"确定"按键槽函数 void on_ownerInfoReturnBtn_clicked(); //"返回"按键槽函数 }; #endif // OWNERINFO_H修复版本二
无注释版
cppclass OwnerInfo : public QWidget { public: enum Mode { AddMode, EditMode }; void setMode(Mode mode); void setOwnerId(int id); private: Mode m_mode; int m_ownerId; }; model->setFilter(QString("ownername = '%1'").arg(name)); model->select(); if (model->rowCount() > 0) { /* 已存在 */ } if (!model->submitAll()) { QMessageBox::critical(this, "错误", "保存失败:" + model->lastError().text()); model->revertAll(); }有注释版
cpp// ============================================================ // 优化1:添加编辑模式 // ============================================================ class OwnerInfo : public QWidget { public: enum Mode { AddMode, EditMode }; void setMode(Mode mode); void setOwnerId(int id); // 编辑时设置要修改的业主ID private: Mode m_mode; int m_ownerId; }; // ============================================================ // 优化2:使用 setFilter 检查重复 // ============================================================ // ❌ 当前:加载所有数据 model->select(); for (int i = 0; i < model->rowCount(); i++) { ... } // ✅ 优化:只查询特定姓名 model->setFilter(QString("ownername = '%1'").arg(name)); model->select(); if (model->rowCount() > 0) { /* 已存在 */ } // ============================================================ // 优化3:添加错误处理 // ============================================================ if (!model->submitAll()) { QMessageBox::critical(this, "错误", "保存失败:" + model->lastError().text()); model->revertAll(); }3.ownerinfo.cpp
原始版本一
cpp#include "ownerinfo.h" #include "ui_ownerinfo.h" /********业主登记类OwnerInfo构造函数*******************************************/ OwnerInfo::OwnerInfo(QWidget *parent) : QWidget(parent), ui(new Ui::OwnerInfo) { ui->setupUi(this); //设置model实现与数据库交互 model=new QSqlTableModel(this); //创建SQL连接 model->setTable("houseowner"); //设置访问表为"houseowner" model->setEditStrategy(QSqlTableModel::OnManualSubmit); //设置数据库编辑模式 model->removeColumns(5,5); //移除当前列之后的5列数据 } /********业主登记类OwnerInfo析构函数*******************************************/ OwnerInfo::~OwnerInfo() { delete ui; } /********《槽函数》"确认"按键执行操作函数*************************************/ void OwnerInfo::on_ownerInfoConfirmBtn_clicked() { if(!this->judgeEmpty()) //判断输入内容是否为空 return; model->select(); //数据查询 int i; for(i=0;i<model->rowCount();i++) //循环检测所有行数据 { //如果当前行的第一个数据与工作人员输入的新业主名字一致,则是重复登记,退出循环 if(model->data(model->index(i,0)).toString()==ui->ownerNameLineEdit->text()) { break; } } if(i!=model->rowCount())//如果检索到有重复的业主名,则退出本次操作,并警告 { QMessageBox::information(this,"提示","该业主已经存在",QMessageBox::Yes); this->clearAll(); //清除所有输入内容 return; } //如果没在数据库中检索到新的业主名,则可以进行添加操作 QSqlRecord record=model->record(); //获取新行记录 //将工作人员输入的名字写入数据库的"ownername"字段 record.setValue("ownername",ui->ownerNameLineEdit->text()); record.setValue("ownerpass",ui->ownerPassLineEdit->text()); record.setValue("owneraddress",ui->ownerAddressLineEdit->text()); record.setValue("ownerphone",ui->ownerPhoneLineEdit->text()); model->insertRecord(-1,record); //向尾部添加新用户数据 if(model->submitAll()) //提交修改 { QMessageBox::information(this,"提示","业主添加成功",QMessageBox::Yes); //显示提示窗口 this->clearAll(); //清除输入所有内容 } } /********《槽函数》"返回"按键执行操作函数*************************************/ void OwnerInfo::on_ownerInfoReturnBtn_clicked() { //如果窗口没有输入任何内容 if(ui->ownerNameLineEdit->text().isEmpty()&&ui->ownerPhoneLineEdit->text().isEmpty()&& ui->ownerPassLineEdit->text().isEmpty()&&ui->ownerAddressLineEdit->text().isEmpty()) { emit EmitWorkerChanged();//发送信号............................实际没用???? this->hide(); //隐藏窗口 qDebug("addworker"); //输出调试信息 return; //返回 } //如果窗口内有部分输入的内容,打开提示窗口 if(QMessageBox::question(this,"提示","尚未保存,是否退出", QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes) { //emit EmitToTeacherManage(); this->hide(); //隐藏窗口 } } /********判断工作人员输入"姓名"和"密码"是否为空函数**********************/ bool OwnerInfo::judgeEmpty() { if(ui->ownerNameLineEdit->text().isEmpty()) //如果工作人员输入的"姓名"内容为空 { //输出警告信息 QMessageBox::warning(this,"警告","业主姓名不能为空",QMessageBox::Yes); return false; } else if(ui->ownerPassLineEdit->text().isEmpty())//如果工作人员输入的"密码"内容为空 { //输出警告信息 QMessageBox::warning(this,"警告","业主密码不能为空",QMessageBox::Yes); return false; } else return true; } /********清除工作人员输入函数************************************************/ void OwnerInfo::clearAll() { ui->ownerNameLineEdit->clear(); //清除工作人员输入的"姓名"内容 ui->ownerPassLineEdit->clear(); // "密码" ui->ownerPhoneLineEdit->clear(); // "电话" ui->ownerAddressLineEdit->clear(); // "住址" }修复版本二
无注释版
cpp#include "ownerinfo.h" #include "ui_ownerinfo.h" OwnerInfo::OwnerInfo(QWidget *parent) : QWidget(parent), ui(new Ui::OwnerInfo) { ui->setupUi(this); model = new QSqlTableModel(this); model->setTable("houseowner"); model->setEditStrategy(QSqlTableModel::OnManualSubmit); model->removeColumns(5, 5); } OwnerInfo::~OwnerInfo() { delete ui; } void OwnerInfo::on_ownerInfoConfirmBtn_clicked() { if (!this->judgeEmpty()) { return; } model->select(); int i; for (i = 0; i < model->rowCount(); i++) { if (model->data(model->index(i, 0)).toString() == ui->ownerNameLineEdit->text()) { break; } } if (i != model->rowCount()) { QMessageBox::information(this, "提示", "该业主已经存在", QMessageBox::Yes); this->clearAll(); return; } QSqlRecord record = model->record(); record.setValue("ownername", ui->ownerNameLineEdit->text()); record.setValue("ownerpass", ui->ownerPassLineEdit->text()); record.setValue("owneraddress", ui->ownerAddressLineEdit->text()); record.setValue("ownerphone", ui->ownerPhoneLineEdit->text()); model->insertRecord(-1, record); if (model->submitAll()) { QMessageBox::information(this, "提示", "业主添加成功", QMessageBox::Yes); this->clearAll(); } } void OwnerInfo::on_ownerInfoReturnBtn_clicked() { if (ui->ownerNameLineEdit->text().isEmpty() && ui->ownerPhoneLineEdit->text().isEmpty() && ui->ownerPassLineEdit->text().isEmpty() && ui->ownerAddressLineEdit->text().isEmpty()) { emit EmitWorkerChanged(); this->hide(); qDebug("addworker"); return; } if (QMessageBox::question(this, "提示", "尚未保存,是否退出", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { this->hide(); } } bool OwnerInfo::judgeEmpty() { if (ui->ownerNameLineEdit->text().isEmpty()) { QMessageBox::warning(this, "警告", "业主姓名不能为空", QMessageBox::Yes); return false; } if (ui->ownerPassLineEdit->text().isEmpty()) { QMessageBox::warning(this, "警告", "业主密码不能为空", QMessageBox::Yes); return false; } return true; } void OwnerInfo::clearAll() { ui->ownerNameLineEdit->clear(); ui->ownerPassLineEdit->clear(); ui->ownerPhoneLineEdit->clear(); ui->ownerAddressLineEdit->clear(); }有注释版
cpp// ============================================================ // 文件:ownerinfo.cpp // 功能:业主信息登记/编辑 // 说明:添加新业主或修改业主信息 // ============================================================ #include "ownerinfo.h" // 包含自己的头文件声明 #include "ui_ownerinfo.h" // 包含由 .ui 文件生成的 UI 类头文件 // ============================================================ // 构造函数 - 初始化业主信息界面 // ============================================================ OwnerInfo::OwnerInfo(QWidget *parent) : QWidget(parent), // 调用父类 QWidget 构造函数 ui(new Ui::OwnerInfo) // 创建 UI 对象 { ui->setupUi(this); // 加载 .ui 界面文件 // ============================================================ // 设置数据模型 // ============================================================ model = new QSqlTableModel(this); // 创建 SQL 表格模型,设置父对象为 this(自动内存管理) model->setTable("houseowner"); // 设置要操作的数据表为 "houseowner"(业主表) model->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略为"手动提交" // 修改后需要调用 submitAll() 才会保存到数据库 model->removeColumns(5, 5); // 从第5列开始,移除5列(隐藏不需要显示的列) // ⚠️ 问题:注释不清晰,不确定移除了哪些列 } // ============================================================ // 析构函数 - 释放资源 // ============================================================ OwnerInfo::~OwnerInfo() { delete ui; // 删除 UI 对象,释放界面控件内存 // model 不需要手动 delete,因为设置了父对象 this } // ============================================================ // "确认"按钮槽函数 - 添加业主 // ============================================================ void OwnerInfo::on_ownerInfoConfirmBtn_clicked() { // -------------------------------------------------------- // 1. 输入验证 // -------------------------------------------------------- if (!this->judgeEmpty()) { // 判断输入是否为空(姓名和密码不能为空) // 如果为空,judgeEmpty() 已弹出警告框,直接返回 return; } // -------------------------------------------------------- // 2. 查询数据库,检查业主是否已存在 // -------------------------------------------------------- model->select(); // 执行查询,从 houseowner 表加载所有数据 int i; for (i = 0; i < model->rowCount(); i++) { // 遍历所有行,检查姓名是否重复 // model->index(i, 0) 获取第 i 行第 0 列(ownername 字段) // data() 获取单元格数据,toString() 转为字符串 if (model->data(model->index(i, 0)).toString() == ui->ownerNameLineEdit->text()) { // 如果当前行的业主名与输入的一致,说明已存在 break; // 退出循环 } } // -------------------------------------------------------- // 3. 检查是否找到重复记录 // -------------------------------------------------------- if (i != model->rowCount()) { // 如果 i 不等于总行数,说明在循环中找到了重复记录(break 提前退出) QMessageBox::information(this, "提示", "该业主已经存在", QMessageBox::Yes); this->clearAll(); // 清除所有输入框 return; // 退出函数 } // -------------------------------------------------------- // 4. 添加新业主记录 // -------------------------------------------------------- QSqlRecord record = model->record(); // 获取一个空记录结构(包含所有字段,但没有数据) // 将用户输入的值设置到记录中 record.setValue("ownername", ui->ownerNameLineEdit->text()); // 业主姓名 record.setValue("ownerpass", ui->ownerPassLineEdit->text()); // 业主密码 record.setValue("owneraddress", ui->ownerAddressLineEdit->text()); // 业主地址 record.setValue("ownerphone", ui->ownerPhoneLineEdit->text()); // 业主电话 model->insertRecord(-1, record); // 插入记录到模型末尾(-1 表示追加到最后) // -------------------------------------------------------- // 5. 提交数据到数据库 // -------------------------------------------------------- if (model->submitAll()) { // submitAll() 提交所有待处理的修改到数据库 // 返回 true 表示提交成功 QMessageBox::information(this, "提示", "业主添加成功", QMessageBox::Yes); this->clearAll(); // 清除输入框,准备添加下一个 } // ⚠️ 问题:如果提交失败,没有错误提示 } // ============================================================ // "返回"按钮槽函数 - 关闭窗口 // ============================================================ void OwnerInfo::on_ownerInfoReturnBtn_clicked() { // -------------------------------------------------------- // 1. 检查是否有输入内容 // -------------------------------------------------------- if (ui->ownerNameLineEdit->text().isEmpty() && ui->ownerPhoneLineEdit->text().isEmpty() && ui->ownerPassLineEdit->text().isEmpty() && ui->ownerAddressLineEdit->text().isEmpty()) { // 所有输入框都为空 → 直接关闭 emit EmitWorkerChanged(); // 发射信号(通知其他模块数据已变更) // ⚠️ 问题:信号名拼写可能有问题,且未连接 this->hide(); // 隐藏窗口(不是关闭) qDebug("addworker"); // 调试输出 return; } // -------------------------------------------------------- // 2. 有输入内容 → 询问是否保存 // -------------------------------------------------------- if (QMessageBox::question(this, "提示", "尚未保存,是否退出", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { // 用户选择"是" → 放弃修改并退出 // emit EmitToTeacherManage(); // 已注释 this->hide(); // 隐藏窗口 } // 用户选择"否" → 什么都不做,继续编辑 } // ============================================================ // 判断输入是否为空 // ============================================================ bool OwnerInfo::judgeEmpty() { // -------------------------------------------------------- // 1. 检查业主姓名 // -------------------------------------------------------- if (ui->ownerNameLineEdit->text().isEmpty()) { QMessageBox::warning(this, "警告", "业主姓名不能为空", QMessageBox::Yes); return false; } // -------------------------------------------------------- // 2. 检查业主密码 // -------------------------------------------------------- if (ui->ownerPassLineEdit->text().isEmpty()) { QMessageBox::warning(this, "警告", "业主密码不能为空", QMessageBox::Yes); return false; } // 姓名和密码都不为空 → 验证通过 return true; } // ============================================================ // 清空所有输入框 // ============================================================ void OwnerInfo::clearAll() { ui->ownerNameLineEdit->clear(); // 清空姓名 ui->ownerPassLineEdit->clear(); // 清空密码 ui->ownerPhoneLineEdit->clear(); // 清空电话 ui->ownerAddressLineEdit->clear(); // 清空地址 }核心功能:添加业主
cpp用户输入业主信息 ↓ 点击"确认"按钮 ↓ ┌─────────────────────────────────────────────────────────────────────┐ │ on_ownerInfoConfirmBtn_clicked() │ ├─────────────────────────────────────────────────────────────────────┤ │ 1. judgeEmpty() → 检查姓名和密码是否为空 │ │ ↓ │ │ 2. 查询数据库 → 检查业主是否已存在 │ │ ↓ │ │ 3. 如果已存在 → 提示"该业主已经存在" → 清空输入 → 返回 │ │ ↓ │ │ 4. 如果不存在 → 创建记录 → insertRecord() → submitAll() │ │ ↓ │ │ 5. 成功 → 提示"业主添加成功" → 清空输入 │ │ 失败 → ❌ 没有错误处理 │ └─────────────────────────────────────────────────────────────────────┘ownerinfo.ui
在管理人员界面可以添加业主信息
4.ownerpayself.h
原始版本一
cpp#ifndef OWNERPAYSELF_H #define OWNERPAYSELF_H #include <QWidget> namespace Ui { class ownerPaySelf; } //缴费类,公有继承QWidget //使用UI设计师完成界面开发 class ownerPaySelf : public QWidget { Q_OBJECT public: explicit ownerPaySelf(QWidget *parent = 0); ~ownerPaySelf(); bool updateState(int nType); private slots: void on_pushButton_clicked(); //"确认"按键槽函数 void on_pushButton_2_clicked(); //"返回"按键槽函数 private: Ui::ownerPaySelf *ui; double getOwnerArrears(const QString &ownerName); bool hasPaid(const QString &ownerName, const QString &type); }; #endif // OWNERPAYSELF_H修复版本二
无注释版
cpp#ifndef OWNERPAYSELF_H #define OWNERPAYSELF_H #include <QWidget> namespace Ui { class ownerPaySelf; } class ownerPaySelf : public QWidget { Q_OBJECT public: explicit ownerPaySelf(QWidget *parent = 0); ~ownerPaySelf(); bool updateState(int nType); private slots: void on_pushButton_clicked(); void on_pushButton_2_clicked(); private: Ui::ownerPaySelf *ui; double getOwnerArrears(const QString &ownerName); bool hasPaid(const QString &ownerName, const QString &type); }; #endif // OWNERPAYSELF_H有注释版
cpp// ============================================================ // 文件:ownerpayself.h // 功能:业主自助缴费界面的头文件声明 // 说明:业主可以在这里缴纳物业费、车位费等各项费用 // ============================================================ #ifndef OWNERPAYSELF_H // 作用:防止头文件被多次包含(Include Guard) // 如果 OWNERPAYSELF_H 未定义,则定义它并包含头文件内容 // 如果已定义,则跳过整个头文件内容 #define OWNERPAYSELF_H // 定义宏 OWNERPAYSELF_H,标记这个头文件已经被包含 // ============================================================ // 头文件包含 // ============================================================ #include <QWidget> // 包含 QWidget 基类 // QWidget 是所有 Qt 窗口控件的基类 // 本类继承 QWidget,作为一个独立的窗口部件 // ============================================================ // UI 命名空间声明 // ============================================================ namespace Ui { class ownerPaySelf; // 声明 UI 类 // 这个类由 Qt 的 uic 工具根据 ownerpayself.ui 文件自动生成 // 包含了界面上所有控件的指针(输入框、按钮、下拉框等) } // ============================================================ // ownerPaySelf 类定义 // 业主自助缴费窗口,继承自 QWidget // ============================================================ class ownerPaySelf : public QWidget // class ownerPaySelf : 定义一个名为 ownerPaySelf 的类 // public QWidget : 公有继承自 QWidget 基类 // 作为独立的窗口部件,可以嵌入到其他窗口或单独显示 { Q_OBJECT // Qt 元对象宏 // 启用信号槽机制、运行时类型信息等 Qt 元对象功能 // 因为类中使用了 private slots,必须包含此宏 public: // ============================================================ // public 区域:对外公开的接口 // ============================================================ explicit ownerPaySelf(QWidget *parent = 0); // 构造函数 // explicit: 防止隐式类型转换 // QWidget *parent = 0: 父窗口指针,默认值为 nullptr ~ownerPaySelf(); // 析构函数 // 当对象被销毁时自动调用,释放资源 bool updateState(int nType); // 更新缴费状态函数(公开接口) // 参数:nType - 缴费类型(0: 车位费, 1: 物业费) // 返回值:true - 更新成功,false - 更新失败 // 在缴费成功后调用,更新对应表的缴费状态 private slots: // ============================================================ // 私有槽函数区域 // 响应按钮点击事件 // ============================================================ void on_pushButton_clicked(); // "确认"按钮的槽函数 // 当用户点击"确认"时被调用 // 功能:验证输入 → 构建缴费记录 → 保存到数据库 → 更新状态 void on_pushButton_2_clicked(); // "返回"按钮的槽函数 // 当用户点击"返回"时被调用 // 功能:关闭当前缴费窗口 private: // ============================================================ // private 区域:私有的成员变量和函数 // 只能在类内部访问,外部不可见 // ============================================================ Ui::ownerPaySelf *ui; // UI 对象指针 // 指向由 uic 工具生成的 UI 类对象 // 通过这个指针可以访问界面上所有的控件 // 例如:ui->lineEdit(金额输入框) // ui->comboBox(缴费类型下拉框) // ui->lineEdit_2(业主姓名输入框) // ui->pushButton(确认按钮) // ui->pushButton_2(返回按钮) // ============================================================ // 私有辅助函数 // ============================================================ double getOwnerArrears(const QString &ownerName); // 获取业主欠费总额 // 参数:ownerName - 业主姓名 // 返回值:欠费总金额(double 类型) // 查询数据库中该业主所有未缴费的记录,汇总金额 // ✅ 新增功能(扩展功能) bool hasPaid(const QString &ownerName, const QString &type); // 检查是否已缴费(防止重复缴费) // 参数:ownerName - 业主姓名,type - 缴费类型 // 返回值:true - 已缴费,false - 未缴费 // 用于防止业主对同一项目重复缴费 // ✅ 新增功能(扩展功能) }; #endif // OWNERPAYSELF_H // 结束条件编译块 // 如果头文件被重复包含,从 #ifndef 到 #endif 之间的内容会被跳过功能流程图
cpp业主打开自助缴费窗口 ↓ 输入缴费金额 ↓ 选择缴费类型(物业费/车位费/其他) ↓ 点击"确认"按钮 ↓ ┌─────────────────────────────────────────────────────────────────────┐ │ on_pushButton_clicked() │ ├─────────────────────────────────────────────────────────────────────┤ │ 1. 验证输入 │ │ ↓ 金额为空 → 提示"请输入缴费金额" │ │ ↓ 业主名为空 → 提示"请输入业主姓名" │ │ 2. 构建缴费记录 │ │ → 业主姓名、缴费类型、缴费金额、缴费时间 │ │ 3. 插入到 priceRecord 表 │ │ 4. 提交到数据库 │ │ 5. 更新状态(调用 updateState()) │ │ ↓ 成功 → 提示"缴费成功!" │ │ ↓ 失败 → 提示"缴费出错,请重新缴费" │ └─────────────────────────────────────────────────────────────────────┘4.ownerpayself.cpp
原始版本一
cpp// ============================================================ // 文件:ownerpayself.cpp // 功能:业主自助缴费模块 // ============================================================ #include "ownerpayself.h" #include "ui_ownerpayself.h" #include <QRegularExpression> // Qt 6 推荐的正则表达式 #include <QRegularExpressionValidator> // Qt 6 推荐的验证器 #include <QSqlTableModel> #include <QSqlRecord> #include <QSqlQuery> #include <QSqlError> #include <QMessageBox> #include <QDateTime> #include <QDebug> // ============================================================ // 构造函数 - 初始化界面和验证器 // ============================================================ ownerPaySelf::ownerPaySelf(QWidget *parent) : QWidget(parent), ui(new Ui::ownerPaySelf) { ui->setupUi(this); // -------------------------------------------------------- // 1. 设置输入验证器:只允许输入数字 // 使用 QRegularExpressionValidator 替代 QRegExpValidator // -------------------------------------------------------- QRegularExpression regx("[0-9]+$"); QValidator* validator = new QRegularExpressionValidator(regx, this); ui->lineEdit->setValidator(validator); // -------------------------------------------------------- // 2. 显示当前时间 // -------------------------------------------------------- QDateTime currentTime = QDateTime::currentDateTime(); QString timeStr = currentTime.toString("yyyy-MM-dd hh:mm:ss"); qDebug() << "缴费窗口初始化成功,当前时间:" << timeStr; } // ============================================================ // 析构函数 - 释放资源 // ============================================================ ownerPaySelf::~ownerPaySelf() { delete ui; } // ============================================================ // "确认缴费"按钮槽函数 // ============================================================ void ownerPaySelf::on_pushButton_clicked() { // -------------------------------------------------------- // 1. 获取并验证用户输入 // -------------------------------------------------------- QString strValue = ui->lineEdit->text().trimmed(); if (strValue.isEmpty()) { QMessageBox::warning(this, tr("提示"), tr("请输入缴费金额!")); ui->lineEdit->setFocus(); return; } // 验证金额是否为有效数字 bool ok; double amount = strValue.toDouble(&ok); if (!ok || amount <= 0) { QMessageBox::warning(this, tr("提示"), tr("请输入有效的金额!")); ui->lineEdit->clear(); ui->lineEdit->setFocus(); return; } QString strType = ui->comboBox->currentText(); QString ownerName = ui->lineEdit_2->text().trimmed(); // 检查业主姓名是否为空 if (ownerName.isEmpty()) { QMessageBox::warning(this, tr("提示"), tr("请先输入业主姓名!")); ui->lineEdit_2->setFocus(); return; } // -------------------------------------------------------- // 2. 使用 QSqlTableModel 保存缴费记录 // -------------------------------------------------------- QSqlTableModel *tableModel = new QSqlTableModel(this); tableModel->setTable("priceRecord"); if (!tableModel->select()) { QMessageBox::critical(this, tr("错误"), tr("数据库查询失败:") + tableModel->lastError().text()); delete tableModel; return; } // -------------------------------------------------------- // 3. 构建缴费记录 // -------------------------------------------------------- QSqlRecord record = tableModel->record(); record.setValue("ownername", ownerName); record.setValue("type", strType); record.setValue("price", strValue); QDateTime time = QDateTime::currentDateTime(); QString strTime = time.toString("yyyy-MM-dd hh:mm:ss"); record.setValue("time", strTime); // -------------------------------------------------------- // 4. 插入记录到数据库 // -------------------------------------------------------- if (!tableModel->insertRecord(-1, record)) { QMessageBox::critical(this, tr("错误"), tr("插入记录失败:") + tableModel->lastError().text()); delete tableModel; return; } // -------------------------------------------------------- // 5. 提交数据到数据库 // -------------------------------------------------------- bool submitSuccess = tableModel->submitAll(); if (submitSuccess) { bool updateSuccess = updateState(ui->comboBox->currentIndex()); if (updateSuccess) { QMessageBox::information(this, tr("提示"), tr("缴费成功!")); ui->lineEdit->clear(); qDebug() << "缴费成功:" << ownerName << strType << strValue << strTime; } else { tableModel->revertAll(); QMessageBox::warning(this, tr("提示"), tr("缴费记录已保存,但状态更新失败,请检查!")); } } else { tableModel->revertAll(); QMessageBox::critical(this, tr("错误"), tr("保存失败:") + tableModel->lastError().text()); } delete tableModel; } // ============================================================ // "返回"按钮槽函数 // ============================================================ void ownerPaySelf::on_pushButton_2_clicked() { this->close(); } // ============================================================ // 更新缴费状态 // ============================================================ bool ownerPaySelf::updateState(int nType) { QString ownerName = ui->lineEdit_2->text().trimmed(); if (ownerName.isEmpty()) { qDebug() << "更新状态失败:业主姓名为空"; return false; } if (0 == nType) { // 车位费缴费 QSqlQuery query; query.prepare("UPDATE carstation SET paystate = '已缴费' WHERE ownername = :ownerName"); query.bindValue(":ownerName", ownerName); if (!query.exec()) { qDebug() << "更新车位状态失败:" << query.lastError().text(); QMessageBox::critical(this, tr("错误"), tr("更新车位状态失败:") + query.lastError().text()); return false; } if (query.numRowsAffected() == 0) { qDebug() << "未找到对应的车位记录:" << ownerName; QMessageBox::warning(this, tr("提示"), tr("未找到业主 '%1' 的车位记录!").arg(ownerName)); return false; } qDebug() << "车位缴费状态更新成功,业主:" << ownerName; return true; } else { qDebug() << "物业费缴费功能待实现"; return false; } } // ============================================================ // 【扩展功能】获取当前业主的欠费信息 // ============================================================ double ownerPaySelf::getOwnerArrears(const QString &ownerName) { QSqlQuery query; query.prepare("SELECT SUM(price) FROM priceRecord WHERE ownername = :ownerName AND status = '未缴费'"); query.bindValue(":ownerName", ownerName); if (query.exec() && query.next()) { return query.value(0).toDouble(); } return 0.0; } // ============================================================ // 【扩展功能】检查是否已缴费 // ============================================================ bool ownerPaySelf::hasPaid(const QString &ownerName, const QString &type) { QSqlQuery query; query.prepare("SELECT COUNT(*) FROM priceRecord WHERE ownername = :ownerName AND type = :type AND time >= date('now', 'start of month')"); query.bindValue(":ownerName", ownerName); query.bindValue(":type", type); if (query.exec() && query.next()) { return query.value(0).toInt() > 0; } return false; }修复版本二
无注释版
cpp#include "ownerpayself.h" #include "ui_ownerpayself.h" #include <QRegularExpression> #include <QRegularExpressionValidator> #include <QSqlTableModel> #include <QSqlRecord> #include <QSqlQuery> #include <QSqlError> #include <QMessageBox> #include <QDateTime> #include <QDebug> ownerPaySelf::ownerPaySelf(QWidget *parent) : QWidget(parent), ui(new Ui::ownerPaySelf) { ui->setupUi(this); QRegularExpression regx("[0-9]+$"); QValidator* validator = new QRegularExpressionValidator(regx, this); ui->lineEdit->setValidator(validator); QDateTime currentTime = QDateTime::currentDateTime(); QString timeStr = currentTime.toString("yyyy-MM-dd hh:mm:ss"); qDebug() << "缴费窗口初始化成功,当前时间:" << timeStr; } ownerPaySelf::~ownerPaySelf() { delete ui; } void ownerPaySelf::on_pushButton_clicked() { QString strValue = ui->lineEdit->text().trimmed(); if (strValue.isEmpty()) { QMessageBox::warning(this, tr("提示"), tr("请输入缴费金额!")); ui->lineEdit->setFocus(); return; } bool ok; double amount = strValue.toDouble(&ok); if (!ok || amount <= 0) { QMessageBox::warning(this, tr("提示"), tr("请输入有效的金额!")); ui->lineEdit->clear(); ui->lineEdit->setFocus(); return; } QString strType = ui->comboBox->currentText(); QString ownerName = ui->lineEdit_2->text().trimmed(); if (ownerName.isEmpty()) { QMessageBox::warning(this, tr("提示"), tr("请先输入业主姓名!")); ui->lineEdit_2->setFocus(); return; } QSqlTableModel *tableModel = new QSqlTableModel(this); tableModel->setTable("priceRecord"); if (!tableModel->select()) { QMessageBox::critical(this, tr("错误"), tr("数据库查询失败:") + tableModel->lastError().text()); delete tableModel; return; } QSqlRecord record = tableModel->record(); record.setValue("ownername", ownerName); record.setValue("type", strType); record.setValue("price", strValue); QDateTime time = QDateTime::currentDateTime(); QString strTime = time.toString("yyyy-MM-dd hh:mm:ss"); record.setValue("time", strTime); if (!tableModel->insertRecord(-1, record)) { QMessageBox::critical(this, tr("错误"), tr("插入记录失败:") + tableModel->lastError().text()); delete tableModel; return; } bool submitSuccess = tableModel->submitAll(); if (submitSuccess) { bool updateSuccess = updateState(ui->comboBox->currentIndex()); if (updateSuccess) { QMessageBox::information(this, tr("提示"), tr("缴费成功!")); ui->lineEdit->clear(); qDebug() << "缴费成功:" << ownerName << strType << strValue << strTime; } else { tableModel->revertAll(); QMessageBox::warning(this, tr("提示"), tr("缴费记录已保存,但状态更新失败,请检查!")); } } else { tableModel->revertAll(); QMessageBox::critical(this, tr("错误"), tr("保存失败:") + tableModel->lastError().text()); } delete tableModel; } void ownerPaySelf::on_pushButton_2_clicked() { this->close(); } bool ownerPaySelf::updateState(int nType) { QString ownerName = ui->lineEdit_2->text().trimmed(); if (ownerName.isEmpty()) { qDebug() << "更新状态失败:业主姓名为空"; return false; } if (0 == nType) { QSqlQuery query; query.prepare("UPDATE carstation SET paystate = '已缴费' WHERE ownername = :ownerName"); query.bindValue(":ownerName", ownerName); if (!query.exec()) { qDebug() << "更新车位状态失败:" << query.lastError().text(); QMessageBox::critical(this, tr("错误"), tr("更新车位状态失败:") + query.lastError().text()); return false; } if (query.numRowsAffected() == 0) { qDebug() << "未找到对应的车位记录:" << ownerName; QMessageBox::warning(this, tr("提示"), tr("未找到业主 '%1' 的车位记录!").arg(ownerName)); return false; } qDebug() << "车位缴费状态更新成功,业主:" << ownerName; return true; } else { qDebug() << "物业费缴费功能待实现"; return false; } } double ownerPaySelf::getOwnerArrears(const QString &ownerName) { QSqlQuery query; query.prepare("SELECT SUM(price) FROM priceRecord WHERE ownername = :ownerName AND status = '未缴费'"); query.bindValue(":ownerName", ownerName); if (query.exec() && query.next()) { return query.value(0).toDouble(); } return 0.0; } bool ownerPaySelf::hasPaid(const QString &ownerName, const QString &type) { QSqlQuery query; query.prepare("SELECT COUNT(*) FROM priceRecord WHERE ownername = :ownerName AND type = :type AND time >= date('now', 'start of month')"); query.bindValue(":ownerName", ownerName); query.bindValue(":type", type); if (query.exec() && query.next()) { return query.value(0).toInt() > 0; } return false; }有注释版
cpp// ============================================================ // 文件:ownerpayself.cpp // 功能:业主自助缴费模块 // 说明:业主可以在此缴纳物业费、车位费等费用 // ============================================================ #include "ownerpayself.h" // 包含自己的头文件声明 // 让编译器知道类 ownerPaySelf 的结构、成员函数和成员变量 #include "ui_ownerpayself.h" // 包含由 .ui 文件生成的 UI 类头文件 // 包含了 Ui::ownerPaySelf 类的定义,其中有所有控件的指针 #include <QRegularExpression> // 包含 Qt 6 的正则表达式类 // 用于验证用户输入的金额是否为纯数字 #include <QRegularExpressionValidator> // 包含 Qt 6 的正则表达式验证器 // 用于限制用户输入只能匹配指定的正则表达式 #include <QSqlTableModel> // 包含 SQL 表格模型类 // 用于与数据库表交互,执行增删改查操作 #include <QSqlRecord> // 包含 SQL 记录类 // 用于表示数据库中的一条记录(一行数据) #include <QSqlQuery> // 包含 SQL 查询类 // 用于执行 SQL 语句和获取结果 #include <QSqlError> // 包含 SQL 错误类 // 用于获取数据库操作失败时的错误信息 #include <QMessageBox> // 包含消息框类 // 用于显示提示、警告、错误等信息 #include <QDateTime> // 包含日期时间类 // 用于获取当前时间,记录缴费时间 #include <QDebug> // 包含调试输出类 // 用于在控制台打印调试信息 // ============================================================ // 构造函数 - 初始化界面和验证器 // 参数:parent - 父窗口指针,默认 nullptr // 当业主点击"自助缴费"时,此对象被创建 // ============================================================ ownerPaySelf::ownerPaySelf(QWidget *parent) : QWidget(parent), // 调用父类 QWidget 的构造函数,传入父窗口指针 ui(new Ui::ownerPaySelf) // 创建 UI 对象(由 Qt Designer 生成的界面类) { ui->setupUi(this); // setupUi() 加载 .ui 文件,创建所有控件并设置布局 // 相当于把 UI 设计师设计的界面加载到当前窗口 // -------------------------------------------------------- // 1. 设置输入验证器:只允许输入数字 // 使用 QRegularExpressionValidator 限制用户只能输入纯数字 // 防止输入非数字字符导致程序异常 // -------------------------------------------------------- QRegularExpression regx("[0-9]+$"); // 创建正则表达式对象 // "[0-9]+$" 含义: // [0-9] 匹配 0-9 之间的任意数字 // + 匹配一次或多次 // $ 匹配字符串结尾 // 整体含义:整个字符串必须全部是数字 QValidator* validator = new QRegularExpressionValidator(regx, this); // 创建正则表达式验证器 // 参数1:正则表达式对象 // 参数2:父对象 this(自动内存管理) // 验证器会检查用户输入是否符合正则表达式 ui->lineEdit->setValidator(validator); // 将验证器设置到金额输入框 // 用户只能输入数字,字母和符号会被自动过滤 // -------------------------------------------------------- // 2. 显示当前时间(用于调试) // -------------------------------------------------------- QDateTime currentTime = QDateTime::currentDateTime(); // 获取当前系统时间 QString timeStr = currentTime.toString("yyyy-MM-dd hh:mm:ss"); // 将时间格式化为字符串 // 格式:年-月-日 时:分:秒 // 例如:2026-08-22 14:30:00 qDebug() << "缴费窗口初始化成功,当前时间:" << timeStr; // 输出调试信息到控制台 // 方便开发者确认窗口已成功创建 } // ============================================================ // 析构函数 - 释放资源 // 当窗口关闭时自动调用 // ============================================================ ownerPaySelf::~ownerPaySelf() { delete ui; // 删除 UI 对象,释放界面上所有控件的内存 // 这是必须的,因为 ui 是在构造函数中用 new 创建的 // Qt 的对象树机制会自动释放子对象,但 ui 本身需要手动释放 } // ============================================================ // "确认缴费"按钮槽函数 // 当用户点击"确认"按钮时被调用 // 功能:验证输入 → 构建记录 → 保存到数据库 // ============================================================ void ownerPaySelf::on_pushButton_clicked() { // -------------------------------------------------------- // 1. 获取并验证用户输入 // -------------------------------------------------------- QString strValue = ui->lineEdit->text().trimmed(); // 获取金额输入框的文本,去除首尾空格 if (strValue.isEmpty()) { // 如果金额为空 QMessageBox::warning(this, tr("提示"), tr("请输入缴费金额!")); // 弹出警告框提示用户 ui->lineEdit->setFocus(); // 将焦点设置到金额输入框,让用户输入 return; // 退出函数 } bool ok; double amount = strValue.toDouble(&ok); // 将字符串转换为 double 类型 // ok 用于判断转换是否成功 if (!ok || amount <= 0) { // 如果转换失败(不是数字)或金额小于等于 0 QMessageBox::warning(this, tr("提示"), tr("请输入有效的金额!")); // 弹出警告框提示用户 ui->lineEdit->clear(); // 清空金额输入框 ui->lineEdit->setFocus(); // 将焦点设置到金额输入框 return; // 退出函数 } QString strType = ui->comboBox->currentText(); // 获取缴费类型下拉框的当前选中文本 // 例如:"物业费"、"车位费"等 QString ownerName = ui->lineEdit_2->text().trimmed(); // 获取业主姓名输入框的文本,去除首尾空格 if (ownerName.isEmpty()) { // 如果业主姓名为空 QMessageBox::warning(this, tr("提示"), tr("请先输入业主姓名!")); // 弹出警告框提示用户 ui->lineEdit_2->setFocus(); // 将焦点设置到业主姓名输入框 return; // 退出函数 } // -------------------------------------------------------- // 2. 使用 QSqlTableModel 保存缴费记录 // ✅ 在堆上创建,避免栈上对象生命周期问题 // -------------------------------------------------------- QSqlTableModel *tableModel = new QSqlTableModel(this); // 创建 SQL 表格模型对象 // 参数 this 表示父对象是当前窗口,由 Qt 自动管理内存 tableModel->setTable("priceRecord"); // 设置要操作的数据表为 "priceRecord"(缴费记录表) if (!tableModel->select()) { // 执行查询,如果失败则进入 if QMessageBox::critical(this, tr("错误"), tr("数据库查询失败:") + tableModel->lastError().text()); // 弹出错误对话框,显示具体错误信息 delete tableModel; // 释放模型对象 return; // 退出函数 } // -------------------------------------------------------- // 3. 构建缴费记录 // 使用 QSqlRecord 创建新记录 // -------------------------------------------------------- QSqlRecord record = tableModel->record(); // 获取一个空记录结构(包含所有字段,但没有数据) // 用于构建要插入的新记录 record.setValue("ownername", ownerName); // 设置 "ownername" 字段的值为业主姓名 record.setValue("type", strType); // 设置 "type" 字段的值为缴费类型 record.setValue("price", strValue); // 设置 "price" 字段的值为缴费金额 QDateTime time = QDateTime::currentDateTime(); // 获取当前系统时间 QString strTime = time.toString("yyyy-MM-dd hh:mm:ss"); // 将时间格式化为字符串 record.setValue("time", strTime); // 设置 "time" 字段的值为当前时间 // -------------------------------------------------------- // 4. 插入记录到数据库 // insertRecord(-1) 表示在末尾追加 // -------------------------------------------------------- if (!tableModel->insertRecord(-1, record)) { // 插入记录到模型末尾,如果失败则进入 if QMessageBox::critical(this, tr("错误"), tr("插入记录失败:") + tableModel->lastError().text()); // 弹出错误对话框,显示具体错误信息 delete tableModel; // 释放模型对象 return; // 退出函数 } // -------------------------------------------------------- // 5. 提交数据到数据库 // -------------------------------------------------------- bool submitSuccess = tableModel->submitAll(); // 提交所有待处理的修改到数据库 // 返回 true 表示提交成功,false 表示提交失败 if (submitSuccess) { // 提交成功 bool updateSuccess = updateState(ui->comboBox->currentIndex()); // 调用 updateState() 更新缴费状态 // 参数:当前选中的缴费类型索引(0: 车位费, 1: 物业费) if (updateSuccess) { // 状态更新成功 QMessageBox::information(this, tr("提示"), tr("缴费成功!")); // 弹出提示框告知用户缴费成功 ui->lineEdit->clear(); // 清空金额输入框,方便下一次输入 qDebug() << "缴费成功:" << ownerName << strType << strValue << strTime; // 输出调试信息,记录缴费详情 } else { // 状态更新失败 tableModel->revertAll(); // 回滚数据(撤销插入操作) QMessageBox::warning(this, tr("提示"), tr("缴费记录已保存,但状态更新失败,请检查!")); // 弹出警告框提示用户 } } else { // 提交失败 tableModel->revertAll(); // 回滚数据(撤销插入操作) QMessageBox::critical(this, tr("错误"), tr("保存失败:") + tableModel->lastError().text()); // 弹出错误对话框,显示具体错误信息 } delete tableModel; // 释放模型对象 } // ============================================================ // "返回"按钮槽函数 - 关闭当前窗口 // 当用户点击"返回"按钮时被调用 // ============================================================ void ownerPaySelf::on_pushButton_2_clicked() { this->close(); // close() 关闭当前缴费窗口 // 窗口关闭后,返回到业主主界面 } // ============================================================ // 更新缴费状态 // 参数:nType - 0:车位费 1:物业费 // 返回:true-更新成功 false-更新失败 // 缴费成功后调用,更新对应表的状态 // ============================================================ bool ownerPaySelf::updateState(int nType) { // -------------------------------------------------------- // 1. 获取当前业主姓名 // -------------------------------------------------------- QString ownerName = ui->lineEdit_2->text().trimmed(); // 从输入框获取业主姓名,去除首尾空格 if (ownerName.isEmpty()) { // 如果业主姓名为空 qDebug() << "更新状态失败:业主姓名为空"; // 输出调试信息 return false; // 返回 false 表示更新失败 } // -------------------------------------------------------- // 2. 根据缴费类型执行不同的更新逻辑 // -------------------------------------------------------- if (0 == nType) { // ========== 车位费缴费 ========== // 更新 carstation 表的 paystate 字段 QSqlQuery query; // 创建 SQL 查询对象 query.prepare("UPDATE carstation SET paystate = '已缴费' WHERE ownername = :ownerName"); // 准备 SQL 更新语句 // :ownerName 是命名占位符,后续用 bindValue() 绑定 // 使用参数绑定防止 SQL 注入攻击 query.bindValue(":ownerName", ownerName); // 将业主姓名绑定到占位符 if (!query.exec()) { // 执行更新,如果失败则进入 if qDebug() << "更新车位状态失败:" << query.lastError().text(); // 输出错误信息到控制台 QMessageBox::critical(this, tr("错误"), tr("更新车位状态失败:") + query.lastError().text()); // 弹出错误对话框 return false; // 返回 false 表示更新失败 } if (query.numRowsAffected() == 0) { // numRowsAffected() 返回受影响的行数 // 如果为 0,说明没有匹配到任何记录 qDebug() << "未找到对应的车位记录:" << ownerName; // 输出调试信息 QMessageBox::warning(this, tr("提示"), tr("未找到业主 '%1' 的车位记录!").arg(ownerName)); // 弹出警告框,提示未找到车位记录 return false; // 返回 false 表示更新失败 } qDebug() << "车位缴费状态更新成功,业主:" << ownerName; // 输出调试信息 return true; // 返回 true 表示更新成功 } else { // ========== 物业费缴费 ========== // 物业费缴费功能待实现 qDebug() << "物业费缴费功能待实现"; // 输出调试信息 return false; // 返回 false 表示更新失败 } } // ============================================================ // 【扩展功能】获取当前业主的欠费信息 // 参数:ownerName - 业主姓名 // 返回值:欠费总金额 // 查询数据库中该业主所有未缴费的记录,汇总金额 // ============================================================ double ownerPaySelf::getOwnerArrears(const QString &ownerName) { QSqlQuery query; // 创建 SQL 查询对象 query.prepare("SELECT SUM(price) FROM priceRecord WHERE ownername = :ownerName AND status = '未缴费'"); // 准备 SQL 查询语句 // SUM(price) 计算所有未缴费记录的总金额 // status = '未缴费' 只查询未缴费的记录 query.bindValue(":ownerName", ownerName); // 将业主姓名绑定到占位符 if (query.exec() && query.next()) { // 执行查询,如果成功且有结果 return query.value(0).toDouble(); // 返回第一行第一列的值(总金额) } return 0.0; // 查询失败或没有记录,返回 0 } // ============================================================ // 【扩展功能】检查是否已缴费(防止重复缴费) // 参数:ownerName - 业主姓名,type - 缴费类型 // 返回值:true-已缴费,false-未缴费 // 用于防止业主对同一项目重复缴费 // ============================================================ bool ownerPaySelf::hasPaid(const QString &ownerName, const QString &type) { QSqlQuery query; // 创建 SQL 查询对象 query.prepare("SELECT COUNT(*) FROM priceRecord WHERE ownername = :ownerName AND type = :type AND time >= date('now', 'start of month')"); // 准备 SQL 查询语句 // COUNT(*) 统计符合条件的记录数量 // time >= date('now', 'start of month') 查询当月开始的记录 // 即只检查本月是否已缴费 query.bindValue(":ownerName", ownerName); // 将业主姓名绑定到占位符 query.bindValue(":type", type); // 将缴费类型绑定到占位符 if (query.exec() && query.next()) { // 执行查询,如果成功且有结果 return query.value(0).toInt() > 0; // 如果数量大于 0,说明已缴费 } return false; // 查询失败或没有记录,返回 false(未缴费) }4.ownerpayself.ui
5.paymanage.h
原始版本一
cpp#ifndef PAYMANAGE_H #define PAYMANAGE_H #include <QWidget> #include <QSqlTableModel> #include <QButtonGroup> #include <QMessageBox> #include <QSqlError> namespace Ui { class PayManage; } //缴费管理类,公有继承QWidgets //使用UI设计师设计界面 class PayManage : public QWidget { Q_OBJECT public: explicit PayManage(QWidget *parent = 0); ~PayManage(); private slots: void on_squreBtn_clicked(); //"查询"按钮槽函数 void on_payConfirmBtn_clicked();//"确认支付"按钮槽函数 void on_pushButton_clicked(); //"缴费"按钮槽函数 private: Ui::PayManage *ui; QSqlTableModel *payModel; //创建SQL表格模型指针 QButtonGroup *payStatusGroup;//单选按键组 }; #endif // PAYMANAGE_H修复版本二
无注释版
cpp#ifndef PAYMANAGE_H #define PAYMANAGE_H #include <QWidget> #include <QSqlTableModel> #include <QButtonGroup> #include <QMessageBox> #include <QSqlError> namespace Ui { class PayManage; } class PayManage : public QWidget { Q_OBJECT public: explicit PayManage(QWidget *parent = 0); ~PayManage(); private slots: void on_squreBtn_clicked(); void on_payConfirmBtn_clicked(); void on_pushButton_clicked(); private: Ui::PayManage *ui; QSqlTableModel *payModel; QButtonGroup *payStatusGroup; }; #endif // PAYMANAGE_H有注释版
cpp// ============================================================ // 文件:paymanage.h // 功能:缴费管理界面的头文件声明 // 说明:管理员在此进行收费管理、查询缴费记录、确认支付等操作 // ============================================================ #ifndef PAYMANAGE_H // 作用:防止头文件被多次包含(Include Guard) // 如果 PAYMANAGE_H 未定义,则定义它并包含头文件内容 // 如果已定义,则跳过整个头文件内容 #define PAYMANAGE_H // 定义宏 PAYMANAGE_H,标记这个头文件已经被包含 // ============================================================ // 头文件包含 // ============================================================ #include <QWidget> // 包含 QWidget 基类 // QWidget 是所有 Qt 窗口控件的基类 // 本类继承 QWidget,作为一个独立的窗口部件 #include <QSqlTableModel> // 包含 QSqlTableModel 类 // 用于与数据库表交互,支持增删改查操作 // 本类用于操作缴费相关的数据表(如 priceRecord) #include <QButtonGroup> // 包含 QButtonGroup 类 // 用于管理一组按钮,实现单选互斥效果 // 本类用于管理缴费状态的单选按钮(已缴费/未缴费) #include <QMessageBox> // 包含 QMessageBox 类 // 用于显示提示、警告、错误等消息框 #include <QSqlError> // 包含 QSqlError 类 // 用于获取数据库操作失败时的错误信息 // ============================================================ // UI 命名空间声明 // ============================================================ namespace Ui { class PayManage; // 声明 UI 类 // 这个类由 Qt 的 uic 工具根据 paymanage.ui 文件自动生成 // 包含了界面上所有控件的指针 } // ============================================================ // PayManage 类定义 // 缴费管理窗口,继承自 QWidget // 管理员在此进行缴费管理操作 // ============================================================ class PayManage : public QWidget // class PayManage : 定义一个名为 PayManage 的类 // public QWidget : 公有继承自 QWidget 基类 // 作为独立的窗口部件,可以嵌入到其他窗口或单独显示 { Q_OBJECT // Qt 元对象宏 // 启用信号槽机制、运行时类型信息等 Qt 元对象功能 // 因为类中使用了 private slots,必须包含此宏 public: // ============================================================ // public 区域:对外公开的接口 // ============================================================ explicit PayManage(QWidget *parent = 0); // 构造函数 // explicit: 防止隐式类型转换 // QWidget *parent = 0: 父窗口指针,默认值为 nullptr ~PayManage(); // 析构函数 // 当对象被销毁时自动调用,释放资源 private slots: // ============================================================ // 私有槽函数区域 // 响应按钮点击事件 // ============================================================ void on_squreBtn_clicked(); // "查询"按钮的槽函数 // 当用户点击"查询"时被调用 // 功能:根据筛选条件查询缴费记录 // 可能按业主姓名、缴费状态、时间范围等条件查询 void on_payConfirmBtn_clicked(); // "确认支付"按钮的槽函数 // 当用户点击"确认支付"时被调用 // 功能:确认选中记录的支付状态 // 将选中的未缴费记录标记为已缴费 void on_pushButton_clicked(); // "缴费"按钮的槽函数 // 当用户点击"缴费"时被调用 // 功能:执行缴费操作 // 可能用于手动录入缴费记录 private: // ============================================================ // private 区域:私有的成员变量 // 只能在类内部访问,外部不可见 // ============================================================ Ui::PayManage *ui; // UI 对象指针 // 指向由 uic 工具生成的 UI 类对象 // 通过这个指针可以访问界面上所有的控件 // 例如:ui->tableView(缴费记录表格) // ui->comboBox(搜索条件下拉框) // ui->lineEdit(搜索关键字输入框) // ui->squreBtn(查询按钮) // ui->payConfirmBtn(确认支付按钮) // ui->pushButton(缴费按钮) QSqlTableModel *payModel; // SQL 表格模型对象指针 // 用于与缴费记录表(如 priceRecord)交互 // 提供数据的查询、显示、更新等功能 // 通过 setTable() 指定表名 // 通过 setFilter() 设置筛选条件 // 通过 select() 执行查询 QButtonGroup *payStatusGroup; // 缴费状态按钮组 // 管理多个单选按钮,实现互斥选择 // 例如:全部 / 已缴费 / 未缴费 // 用于筛选不同状态的缴费记录 }; #endif // PAYMANAGE_H // 结束条件编译块 // 如果头文件被重复包含,从 #ifndef 到 #endif 之间的内容会被跳过5.paymanage.cpp
原始版本一
cpp#include "paymanage.h" #include "ui_paymanage.h" #include "ownerpayself.h" /*********PayManage缴费管理类构造函数********************************************************/ PayManage::PayManage(QWidget *parent) : QWidget(parent), ui(new Ui::PayManage) { ui->setupUi(this); payModel = new QSqlTableModel(this); payModel->setEditStrategy(QSqlTableModel::OnManualSubmit); payModel->setTable("priceRecord"); //创建数据库连接表"priceRecord" payModel->select(); payModel->setHeaderData(0,Qt::Horizontal,tr("缴费人")); //设置显示字段 payModel->setHeaderData(1,Qt::Horizontal,tr("缴费类型")); payModel->setHeaderData(2,Qt::Horizontal,tr("缴费金额")); payModel->setHeaderData(3,Qt::Horizontal,tr("缴费时间")); ui->payTableView->setModel(payModel); //送入表格显示 payStatusGroup=new QButtonGroup(this); //创建单选按键组 payStatusGroup->addButton(ui->payedRadioButton,0);//添加单选案件 payStatusGroup->addButton(ui->payRadioButton,1); ui->payRadioButton->setChecked(true); //设置"物业费"按键默认选中 } /*********PayManage缴费管理类析构函数********************************************************/ PayManage::~PayManage() { delete ui; } /*********《槽函数》"查询"按键槽函数********************************************************/ void PayManage::on_squreBtn_clicked() { if(ui->ownerNameLineEdit->text().isEmpty()) //判断"业主姓名"是否为空,为空进入 { if(payStatusGroup->checkedId()== 0) //"车位租金"按键被选中,显示所有车位租金相关数据 { payModel->setFilter("type='车位租金'"); //筛选数据 } else { payModel->setFilter("type='物业费'"); } } else //判断"业主姓名"不为空 { if(payStatusGroup->checkedId()==0) //"车位租金"按键被选中 { payModel->setFilter(QString("ownername= '%1'and type='车位租金'") .arg(ui->ownerNameLineEdit->text())); } else { payModel->setFilter(QString("ownername= '%1'andtype='物业费'") .arg(ui->ownerNameLineEdit->text())); } } payModel->select(); //数据查询 ui->payTableView->setModel(payModel); //窗口显示 } /*********《槽函数》"确认支付"按键槽函数********************************************************/ void PayManage::on_payConfirmBtn_clicked() { payModel->database().transaction(); //判断并启动事件 if(payModel->submitAll()) //提交缓存 { payModel->database().commit();//提交数据库 } else { payModel->database().rollback();//提交失败则回滚 QMessageBox::warning(this,tr("tabalModel"), tr("数据库错误:% 1").arg(payModel->lastError().text())); } } /*********《槽函数》"缴费"按键槽函数********************************************************/ void PayManage::on_pushButton_clicked() { ownerPaySelf *p = new ownerPaySelf; //创建缴费川口对象 p->show(); //显示窗口 }修复版本二
无注释版
cpp#include "paymanage.h" #include "ui_paymanage.h" #include "ownerpayself.h" #include <QSqlError> #include <QDebug> PayManage::PayManage(QWidget *parent) : QWidget(parent), ui(new Ui::PayManage) { ui->setupUi(this); payModel = new QSqlTableModel(this); payModel->setEditStrategy(QSqlTableModel::OnManualSubmit); payModel->setTable("priceRecord"); payModel->select(); payModel->setHeaderData(0, Qt::Horizontal, tr("缴费人")); payModel->setHeaderData(1, Qt::Horizontal, tr("缴费类型")); payModel->setHeaderData(2, Qt::Horizontal, tr("缴费金额")); payModel->setHeaderData(3, Qt::Horizontal, tr("缴费时间")); ui->payTableView->setModel(payModel); payStatusGroup = new QButtonGroup(this); payStatusGroup->addButton(ui->payedRadioButton, 0); payStatusGroup->addButton(ui->payRadioButton, 1); ui->payRadioButton->setChecked(true); } PayManage::~PayManage() { delete ui; } void PayManage::on_squreBtn_clicked() { QString ownerName = ui->ownerNameLineEdit->text().trimmed(); int typeId = payStatusGroup->checkedId(); QString typeName = (typeId == 0) ? "车位租金" : "物业费"; QString filter; if (ownerName.isEmpty()) { filter = QString("type = '%1'").arg(typeName); } else { QString safeName = ownerName; safeName.replace("'", "''"); filter = QString("ownername = '%1' AND type = '%2'") .arg(safeName).arg(typeName); } payModel->setFilter(filter); payModel->select(); qDebug() << "查询条件:" << filter; } void PayManage::on_payConfirmBtn_clicked() { if (!payModel->isDirty()) { QMessageBox::information(this, tr("提示"), tr("没有需要保存的修改!")); return; } int ret = QMessageBox::question(this, tr("确认支付"), tr("确定要确认所有选中的缴费记录吗?"), QMessageBox::Yes | QMessageBox::No); if (ret != QMessageBox::Yes) { return; } payModel->database().transaction(); if (payModel->submitAll()) { payModel->database().commit(); QMessageBox::information(this, tr("提示"), tr("确认支付成功!")); qDebug() << "确认支付成功,提交了所有修改"; } else { payModel->database().rollback(); QString errorMsg = payModel->lastError().text(); QMessageBox::critical(this, tr("错误"), tr("确认支付失败:") + errorMsg); qDebug() << "确认支付失败:" << errorMsg; } } void PayManage::on_pushButton_clicked() { ownerPaySelf *p = new ownerPaySelf(this); p->show(); }有注释版
cpp// ============================================================ // 文件:paymanage.cpp // 功能:缴费管理界面的实现 // 说明:管理员在此进行缴费记录的查询和确认支付 // ============================================================ #include "paymanage.h" // 包含自己的头文件声明 // 让编译器知道类 PayManage 的结构、成员函数和成员变量 #include "ui_paymanage.h" // 包含由 .ui 文件生成的 UI 类头文件 // 包含了 Ui::PayManage 类的定义,其中有所有控件的指针 #include "ownerpayself.h" // 包含自助缴费模块的头文件 // 用于创建业主自助缴费窗口 #include <QSqlError> // 包含 SQL 错误类 // 用于获取数据库操作失败时的错误信息 #include <QDebug> // 包含调试输出类 // 用于在控制台打印调试信息 // ============================================================ // 构造函数 - 初始化缴费管理界面 // 参数:parent - 父窗口指针,默认 nullptr // 当管理员点击"缴费管理"时,此对象被创建 // ============================================================ PayManage::PayManage(QWidget *parent) : QWidget(parent), // 调用父类 QWidget 的构造函数,传入父窗口指针 ui(new Ui::PayManage) // 创建 UI 对象(由 Qt Designer 生成的界面类) { ui->setupUi(this); // setupUi() 加载 .ui 文件,创建所有控件并设置布局 // -------------------------------------------------------- // 1. 创建数据模型 // -------------------------------------------------------- payModel = new QSqlTableModel(this); // 创建 SQL 表格模型,设置父对象为 this(自动内存管理) // 用于与缴费记录表交互 payModel->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略为"手动提交" // 修改后需要调用 submitAll() 才会保存到数据库 // 优点:可以批量修改,确认后再提交 payModel->setTable("priceRecord"); // 设置要操作的数据表为 "priceRecord"(缴费记录表) payModel->select(); // 执行查询,从数据库加载所有缴费记录 // -------------------------------------------------------- // 2. 设置表头显示名称(用户看到的列名) // -------------------------------------------------------- payModel->setHeaderData(0, Qt::Horizontal, tr("缴费人")); // 第0列显示为"缴费人" payModel->setHeaderData(1, Qt::Horizontal, tr("缴费类型")); // 第1列显示为"缴费类型" payModel->setHeaderData(2, Qt::Horizontal, tr("缴费金额")); // 第2列显示为"缴费金额" payModel->setHeaderData(3, Qt::Horizontal, tr("缴费时间")); // 第3列显示为"缴费时间" ui->payTableView->setModel(payModel); // 将数据模型设置到表格视图 // 表格现在显示所有缴费记录 // -------------------------------------------------------- // 3. 创建缴费状态按钮组 // -------------------------------------------------------- payStatusGroup = new QButtonGroup(this); // 创建按钮组,父对象为 this(自动内存管理) // 用于实现单选互斥 payStatusGroup->addButton(ui->payedRadioButton, 0); // 将"车位租金"单选按钮加入组,ID 为 0 payStatusGroup->addButton(ui->payRadioButton, 1); // 将"物业费"单选按钮加入组,ID 为 1 ui->payRadioButton->setChecked(true); // 默认选中"物业费"单选按钮 // 用户打开窗口时,默认显示物业费缴费记录 } // ============================================================ // 析构函数 - 释放资源 // 当窗口关闭时自动调用 // ============================================================ PayManage::~PayManage() { delete ui; // 删除 UI 对象,释放界面上所有控件的内存 // 这是必须的,因为 ui 是在构造函数中用 new 创建的 // payModel 不需要手动 delete,因为设置了父对象 this } // ============================================================ // "查询"按钮槽函数 - 改进版 // 当用户点击"查询"按钮时被调用 // 功能:根据业主姓名和缴费类型筛选缴费记录 // 改进:使用参数绑定防止 SQL 注入,优化代码结构 // ============================================================ void PayManage::on_squreBtn_clicked() { // -------------------------------------------------------- // 1. 获取用户输入 // -------------------------------------------------------- QString ownerName = ui->ownerNameLineEdit->text().trimmed(); // 获取业主姓名输入框的文本,去除首尾空格 int typeId = payStatusGroup->checkedId(); // 获取当前选中的缴费类型 ID // 0: 车位租金, 1: 物业费 QString typeName = (typeId == 0) ? "车位租金" : "物业费"; // 根据 ID 获取对应的类型名称字符串 // -------------------------------------------------------- // 2. 构建安全的过滤条件(防止 SQL 注入) // -------------------------------------------------------- QString filter; // 声明过滤条件字符串 if (ownerName.isEmpty()) { // 如果业主姓名为空,只按类型筛选 filter = QString("type = '%1'").arg(typeName); // 筛选条件:缴费类型 = 选中的类型 // ⚠️ typeName 是固定值("车位租金"或"物业费"),安全 } else { // 如果业主姓名不为空,按姓名和类型筛选 // 转义单引号防止 SQL 注入 QString safeName = ownerName; safeName.replace("'", "''"); // 将单引号替换为两个单引号(SQLite 转义方式) filter = QString("ownername = '%1' AND type = '%2'") .arg(safeName).arg(typeName); // 筛选条件:业主姓名 = 输入值 AND 缴费类型 = 选中的类型 // ✅ 使用转义后的名称,防止 SQL 注入 } // -------------------------------------------------------- // 3. 执行查询并刷新显示 // -------------------------------------------------------- payModel->setFilter(filter); // 设置过滤条件 payModel->select(); // 执行查询,从数据库获取筛选后的数据 // payModel 中的数据已经更新,表格会自动刷新 // 不需要再次调用 ui->payTableView->setModel(payModel) qDebug() << "查询条件:" << filter; // 输出调试信息,记录查询条件 } // ============================================================ // "确认支付"按钮槽函数 - 改进版 // 当用户点击"确认支付"按钮时被调用 // 功能:确认当前显示的缴费记录,提交到数据库 // 改进:增加错误处理和用户反馈 // ============================================================ void PayManage::on_payConfirmBtn_clicked() { // -------------------------------------------------------- // 1. 检查是否有待提交的修改 // -------------------------------------------------------- if (!payModel->isDirty()) { // isDirty() 返回 true 表示有未保存的修改 // 如果没有修改,直接返回 QMessageBox::information(this, tr("提示"), tr("没有需要保存的修改!")); // 弹出提示框告知用户 return; // 退出函数 } // -------------------------------------------------------- // 2. 确认提交 // -------------------------------------------------------- int ret = QMessageBox::question(this, tr("确认支付"), tr("确定要确认所有选中的缴费记录吗?"), QMessageBox::Yes | QMessageBox::No); // 弹出询问对话框,让用户确认是否提交 // 返回用户点击的按钮(Yes 或 No) if (ret != QMessageBox::Yes) { // 如果用户点击"否",取消操作 return; // 退出函数 } // -------------------------------------------------------- // 3. 使用事务确保数据一致性 // -------------------------------------------------------- payModel->database().transaction(); // 开始数据库事务 // 事务保证:要么全部成功,要么全部失败 // 防止数据不一致 if (payModel->submitAll()) { // submitAll() 提交所有待处理的修改到数据库 // 返回 true 表示提交成功 payModel->database().commit(); // 提交事务,确认修改 // 修改永久保存到数据库 QMessageBox::information(this, tr("提示"), tr("确认支付成功!")); // 弹出提示框告知用户操作成功 qDebug() << "确认支付成功,提交了所有修改"; // 输出调试信息 } else { // 提交失败 payModel->database().rollback(); // 回滚事务,撤销所有修改 // 数据库恢复到事务开始前的状态 QString errorMsg = payModel->lastError().text(); // 获取错误信息 QMessageBox::critical(this, tr("错误"), tr("确认支付失败:") + errorMsg); // 弹出错误对话框,显示具体错误信息 qDebug() << "确认支付失败:" << errorMsg; // 输出调试信息 } } // ============================================================ // "缴费"按钮槽函数 - 改进版 // 当用户点击"缴费"按钮时被调用 // 功能:打开业主自助缴费窗口 // 改进:设置父对象防止内存泄漏 // ============================================================ void PayManage::on_pushButton_clicked() { ownerPaySelf *p = new ownerPaySelf(this); // 创建自助缴费窗口对象 // ✅ 设置父对象为 this,由 Qt 自动管理内存 // 当 PayManage 窗口关闭时,缴费窗口也会被自动销毁 p->show(); // 显示缴费窗口(非模态) // 用户可以同时在两个窗口间切换操作 }5.paymanage.ui
6.pricemanage.h
原始版本一
cpp#ifndef PRICEMANAGE_H #define PRICEMANAGE_H #include <QWidget> #include <QSqlTableModel> #include <QMessageBox> #include <QSqlRecord> #include <QDebug> namespace Ui { class PriceManage; } //价格维护窗口类,公有继承自QMainWindow类 //使用UI设计师完成设计 class PriceManage : public QWidget { Q_OBJECT public: explicit PriceManage(QWidget *parent = 0); ~PriceManage(); private slots: void on_priceConfirmBtn_clicked(); //"确认"按键槽函数 void on_priceReturnBtn_clicked(); //"返回"按键槽函数 private: Ui::PriceManage *ui; QSqlTableModel *priceModel; //创建SQL表格模型指针 }; #endif // PRICEMANAGE_H修复版本二
无注释版
cpp#ifndef PRICEMANAGE_H #define PRICEMANAGE_H #include <QWidget> #include <QSqlTableModel> #include <QMessageBox> #include <QSqlRecord> #include <QDebug> namespace Ui { class PriceManage; } class PriceManage : public QWidget { Q_OBJECT public: explicit PriceManage(QWidget *parent = 0); ~PriceManage(); private slots: void on_priceConfirmBtn_clicked(); void on_priceReturnBtn_clicked(); private: Ui::PriceManage *ui; QSqlTableModel *priceModel; }; #endif // PRICEMANAGE_H有注释版
cpp// ============================================================ // 文件:pricemanage.h // 功能:价格维护界面的头文件声明 // 说明:管理员在此设置和管理物业费、车位费等收费标准 // ============================================================ #ifndef PRICEMANAGE_H // 作用:防止头文件被多次包含(Include Guard) // 如果 PRICEMANAGE_H 未定义,则定义它并包含头文件内容 // 如果已定义,则跳过整个头文件内容 #define PRICEMANAGE_H // 定义宏 PRICEMANAGE_H,标记这个头文件已经被包含 // ============================================================ // 头文件包含 // ============================================================ #include <QWidget> // 包含 QWidget 基类 // QWidget 是所有 Qt 窗口控件的基类 // 本类继承 QWidget,作为一个独立的窗口部件 #include <QSqlTableModel> // 包含 QSqlTableModel 类 // 用于与数据库表交互,支持增删改查操作 // 本类用于操作价格相关的数据表(如 price 表) #include <QMessageBox> // 包含 QMessageBox 类 // 用于显示提示、警告、错误等消息框 #include <QSqlRecord> // 包含 QSqlRecord 类 // 用于表示数据库中的一条记录(一行数据) // 在添加或修改价格时,用于构建记录 #include <QDebug> // 包含 QDebug 类 // 用于输出调试信息到控制台 // ============================================================ // UI 命名空间声明 // ============================================================ namespace Ui { class PriceManage; // 声明 UI 类 // 这个类由 Qt 的 uic 工具根据 pricemanage.ui 文件自动生成 // 包含了界面上所有控件的指针 } // ============================================================ // PriceManage 类定义 // 价格维护窗口,继承自 QWidget // 管理员在此设置和管理收费标准 // ============================================================ class PriceManage : public QWidget // class PriceManage : 定义一个名为 PriceManage 的类 // public QWidget : 公有继承自 QWidget 基类 // 作为独立的窗口部件,可以嵌入到其他窗口或单独显示 { Q_OBJECT // Qt 元对象宏 // 启用信号槽机制、运行时类型信息等 Qt 元对象功能 // 因为类中使用了 private slots,必须包含此宏 public: // ============================================================ // public 区域:对外公开的接口 // ============================================================ explicit PriceManage(QWidget *parent = 0); // 构造函数 // explicit: 防止隐式类型转换 // QWidget *parent = 0: 父窗口指针,默认值为 nullptr ~PriceManage(); // 析构函数 // 当对象被销毁时自动调用,释放资源 private slots: // ============================================================ // 私有槽函数区域 // 响应按钮点击事件 // ============================================================ void on_priceConfirmBtn_clicked(); // "确认"按钮的槽函数 // 当用户点击"确认"时被调用 // 功能:将当前输入的价格信息保存到数据库 void on_priceReturnBtn_clicked(); // "返回"按钮的槽函数 // 当用户点击"返回"时被调用 // 功能:关闭当前价格管理窗口 private: // ============================================================ // private 区域:私有的成员变量 // 只能在类内部访问,外部不可见 // ============================================================ Ui::PriceManage *ui; // UI 对象指针 // 指向由 uic 工具生成的 UI 类对象 // 通过这个指针可以访问界面上所有的控件 // 例如:ui->typeComboBox(收费类型下拉框) // ui->priceLineEdit(价格输入框) // ui->unitComboBox(单位下拉框) // ui->priceConfirmBtn(确认按钮) // ui->priceReturnBtn(返回按钮) // ui->tableView(价格列表表格) QSqlTableModel *priceModel; // SQL 表格模型对象指针 // 用于与价格表(如 price)交互 // 提供数据的查询、显示、更新等功能 // 通过 setTable() 指定表名 // 通过 select() 执行查询 // 通过 submitAll() 提交修改 }; #endif // PRICEMANAGE_H // 结束条件编译块 // 如果头文件被重复包含,从 #ifndef 到 #endif 之间的内容会被跳过6.pricemanage.cpp
原始版本一
cpp#include "pricemanage.h" #include "ui_pricemanage.h" /*********PriceManage类构造函数***************************************************/ PriceManage::PriceManage(QWidget *parent) : QWidget(parent), ui(new Ui::PriceManage) { ui->setupUi(this); priceModel=new QSqlTableModel(this); //设置model实现与数据库交互 priceModel->setTable("price"); //与数据库"price"表建立连接 priceModel->setEditStrategy(QSqlTableModel::OnManualSubmit); } /*********PriceManage类析构函数***************************************************/ PriceManage::~PriceManage() { delete ui; } /********《槽函数》"确认"按键处理函数*******************************************/ void PriceManage::on_priceConfirmBtn_clicked() { if(ui->pmFreeLineEdit->text().isEmpty()&&ui->carStationFreeLineEdit->text().isEmpty() &&ui->repareFreeLineEdit->text().isEmpty()) { QMessageBox::warning(this,"警告","请填写完整信息",QMessageBox::Yes); return; } priceModel->select(); QSqlRecord record=priceModel->record(); record.setValue("pmfree",ui->pmFreeLineEdit->text()); record.setValue("carstationfree",ui->carStationFreeLineEdit->text()); record.setValue("reparifree",ui->repareFreeLineEdit->text()); priceModel->insertRecord(-1,record); if(priceModel->submitAll()) { QMessageBox::information(this,"提示","价格信息修改成功",QMessageBox::Yes); ui->carStationFreeLineEdit->clear(); ui->pmFreeLineEdit->clear(); ui->repareFreeLineEdit->clear(); } else { QMessageBox::information(this,"提示","价格信息修改失败,请重新输入",QMessageBox::Yes); } } /********《槽函数》"返回"按键处理函数*******************************************/ void PriceManage::on_priceReturnBtn_clicked() { this->hide(); }修复版本二
无注释版
cpp#include "pricemanage.h" #include "ui_pricemanage.h" PriceManage::PriceManage(QWidget *parent) : QWidget(parent), ui(new Ui::PriceManage) { ui->setupUi(this); priceModel = new QSqlTableModel(this); priceModel->setTable("price"); priceModel->setEditStrategy(QSqlTableModel::OnManualSubmit); } PriceManage::~PriceManage() { delete ui; } void PriceManage::on_priceConfirmBtn_clicked() { if (ui->pmFreeLineEdit->text().isEmpty() && ui->carStationFreeLineEdit->text().isEmpty() && ui->repareFreeLineEdit->text().isEmpty()) { QMessageBox::warning(this, "警告", "请填写完整信息", QMessageBox::Yes); return; } priceModel->select(); QSqlRecord record = priceModel->record(); record.setValue("pmfree", ui->pmFreeLineEdit->text()); record.setValue("carstationfree", ui->carStationFreeLineEdit->text()); record.setValue("reparifree", ui->repareFreeLineEdit->text()); priceModel->insertRecord(-1, record); if (priceModel->submitAll()) { QMessageBox::information(this, "提示", "价格信息修改成功", QMessageBox::Yes); ui->carStationFreeLineEdit->clear(); ui->pmFreeLineEdit->clear(); ui->repareFreeLineEdit->clear(); } else { QMessageBox::information(this, "提示", "价格信息修改失败,请重新输入", QMessageBox::Yes); } } void PriceManage::on_priceReturnBtn_clicked() { this->hide(); }有注释版
cpp// ============================================================ // 文件:pricemanage.cpp // 功能:价格维护界面的实现 // 说明:管理员在此设置物业费、车位费、维修费等收费标准 // ============================================================ #include "pricemanage.h" // 包含自己的头文件声明 // 让编译器知道类 PriceManage 的结构、成员函数和成员变量 #include "ui_pricemanage.h" // 包含由 .ui 文件生成的 UI 类头文件 // 包含了 Ui::PriceManage 类的定义,其中有所有控件的指针 // ============================================================ // 构造函数 - 初始化价格管理界面 // 参数:parent - 父窗口指针,默认 nullptr // 当管理员点击"价格管理"时,此对象被创建 // ============================================================ PriceManage::PriceManage(QWidget *parent) : QWidget(parent), // 调用父类 QWidget 的构造函数,传入父窗口指针 ui(new Ui::PriceManage) // 创建 UI 对象(由 Qt Designer 生成的界面类) { ui->setupUi(this); // setupUi() 加载 .ui 文件,创建所有控件并设置布局 // -------------------------------------------------------- // 创建数据模型 // -------------------------------------------------------- priceModel = new QSqlTableModel(this); // 创建 SQL 表格模型,设置父对象为 this(自动内存管理) // 用于与价格表交互 priceModel->setTable("price"); // 设置要操作的数据表为 "price"(价格表) // 该表存储各项收费标准 priceModel->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略为"手动提交" // 修改后需要调用 submitAll() 才会保存到数据库 // 优点:可以批量修改,确认后再提交 } // ============================================================ // 析构函数 - 释放资源 // 当窗口关闭时自动调用 // ============================================================ PriceManage::~PriceManage() { delete ui; // 删除 UI 对象,释放界面上所有控件的内存 // 这是必须的,因为 ui 是在构造函数中用 new 创建的 // priceModel 不需要手动 delete,因为设置了父对象 this } // ============================================================ // "确认"按钮槽函数 // 当用户点击"确认"按钮时被调用 // 功能:将输入的价格信息保存到数据库 // ============================================================ void PriceManage::on_priceConfirmBtn_clicked() { // -------------------------------------------------------- // 1. 验证输入是否完整 // -------------------------------------------------------- if (ui->pmFreeLineEdit->text().isEmpty() && ui->carStationFreeLineEdit->text().isEmpty() && ui->repareFreeLineEdit->text().isEmpty()) { // 检查三个价格输入框是否都为空 // ⚠️ 问题:逻辑错误!要求三个都为空才提示,应该是"任何一个为空"就提示 // 当前逻辑:只有三个都为空时才提示,如果只填了一个或两个,不会提示 QMessageBox::warning(this, "警告", "请填写完整信息", QMessageBox::Yes); // 弹出警告框提示用户 return; // 退出函数 } // -------------------------------------------------------- // 2. 查询数据库,准备插入新记录 // -------------------------------------------------------- priceModel->select(); // 执行查询,从数据库加载所有价格记录 // -------------------------------------------------------- // 3. 构建价格记录 // -------------------------------------------------------- QSqlRecord record = priceModel->record(); // 获取一个空记录结构(包含所有字段,但没有数据) record.setValue("pmfree", ui->pmFreeLineEdit->text()); // 设置 "pmfree" 字段(物业费价格) // ⚠️ 问题:字段名 "pmfree" 可能是 "property management fee" 的缩写 // 但命名不够清晰,可读性差 record.setValue("carstationfree", ui->carStationFreeLineEdit->text()); // 设置 "carstationfree" 字段(车位费价格) record.setValue("reparifree", ui->repareFreeLineEdit->text()); // 设置 "reparifree" 字段(维修费价格) // ⚠️ 问题:字段名拼写错误,"reparifree" 应该是 "repairfree" // -------------------------------------------------------- // 4. 插入记录到数据库 // -------------------------------------------------------- priceModel->insertRecord(-1, record); // 插入记录到模型末尾(-1 表示追加到最后) if (priceModel->submitAll()) { // submitAll() 提交所有待处理的修改到数据库 // 返回 true 表示提交成功 QMessageBox::information(this, "提示", "价格信息修改成功", QMessageBox::Yes); // 弹出提示框告知用户操作成功 // 清空所有输入框 ui->carStationFreeLineEdit->clear(); // 清空车位费输入框 ui->pmFreeLineEdit->clear(); // 清空物业费输入框 ui->repareFreeLineEdit->clear(); // 清空维修费输入框 } else { // 提交失败 QMessageBox::information(this, "提示", "价格信息修改失败,请重新输入", QMessageBox::Yes); // 弹出提示框告知用户操作失败 // ⚠️ 问题:应该用 critical() 而不是 information() // 且没有显示具体错误信息 } } // ============================================================ // "返回"按钮槽函数 // 当用户点击"返回"按钮时被调用 // 功能:关闭当前价格管理窗口 // ============================================================ void PriceManage::on_priceReturnBtn_clicked() { this->hide(); // hide() 隐藏当前窗口 // 与 close() 的区别: // hide():隐藏窗口,对象仍然存在,可以再次显示 // close():关闭窗口,可能销毁对象 }6.pricemanage.ui
7.setowner.h
原始版本一
cpp#ifndef SETOWNER_H #define SETOWNER_H #include <QWidget> #include <QSqlTableModel> namespace Ui { class SetOwner; } class SetOwner : public QWidget { Q_OBJECT public: explicit SetOwner(QWidget *parent = 0); ~SetOwner(); private: Ui::SetOwner *ui; QSqlTableModel *showOwnerTalbe; }; #endif // SETOWNER_H修复版本二
无注释版
cpp#ifndef SETOWNER_H #define SETOWNER_H #include <QWidget> #include <QSqlTableModel> namespace Ui { class SetOwner; } class SetOwner : public QWidget { Q_OBJECT public: explicit SetOwner(QWidget *parent = 0); ~SetOwner(); private: Ui::SetOwner *ui; QSqlTableModel *showOwnerTalbe; }; #endif // SETOWNER_H有注释版
cpp// ============================================================ // 文件:setowner.h // 功能:设置业主界面的头文件声明 // 说明:管理员在此为业主分配房屋、设置业主信息等 // ============================================================ #ifndef SETOWNER_H // 作用:防止头文件被多次包含(Include Guard) // 如果 SETOWNER_H 未定义,则定义它并包含头文件内容 // 如果已定义,则跳过整个头文件内容 #define SETOWNER_H // 定义宏 SETOWNER_H,标记这个头文件已经被包含 // ============================================================ // 头文件包含 // ============================================================ #include <QWidget> // 包含 QWidget 基类 // QWidget 是所有 Qt 窗口控件的基类 // 本类继承 QWidget,作为一个独立的窗口部件 #include <QSqlTableModel> // 包含 QSqlTableModel 类 // 用于与数据库表交互,支持增删改查操作 // 本类用于显示业主列表或房屋信息等 // ============================================================ // UI 命名空间声明 // ============================================================ namespace Ui { class SetOwner; // 声明 UI 类 // 这个类由 Qt 的 uic 工具根据 setowner.ui 文件自动生成 // 包含了界面上所有控件的指针 } // ============================================================ // SetOwner 类定义 // 设置业主窗口,继承自 QWidget // 管理员在此为业主分配房屋、设置相关信息 // ============================================================ class SetOwner : public QWidget // class SetOwner : 定义一个名为 SetOwner 的类 // public QWidget : 公有继承自 QWidget 基类 // 作为独立的窗口部件,可以嵌入到其他窗口或单独显示 { Q_OBJECT // Qt 元对象宏 // 启用信号槽机制、运行时类型信息等 Qt 元对象功能 // 虽然当前没有使用信号槽,但这是一个良好习惯 public: // ============================================================ // public 区域:对外公开的接口 // ============================================================ explicit SetOwner(QWidget *parent = 0); // 构造函数 // explicit: 防止隐式类型转换 // QWidget *parent = 0: 父窗口指针,默认值为 nullptr ~SetOwner(); // 析构函数 // 当对象被销毁时自动调用,释放资源 private: // ============================================================ // private 区域:私有的成员变量 // 只能在类内部访问,外部不可见 // ============================================================ Ui::SetOwner *ui; // UI 对象指针 // 指向由 uic 工具生成的 UI 类对象 // 通过这个指针可以访问界面上所有的控件 QSqlTableModel *showOwnerTalbe; // SQL 表格模型对象指针 // 用于显示业主或房屋相关数据 // ⚠️ 注意:变量名拼写错误 "Talbe" 应该是 "Table" // 用于与数据库表交互,显示数据到 QTableView }; #endif // SETOWNER_H // 结束条件编译块 // 如果头文件被重复包含,从 #ifndef 到 #endif 之间的内容会被跳过7.setowner.cpp
原始版本一
cpp#include "setowner.h" #include "ui_setowner.h" SetOwner::SetOwner(QWidget *parent) : QWidget(parent), ui(new Ui::SetOwner) { ui->setupUi(this); showOwnerTalbe = new QSqlTableModel(this); showOwnerTalbe->setEditStrategy(QSqlTableModel::OnManualSubmit); showOwnerTalbe->setTable("houseowner"); showOwnerTalbe->select(); ui->tableView->setModel(showOwnerTalbe); } SetOwner::~SetOwner() { delete ui; }修复版本二
无注释版
cpp#include "setowner.h" #include "ui_setowner.h" SetOwner::SetOwner(QWidget *parent) : QWidget(parent), ui(new Ui::SetOwner) { ui->setupUi(this); showOwnerTalbe = new QSqlTableModel(this); showOwnerTalbe->setEditStrategy(QSqlTableModel::OnManualSubmit); showOwnerTalbe->setTable("houseowner"); showOwnerTalbe->select(); ui->tableView->setModel(showOwnerTalbe); } SetOwner::~SetOwner() { delete ui; }有注释版
cpp// ============================================================ // 文件:setowner.cpp // 功能:设置业主界面的实现 // 说明:管理员在此查看业主列表,为业主分配房屋等 // ============================================================ #include "setowner.h" // 包含自己的头文件声明 // 让编译器知道类 SetOwner 的结构、成员函数和成员变量 #include "ui_setowner.h" // 包含由 .ui 文件生成的 UI 类头文件 // 包含了 Ui::SetOwner 类的定义,其中有所有控件的指针 // ============================================================ // 构造函数 - 初始化设置业主界面 // 参数:parent - 父窗口指针,默认 nullptr // 当管理员点击"设置业主"时,此对象被创建 // ============================================================ SetOwner::SetOwner(QWidget *parent) : QWidget(parent), // 调用父类 QWidget 的构造函数,传入父窗口指针 ui(new Ui::SetOwner) // 创建 UI 对象(由 Qt Designer 生成的界面类) { ui->setupUi(this); // setupUi() 加载 .ui 文件,创建所有控件并设置布局 // -------------------------------------------------------- // 创建数据模型,显示业主列表 // -------------------------------------------------------- showOwnerTalbe = new QSqlTableModel(this); // 创建 SQL 表格模型,设置父对象为 this(自动内存管理) // ⚠️ 问题:变量名拼写错误 "Talbe" 应该是 "Table" showOwnerTalbe->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略为"手动提交" // 修改后需要调用 submitAll() 才会保存到数据库 showOwnerTalbe->setTable("houseowner"); // 设置要操作的数据表为 "houseowner"(业主表) // 显示所有业主信息 showOwnerTalbe->select(); // 执行查询,从数据库加载所有业主记录 ui->tableView->setModel(showOwnerTalbe); // 将数据模型设置到表格视图 // 表格显示所有业主信息 } // ============================================================ // 析构函数 - 释放资源 // 当窗口关闭时自动调用 // ============================================================ SetOwner::~SetOwner() { delete ui; // 删除 UI 对象,释放界面上所有控件的内存 // 这是必须的,因为 ui 是在构造函数中用 new 创建的 // showOwnerTalbe 不需要手动 delete,因为设置了父对象 this }7.setowner.ui
8.workerfree.h
原始版本一
cpp#ifndef WORKERFREE_H #define WORKERFREE_H #include <QWidget> #include <QSqlQueryModel> #include <QSqlTableModel> #include <QMessageBox> #include <QSqlRecord> #include <QDebug> #include <QDateTime> #include <QString> #include <QButtonGroup> namespace Ui { class WorkerFree; } //员工请假类,公有继承自QWidget //界面由UI设计师完成设计 class WorkerFree : public QWidget { Q_OBJECT public: explicit WorkerFree(QWidget *parent = 0); ~WorkerFree(); private slots: void on_workerFreeBtn_clicked(); //"提交"按钮槽函数 void on_workerFreeReturnBtn_clicked(); //"返回"按钮槽函数 void on_freeRadioButton_clicked(); //"请假"按钮槽函数 void on_attendRadioButton_clicked(); //"出勤"按钮槽函数 private: Ui::WorkerFree *ui; QSqlTableModel *workerFreeModel; //创建SQL表格查询模型 QButtonGroup *freeInfoRadioGroup; //创建组合按键对象指针 bool judgeEmpty(); //判断员工输入是否为空 void clearAll(); //清除员工所有输入内容 }; #endif // WORKERFREE_H修复版本二
无注释版
cpp#ifndef WORKERFREE_H #define WORKERFREE_H #include <QWidget> #include <QSqlQueryModel> #include <QSqlTableModel> #include <QMessageBox> #include <QSqlRecord> #include <QDebug> #include <QDateTime> #include <QString> #include <QButtonGroup> namespace Ui { class WorkerFree; } class WorkerFree : public QWidget { Q_OBJECT public: explicit WorkerFree(QWidget *parent = 0); ~WorkerFree(); private slots: void on_workerFreeBtn_clicked(); void on_workerFreeReturnBtn_clicked(); void on_freeRadioButton_clicked(); void on_attendRadioButton_clicked(); private: Ui::WorkerFree *ui; QSqlTableModel *workerFreeModel; QButtonGroup *freeInfoRadioGroup; bool judgeEmpty(); void clearAll(); }; #endif // WORKERFREE_H有注释版
cpp// ============================================================ // 文件:workerfree.h // 功能:员工请假/考勤管理界面的头文件声明 // 说明:工作人员在此提交请假申请,管理员管理出勤状态 // ============================================================ #ifndef WORKERFREE_H // 作用:防止头文件被多次包含(Include Guard) // 如果 WORKERFREE_H 未定义,则定义它并包含头文件内容 // 如果已定义,则跳过整个头文件内容 #define WORKERFREE_H // 定义宏 WORKERFREE_H,标记这个头文件已经被包含 // ============================================================ // 头文件包含 // ============================================================ #include <QWidget> // 包含 QWidget 基类 // QWidget 是所有 Qt 窗口控件的基类 // 本类继承 QWidget,作为一个独立的窗口部件 #include <QSqlQueryModel> // 包含 QSqlQueryModel 类(只读查询模型) // 用于执行自定义 SQL 查询,显示结果 // 适用于不需要编辑数据的场景 #include <QSqlTableModel> // 包含 QSqlTableModel 类(可读写表格模型) // 用于与数据库表交互,支持增删改查操作 // 本类用于操作员工考勤相关数据表 #include <QMessageBox> // 包含 QMessageBox 类 // 用于显示提示、警告、错误等消息框 #include <QSqlRecord> // 包含 QSqlRecord 类 // 用于表示数据库中的一条记录(一行数据) // 在添加或修改考勤记录时使用 #include <QDebug> // 包含 QDebug 类 // 用于输出调试信息到控制台 #include <QDateTime> // 包含 QDateTime 类 // 用于获取当前时间,记录请假/考勤时间 #include <QString> // 包含 QString 类 // Qt 的字符串类,用于处理文本数据 #include <QButtonGroup> // 包含 QButtonGroup 类 // 用于管理一组按钮,实现单选互斥效果 // 本类用于管理"请假"和"出勤"两个单选按钮 // ============================================================ // UI 命名空间声明 // ============================================================ namespace Ui { class WorkerFree; // 声明 UI 类 // 这个类由 Qt 的 uic 工具根据 workerfree.ui 文件自动生成 // 包含了界面上所有控件的指针 } // ============================================================ // WorkerFree 类定义 // 员工请假/考勤管理窗口,继承自 QWidget // 工作人员提交请假申请,管理员管理出勤状态 // ============================================================ class WorkerFree : public QWidget // class WorkerFree : 定义一个名为 WorkerFree 的类 // public QWidget : 公有继承自 QWidget 基类 // 作为独立的窗口部件,可以嵌入到其他窗口或单独显示 { Q_OBJECT // Qt 元对象宏 // 启用信号槽机制、运行时类型信息等 Qt 元对象功能 // 因为类中使用了 private slots,必须包含此宏 public: // ============================================================ // public 区域:对外公开的接口 // ============================================================ explicit WorkerFree(QWidget *parent = 0); // 构造函数 // explicit: 防止隐式类型转换 // QWidget *parent = 0: 父窗口指针,默认值为 nullptr ~WorkerFree(); // 析构函数 // 当对象被销毁时自动调用,释放资源 private slots: // ============================================================ // 私有槽函数区域 // 响应按钮点击事件 // ============================================================ void on_workerFreeBtn_clicked(); // "提交"按钮的槽函数 // 当用户点击"提交"时被调用 // 功能:提交请假申请或出勤记录到数据库 void on_workerFreeReturnBtn_clicked(); // "返回"按钮的槽函数 // 当用户点击"返回"时被调用 // 功能:关闭当前窗口 void on_freeRadioButton_clicked(); // "请假"按钮的槽函数 // 当用户点击"请假"单选按钮时被调用 // 功能:切换到请假模式,显示请假相关选项 void on_attendRadioButton_clicked(); // "出勤"按钮的槽函数 // 当用户点击"出勤"单选按钮时被调用 // 功能:切换到出勤模式,显示出勤相关选项 private: // ============================================================ // private 区域:私有的成员变量 // 只能在类内部访问,外部不可见 // ============================================================ Ui::WorkerFree *ui; // UI 对象指针 // 指向由 uic 工具生成的 UI 类对象 // 通过这个指针可以访问界面上所有的控件 QSqlTableModel *workerFreeModel; // SQL 表格模型对象指针 // 用于与考勤数据表交互(如 worker_attendance 或 workerfree 表) // 提供数据的查询、显示、插入等功能 QButtonGroup *freeInfoRadioGroup; // 状态按钮组 // 管理"请假"和"出勤"两个单选按钮 // 实现互斥选择,只能选一个 // ============================================================ // 私有辅助函数 // ============================================================ bool judgeEmpty(); // 判断员工输入是否为空 // 返回值:true - 不为空,false - 为空 // 在提交前调用,验证输入完整性 void clearAll(); // 清除员工所有输入内容 // 清空所有输入框,重置界面状态 // 在提交成功或取消时调用 }; #endif // WORKERFREE_H // 结束条件编译块 // 如果头文件被重复包含,从 #ifndef 到 #endif 之间的内容会被跳过8.workerfree.cpp
原始版本一
cpp#include "workerfree.h" #include "ui_workerfree.h" /*********员工请假类WorkerFree构造函数*******************************************************/ WorkerFree::WorkerFree(QWidget *parent) : QWidget(parent), ui(new Ui::WorkerFree) { ui->setupUi(this); workerFreeModel=new QSqlTableModel(this); //创建SQL表格模型对象 workerFreeModel->setEditStrategy(QSqlTableModel::OnManualSubmit);//设置编辑模式 freeInfoRadioGroup=new QButtonGroup(this); //创建按键组对象 freeInfoRadioGroup->addButton(ui->attendRadioButton,0); //添加单选按钮"出勤",序号为0 freeInfoRadioGroup->addButton(ui->freeRadioButton,1); //添加单选按钮"请假",序号为1 ui->attendRadioButton->setChecked(true); //设置默认单选按键为"出勤" QDateTime time = QDateTime::currentDateTime(); //获取当前系统时间 QString str = time.toString("yyyy-MM-dd hh:mm:ss"); //格式化 ui->freeTimeLineEdit->setText(str); //设置界面中"当前时间"默认内容为系统时间 ui->freeTextLineEdit->hide(); //默认隐藏"请假事由"文本编辑行 ui->label_3->hide(); //默认隐藏标签 } /*********员工请假类WorkerFree析构函数*******************************************************/ WorkerFree::~WorkerFree() { delete ui; } /*********《槽函数》"提交"按键函数*******************************************************/ void WorkerFree::on_workerFreeBtn_clicked() { if(!this->judgeEmpty()) //判断员工输入是否为空 return; workerFreeModel->setTable("worker");//设置连接的数据库表为"worker" workerFreeModel->select(); //启动查询 int i,j=0; //i用于设置for循环变量,j=1表示检索到员工,j=0表示为检索到员工 for(i=0;i<workerFreeModel->rowCount();i++) { if(workerFreeModel->data(workerFreeModel->index(i,0)).toString()== //查询表中所有行 ui->workerNameLineEdit->text()) { j=1; //表中发现对应员工 break; //退出for循环 } else //表中未发现员工 j=0; } qDebug()<<i<<workerFreeModel->rowCount(); //输出表中行数 if(j==0) //如果未发现员工,输出警告信息 { QMessageBox::information(this,"提示","不存在此员工信息",QMessageBox::Yes); this->clearAll(); return; } workerFreeModel->setTable("workerattend"); //设置连接表为"workerattend" QSqlRecord record=workerFreeModel->record();//获取一个空记录 record.setValue("workernum",ui->workerNameLineEdit->text()); //workernum填充数据 if(freeInfoRadioGroup->checkedId()==0) //判断单选按键为"出勤" { record.setValue("workfree","出勤"); //workfree填充数据 record.setValue("freetime",ui->freeTimeLineEdit->text()); } else //判断单选按键为"请假" { record.setValue("workfree","请假"); //workfree填充数据 record.setValue("freetime",ui->freeTimeLineEdit->text()); //freetime填充数据 record.setValue("freetext",ui->freeTextLineEdit->text()); //freetext填充数据 record.setValue("freestatus","未批准"); } workerFreeModel->insertRecord(-1,record); //首行添加数据 if(workerFreeModel->submitAll()) //提交数据 { QMessageBox::information(this,"提示","提交成功",QMessageBox::Yes); this->clearAll(); //提交成功,清除所有 } else { QMessageBox::information(this,"提示","提交失败",QMessageBox::Yes); this->clearAll(); //提交失败,清除所有 } } /*********《槽函数》"返回"按键函数*******************************************************/ void WorkerFree::on_workerFreeReturnBtn_clicked() { if(ui->workerNameLineEdit->text().isEmpty()&&ui->freeTimeLineEdit->text().isEmpty()) { this->hide(); //判断员工输入内容为空,则直接隐藏推出 return; } else if(QMessageBox::question(this,"提示","是否取消提交",QMessageBox::Yes|QMessageBox::No) ==QMessageBox::Yes) { this->hide(); //员工输入了部分内容,提示是否取消,确认之后隐藏 } } /*********《槽函数》"请假"单选按键函数*******************************************************/ void WorkerFree::on_freeRadioButton_clicked() { ui->freeTextLineEdit->show(); //显示请假理由行编辑器 ui->label_3->show(); //显示提示标签 } /*********《槽函数》"出勤"单选按键函数*******************************************************/ void WorkerFree::on_attendRadioButton_clicked() { ui->freeTextLineEdit->hide(); //隐藏请假理由行编辑器 ui->label_3->hide(); //隐藏提示标签 } /*********判断员工输入的内容是否为空函数*************************************************/ bool WorkerFree::judgeEmpty() { if(ui->workerNameLineEdit->text().isEmpty()) { QMessageBox::warning(this,"警告","请填写请假人员姓名",QMessageBox::Yes); return false; } else return true; } /*********清除员工输入的内容函数*******************************************************/ void WorkerFree::clearAll() { ui->workerNameLineEdit->clear(); ui->freeTextLineEdit->clear(); }修复版本二
无注释版
cpp#include "workerfree.h" #include "ui_workerfree.h" WorkerFree::WorkerFree(QWidget *parent) : QWidget(parent), ui(new Ui::WorkerFree) { ui->setupUi(this); workerFreeModel = new QSqlTableModel(this); workerFreeModel->setEditStrategy(QSqlTableModel::OnManualSubmit); freeInfoRadioGroup = new QButtonGroup(this); freeInfoRadioGroup->addButton(ui->attendRadioButton, 0); freeInfoRadioGroup->addButton(ui->freeRadioButton, 1); ui->attendRadioButton->setChecked(true); QDateTime time = QDateTime::currentDateTime(); QString str = time.toString("yyyy-MM-dd hh:mm:ss"); ui->freeTimeLineEdit->setText(str); ui->freeTextLineEdit->hide(); ui->label_3->hide(); } WorkerFree::~WorkerFree() { delete ui; } void WorkerFree::on_workerFreeBtn_clicked() { if (!this->judgeEmpty()) { return; } workerFreeModel->setTable("worker"); workerFreeModel->select(); int i, j = 0; for (i = 0; i < workerFreeModel->rowCount(); i++) { if (workerFreeModel->data(workerFreeModel->index(i, 0)).toString() == ui->workerNameLineEdit->text()) { j = 1; break; } else { j = 0; } } qDebug() << i << workerFreeModel->rowCount(); if (j == 0) { QMessageBox::information(this, "提示", "不存在此员工信息", QMessageBox::Yes); this->clearAll(); return; } workerFreeModel->setTable("workerattend"); QSqlRecord record = workerFreeModel->record(); record.setValue("workernum", ui->workerNameLineEdit->text()); if (freeInfoRadioGroup->checkedId() == 0) { record.setValue("workfree", "出勤"); record.setValue("freetime", ui->freeTimeLineEdit->text()); } else { record.setValue("workfree", "请假"); record.setValue("freetime", ui->freeTimeLineEdit->text()); record.setValue("freetext", ui->freeTextLineEdit->text()); record.setValue("freestatus", "未批准"); } workerFreeModel->insertRecord(-1, record); if (workerFreeModel->submitAll()) { QMessageBox::information(this, "提示", "提交成功", QMessageBox::Yes); this->clearAll(); } else { QMessageBox::information(this, "提示", "提交失败", QMessageBox::Yes); this->clearAll(); } } void WorkerFree::on_workerFreeReturnBtn_clicked() { if (ui->workerNameLineEdit->text().isEmpty() && ui->freeTimeLineEdit->text().isEmpty()) { this->hide(); return; } else if (QMessageBox::question(this, "提示", "是否取消提交", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { this->hide(); } } void WorkerFree::on_freeRadioButton_clicked() { ui->freeTextLineEdit->show(); ui->label_3->show(); } void WorkerFree::on_attendRadioButton_clicked() { ui->freeTextLineEdit->hide(); ui->label_3->hide(); } bool WorkerFree::judgeEmpty() { if (ui->workerNameLineEdit->text().isEmpty()) { QMessageBox::warning(this, "警告", "请填写请假人员姓名", QMessageBox::Yes); return false; } return true; } void WorkerFree::clearAll() { ui->workerNameLineEdit->clear(); ui->freeTextLineEdit->clear(); }有注释版
cpp// ============================================================ // 文件:workerfree.cpp // 功能:员工请假/考勤管理界面的实现 // 说明:工作人员提交请假申请,管理员管理出勤状态 // ============================================================ #include "workerfree.h" // 包含自己的头文件声明 // 让编译器知道类 WorkerFree 的结构、成员函数和成员变量 #include "ui_workerfree.h" // 包含由 .ui 文件生成的 UI 类头文件 // 包含了 Ui::WorkerFree 类的定义,其中有所有控件的指针 // ============================================================ // 构造函数 - 初始化考勤管理界面 // 参数:parent - 父窗口指针,默认 nullptr // 当用户打开考勤管理窗口时,此对象被创建 // ============================================================ WorkerFree::WorkerFree(QWidget *parent) : QWidget(parent), // 调用父类 QWidget 的构造函数,传入父窗口指针 ui(new Ui::WorkerFree) // 创建 UI 对象(由 Qt Designer 生成的界面类) { ui->setupUi(this); // setupUi() 加载 .ui 文件,创建所有控件并设置布局 // -------------------------------------------------------- // 1. 创建数据模型 // -------------------------------------------------------- workerFreeModel = new QSqlTableModel(this); // 创建 SQL 表格模型,设置父对象为 this(自动内存管理) // 用于与考勤数据表交互 workerFreeModel->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略为"手动提交" // 修改后需要调用 submitAll() 才会保存到数据库 // -------------------------------------------------------- // 2. 创建按钮组(出勤/请假) // -------------------------------------------------------- freeInfoRadioGroup = new QButtonGroup(this); // 创建按钮组,父对象为 this(自动内存管理) // 用于实现单选互斥 freeInfoRadioGroup->addButton(ui->attendRadioButton, 0); // 将"出勤"单选按钮加入组,ID 为 0 freeInfoRadioGroup->addButton(ui->freeRadioButton, 1); // 将"请假"单选按钮加入组,ID 为 1 ui->attendRadioButton->setChecked(true); // 默认选中"出勤"单选按钮 // 用户打开窗口时,默认显示出勤模式 // -------------------------------------------------------- // 3. 设置当前时间 // -------------------------------------------------------- QDateTime time = QDateTime::currentDateTime(); // 获取当前系统时间 QString str = time.toString("yyyy-MM-dd hh:mm:ss"); // 将时间格式化为字符串 ui->freeTimeLineEdit->setText(str); // 将当前时间显示在时间输入框中 // -------------------------------------------------------- // 4. 默认隐藏"请假事由"相关控件 // -------------------------------------------------------- ui->freeTextLineEdit->hide(); // 默认隐藏"请假事由"文本输入框 // 只有选择"请假"时才显示 ui->label_3->hide(); // 默认隐藏"事由"标签 // 只有选择"请假"时才显示 } // ============================================================ // 析构函数 - 释放资源 // 当窗口关闭时自动调用 // ============================================================ WorkerFree::~WorkerFree() { delete ui; // 删除 UI 对象,释放界面上所有控件的内存 // workerFreeModel 不需要手动 delete,因为设置了父对象 this } // ============================================================ // "提交"按钮槽函数 // 当用户点击"提交"按钮时被调用 // 功能:提交请假或出勤记录到数据库 // ============================================================ void WorkerFree::on_workerFreeBtn_clicked() { // -------------------------------------------------------- // 1. 验证输入 // -------------------------------------------------------- if (!this->judgeEmpty()) { // 判断员工姓名是否为空 // 如果为空,judgeEmpty() 已弹出警告框,直接返回 return; } // -------------------------------------------------------- // 2. 检查员工是否存在 // -------------------------------------------------------- workerFreeModel->setTable("worker"); // 切换到 "worker" 表(员工信息表) workerFreeModel->select(); // 执行查询,加载所有员工数据 int i, j = 0; // i:循环变量 // j:标志位,1 表示找到员工,0 表示未找到 for (i = 0; i < workerFreeModel->rowCount(); i++) { // 遍历所有行,检查员工是否存在 if (workerFreeModel->data(workerFreeModel->index(i, 0)).toString() == ui->workerNameLineEdit->text()) { // 如果当前行的第0列(员工姓名)与输入匹配 j = 1; // 找到员工 break; // 退出循环 } else { j = 0; // 未找到员工 } } qDebug() << i << workerFreeModel->rowCount(); // 输出调试信息:当前索引和总行数 if (j == 0) { // 如果未找到员工 QMessageBox::information(this, "提示", "不存在此员工信息", QMessageBox::Yes); // 弹出提示框 this->clearAll(); // 清空所有输入框 return; // 退出函数 } // -------------------------------------------------------- // 3. 构建考勤记录 // -------------------------------------------------------- workerFreeModel->setTable("workerattend"); // 切换到 "workerattend" 表(考勤记录表) QSqlRecord record = workerFreeModel->record(); // 获取一个空记录结构 record.setValue("workernum", ui->workerNameLineEdit->text()); // 设置 "workernum" 字段(员工姓名) if (freeInfoRadioGroup->checkedId() == 0) { // 如果"出勤"按钮被选中 record.setValue("workfree", "出勤"); // 设置 "workfree" 字段为"出勤" record.setValue("freetime", ui->freeTimeLineEdit->text()); // 设置 "freetime" 字段为当前时间 } else { // 如果"请假"按钮被选中 record.setValue("workfree", "请假"); // 设置 "workfree" 字段为"请假" record.setValue("freetime", ui->freeTimeLineEdit->text()); // 设置 "freetime" 字段为当前时间 record.setValue("freetext", ui->freeTextLineEdit->text()); // 设置 "freetext" 字段为请假事由 record.setValue("freestatus", "未批准"); // 设置 "freestatus" 字段为"未批准" // 请假需要管理员审批 } // -------------------------------------------------------- // 4. 插入记录并提交 // -------------------------------------------------------- workerFreeModel->insertRecord(-1, record); // 插入记录到模型末尾(-1 表示追加到最后) if (workerFreeModel->submitAll()) { // 提交成功 QMessageBox::information(this, "提示", "提交成功", QMessageBox::Yes); // 弹出提示框 this->clearAll(); // 清空所有输入框 } else { // 提交失败 QMessageBox::information(this, "提示", "提交失败", QMessageBox::Yes); // ⚠️ 问题:应该用 critical() 而不是 information() // 且没有显示具体错误信息 this->clearAll(); // 清空所有输入框 } } // ============================================================ // "返回"按钮槽函数 // 当用户点击"返回"按钮时被调用 // 功能:关闭当前窗口 // ============================================================ void WorkerFree::on_workerFreeReturnBtn_clicked() { if (ui->workerNameLineEdit->text().isEmpty() && ui->freeTimeLineEdit->text().isEmpty()) { // 如果所有输入框都为空 this->hide(); // 直接隐藏窗口 return; } else if (QMessageBox::question(this, "提示", "是否取消提交", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { // 如果有输入内容,询问是否取消 // 用户点击"是",隐藏窗口 this->hide(); } // 用户点击"否",继续编辑 } // ============================================================ // "请假"单选按钮槽函数 // 当用户点击"请假"单选按钮时被调用 // 功能:显示请假事由输入框 // ============================================================ void WorkerFree::on_freeRadioButton_clicked() { ui->freeTextLineEdit->show(); // 显示请假事由输入框 ui->label_3->show(); // 显示"事由"标签 } // ============================================================ // "出勤"单选按钮槽函数 // 当用户点击"出勤"单选按钮时被调用 // 功能:隐藏请假事由输入框 // ============================================================ void WorkerFree::on_attendRadioButton_clicked() { ui->freeTextLineEdit->hide(); // 隐藏请假事由输入框 ui->label_3->hide(); // 隐藏"事由"标签 } // ============================================================ // 判断输入是否为空 // 返回值:true - 不为空,false - 为空 // ============================================================ bool WorkerFree::judgeEmpty() { if (ui->workerNameLineEdit->text().isEmpty()) { // 如果员工姓名为空 QMessageBox::warning(this, "警告", "请填写请假人员姓名", QMessageBox::Yes); // 弹出警告框 return false; // 返回 false } return true; // 返回 true } // ============================================================ // 清空所有输入框 // ============================================================ void WorkerFree::clearAll() { ui->workerNameLineEdit->clear(); // 清空员工姓名输入框 ui->freeTextLineEdit->clear(); // 清空请假事由输入框 }8.workerfree.ui
9.workerinfo.h
原始版本一
cpp#ifndef WORKERINFO_H #define WORKERINFO_H #include <QWidget> #include <QDebug> #include <QMessageBox> #include <QSqlTableModel> #include <QSqlRecord> #include <QButtonGroup> //#include "managermanage.h" namespace Ui { class WorkerInfo; } //工作人员信息添加窗口类,公有继承自QWidget类 //该添加窗口,使用UI编辑器,构建整个UI界面。 class WorkerInfo : public QWidget { Q_OBJECT public: explicit WorkerInfo(QWidget *parent = 0); ~WorkerInfo(); private slots: void on_AddActBtn_clicked(); //添加按键槽函数 void on_ReturnBtn_clicked(); //返回按键槽函数 signals: void EmitWorkerChanged(); private: Ui::WorkerInfo *ui; QSqlTableModel *model; //使用SQL表格模型操作数据库 QButtonGroup *isManagerRadioGroup;//创建按键组指针 bool judgeEmpty(); //判断用户输入的账号、密码是否为空 void clearAll(); //清除界面用户输入的账号、密码和电话内容 }; #endif // WORKERINFO_H修复版本二
无注释版
cpp#ifndef WORKERINFO_H #define WORKERINFO_H #include <QWidget> #include <QDebug> #include <QMessageBox> #include <QSqlTableModel> #include <QSqlRecord> #include <QButtonGroup> namespace Ui { class WorkerInfo; } class WorkerInfo : public QWidget { Q_OBJECT public: explicit WorkerInfo(QWidget *parent = 0); ~WorkerInfo(); private slots: void on_AddActBtn_clicked(); void on_ReturnBtn_clicked(); signals: void EmitWorkerChanged(); private: Ui::WorkerInfo *ui; QSqlTableModel *model; QButtonGroup *isManagerRadioGroup; bool judgeEmpty(); void clearAll(); }; #endif // WORKERINFO_H有注释版
cpp// ============================================================ // 文件:workerinfo.h // 功能:工作人员信息添加界面的头文件声明 // 说明:管理员在此添加新的工作人员账号 // ============================================================ #ifndef WORKERINFO_H // 作用:防止头文件被多次包含(Include Guard) // 如果 WORKERINFO_H 未定义,则定义它并包含头文件内容 // 如果已定义,则跳过整个头文件内容 #define WORKERINFO_H // 定义宏 WORKERINFO_H,标记这个头文件已经被包含 // ============================================================ // 头文件包含 // ============================================================ #include <QWidget> // 包含 QWidget 基类 // QWidget 是所有 Qt 窗口控件的基类 // 本类继承 QWidget,作为一个独立的窗口部件 #include <QDebug> // 包含 QDebug 类 // 用于输出调试信息到控制台 #include <QMessageBox> // 包含 QMessageBox 类 // 用于显示提示、警告、错误等消息框 #include <QSqlTableModel> // 包含 QSqlTableModel 类(可读写表格模型) // 用于与数据库表交互,支持增删改查操作 // 本类用于操作工作人员数据表 #include <QSqlRecord> // 包含 QSqlRecord 类 // 用于表示数据库中的一条记录(一行数据) // 在添加工作人员时,用于构建新记录 #include <QButtonGroup> // 包含 QButtonGroup 类 // 用于管理一组按钮,实现单选互斥效果 // 本类用于管理"是/否管理员"两个单选按钮 //#include "managermanage.h" // 已注释:原本可能需要管理员管理界面的头文件 // 但当前不需要 // ============================================================ // UI 命名空间声明 // ============================================================ namespace Ui { class WorkerInfo; // 声明 UI 类 // 这个类由 Qt 的 uic 工具根据 workerinfo.ui 文件自动生成 // 包含了界面上所有控件的指针 } // ============================================================ // WorkerInfo 类定义 // 工作人员信息添加窗口,继承自 QWidget // 管理员在此添加新的工作人员账号 // ============================================================ class WorkerInfo : public QWidget // class WorkerInfo : 定义一个名为 WorkerInfo 的类 // public QWidget : 公有继承自 QWidget 基类 // 作为独立的窗口部件,可以嵌入到其他窗口或单独显示 { Q_OBJECT // Qt 元对象宏 // 启用信号槽机制、运行时类型信息等 Qt 元对象功能 // 因为类中使用了 signals 和 private slots,必须包含此宏 public: // ============================================================ // public 区域:对外公开的接口 // ============================================================ explicit WorkerInfo(QWidget *parent = 0); // 构造函数 // explicit: 防止隐式类型转换 // QWidget *parent = 0: 父窗口指针,默认值为 nullptr ~WorkerInfo(); // 析构函数 // 当对象被销毁时自动调用,释放资源 private slots: // ============================================================ // 私有槽函数区域 // 响应按钮点击事件 // ============================================================ void on_AddActBtn_clicked(); // "添加"按钮的槽函数 // 当用户点击"添加"时被调用 // 功能:验证输入 → 检查重复 → 添加工作人员到数据库 void on_ReturnBtn_clicked(); // "返回"按钮的槽函数 // 当用户点击"返回"时被调用 // 功能:关闭当前添加窗口 signals: // ============================================================ // 信号区域 // ============================================================ void EmitWorkerChanged(); // 工作人员信息变更信号 // 当工作人员信息被添加或修改时发射此信号 // 用于通知其他模块(如工作人员管理界面)刷新数据 private: // ============================================================ // private 区域:私有的成员变量 // 只能在类内部访问,外部不可见 // ============================================================ Ui::WorkerInfo *ui; // UI 对象指针 // 指向由 uic 工具生成的 UI 类对象 // 通过这个指针可以访问界面上所有的控件 QSqlTableModel *model; // SQL 表格模型对象指针 // 用于与工作人员表(如 worker)交互 // 提供数据的插入、查询等功能 QButtonGroup *isManagerRadioGroup; // 管理员权限按钮组 // 管理"是管理员"和"否管理员"两个单选按钮 // 实现互斥选择,决定新用户是否为管理员 // ============================================================ // 私有辅助函数 // ============================================================ bool judgeEmpty(); // 判断用户输入的账号、密码是否为空 // 返回值:true - 都不为空,false - 至少有一个为空 // 在添加前调用,验证输入完整性 void clearAll(); // 清除界面用户输入的账号、密码和电话内容 // 清空所有输入框,重置界面状态 // 在添加成功或取消时调用 }; #endif // WORKERINFO_H // 结束条件编译块 // 如果头文件被重复包含,从 #ifndef 到 #endif 之间的内容会被跳过9.workerinfo.cpp
原始版本一
cpp#include "workerinfo.h" #include "ui_workerinfo.h" /*********WorkerInfo类构造函数***********************************/ WorkerInfo::WorkerInfo(QWidget *parent) : QWidget(parent), ui(new Ui::WorkerInfo) { ui->setupUi(this); isManagerRadioGroup=new QButtonGroup; //创建按键组,实现单选功能 isManagerRadioGroup->addButton(ui->yesradioButton,0);//添加"是"按键,编号为0 isManagerRadioGroup->addButton(ui->noradioButton,1); //添加"否"按键,编号为1 ui->noradioButton->setChecked(true); //设置"否"按键默认选中 //设使用表格模型tablemodel实现与数据库交互 model=new QSqlTableModel(this); //设置数据表名称为为"worker" model->setTable("worker"); //设置编辑策略:数据改变先缓存,直到调用提交函数。 model->setEditStrategy(QSqlTableModel::OnManualSubmit); //从"第5列"开始的"5列"数据 model->removeColumns(5,5);/*?*/ } /*********WorkerInfo类析构造函数***********************************/ WorkerInfo::~WorkerInfo() { delete ui; } /*********"添加"按键实现函数*************************************/ void WorkerInfo::on_AddActBtn_clicked() { if(!this->judgeEmpty()) //如果账号和密码有一个为空,则直接退出。 return; model->select(); //数据库查询 int i; //用于for循环中,测试用户输入账户与数据表中账户是否一致。 for(i=0;i<model->rowCount();i++) { //不断查询数据库中数据,调取表中第一列账户名,与用户输入账户名进行比较 if(model->data(model->index(i,0)).toString()==ui->worknumlineEdit->text()) { break; //发现相同账户名,结束for循环 } } //如果发现循环次数i小于数据表中总的数据条数,说明数据表中本来就有该账户 if(i!=model->rowCount()) { //弹出提示人员存在信息窗口 QMessageBox::information(this,"提示","该人员已经存在",QMessageBox::Yes); this->clearAll(); //清除窗口内容 return; //函数返回 } QSqlRecord record=model->record(); //生成一个空的字段(空数据行) //将ui界面用户输入的"账号"、"密码"、"电话"内容,放到该空行的 //workernum、workerpass、workerphone里面 record.setValue("workernum",ui->worknumlineEdit->text()); record.setValue("workerpass",ui->workpasslineEdit->text()); record.setValue("workerphone",ui->workphonelineEdit->text()); if(isManagerRadioGroup->checkedId()==0) //判断单选窗口选中的按键 { //判断按键编号为0,表示按下"是"按键,则设置表中workertype字段 //内容为"是" record.setValue("workertype","是"); } else { record.setValue("workertype","否"); } model->insertRecord(-1,record); //将新行数据插入到表的第一行 if(model->submitAll()) //提交修改数据 { //创建信息窗口,显示添加成功 QMessageBox::information(this,"提示","工作人员添加成功",QMessageBox::Yes); this->clearAll(); //清除用户如输入的内容,准备添加新用户 } } /*********"返回"按键实现函数*************************************/ void WorkerInfo::on_ReturnBtn_clicked() { //如果"账户""密码""电话"都为空,关闭时就只退出收尾即可 if(ui->worknumlineEdit->text().isEmpty()&&ui->workpasslineEdit->text().isEmpty()&& ui->workphonelineEdit->text().isEmpty()) { emit EmitWorkerChanged(); //发送数据改变信号。---------------实际没有使用槽函数,改进???? this->hide(); //隐藏该窗口(关闭) qDebug("addworker"); //输出调试信息 return; //程序返回 } //如果还有用户输入的内容,创建询问窗口,让用户确认是否退出 if(QMessageBox::question(this,"提示","尚未保存,是否退出",QMessageBox::Yes|QMessageBox::No)==QMessageBox::Yes) { //emit EmitToTeacherManage(); this->hide(); //窗口隐藏(关闭) } } /*********判断用户输入内容是否为空函数******************************/ bool WorkerInfo::judgeEmpty() { if(ui->worknumlineEdit->text().isEmpty()) //判断用户输入的"账号"内容是否为空 { //内容为空,创建警告窗口,提示错误信息 QMessageBox::warning(this,"警告","人员编号不能为空",QMessageBox::Yes); return false; } else if(ui->workpasslineEdit->text().isEmpty())//判断用户输入的"密码"是否为空 { //内容为空,创建警告窗口,提示错误信息 QMessageBox::warning(this,"警告","密码不能为空",QMessageBox::Yes); return false; } else//用户输入的"账号"和"密码"都有内容,则直接返回true return true; } /*********清除用户输入内容函数*************************************/ void WorkerInfo::clearAll() { ui->worknumlineEdit->clear(); //清空用户输入的 用户名 ui->workpasslineEdit->clear(); //清空用户输入的 登陆密码 ui->workphonelineEdit->clear(); //清除用户输入的 电话 }修复版本二
无注释版
cpp#include "workerinfo.h" #include "ui_workerinfo.h" WorkerInfo::WorkerInfo(QWidget *parent) : QWidget(parent), ui(new Ui::WorkerInfo) { ui->setupUi(this); isManagerRadioGroup = new QButtonGroup; isManagerRadioGroup->addButton(ui->yesradioButton, 0); isManagerRadioGroup->addButton(ui->noradioButton, 1); ui->noradioButton->setChecked(true); model = new QSqlTableModel(this); model->setTable("worker"); model->setEditStrategy(QSqlTableModel::OnManualSubmit); model->removeColumns(5, 5); } WorkerInfo::~WorkerInfo() { delete ui; } void WorkerInfo::on_AddActBtn_clicked() { if (!this->judgeEmpty()) { return; } model->select(); int i; for (i = 0; i < model->rowCount(); i++) { if (model->data(model->index(i, 0)).toString() == ui->worknumlineEdit->text()) { break; } } if (i != model->rowCount()) { QMessageBox::information(this, "提示", "该人员已经存在", QMessageBox::Yes); this->clearAll(); return; } QSqlRecord record = model->record(); record.setValue("workernum", ui->worknumlineEdit->text()); record.setValue("workerpass", ui->workpasslineEdit->text()); record.setValue("workerphone", ui->workphonelineEdit->text()); if (isManagerRadioGroup->checkedId() == 0) { record.setValue("workertype", "是"); } else { record.setValue("workertype", "否"); } model->insertRecord(-1, record); if (model->submitAll()) { QMessageBox::information(this, "提示", "工作人员添加成功", QMessageBox::Yes); this->clearAll(); } } void WorkerInfo::on_ReturnBtn_clicked() { if (ui->worknumlineEdit->text().isEmpty() && ui->workpasslineEdit->text().isEmpty() && ui->workphonelineEdit->text().isEmpty()) { emit EmitWorkerChanged(); this->hide(); qDebug("addworker"); return; } if (QMessageBox::question(this, "提示", "尚未保存,是否退出", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { this->hide(); } } bool WorkerInfo::judgeEmpty() { if (ui->worknumlineEdit->text().isEmpty()) { QMessageBox::warning(this, "警告", "人员编号不能为空", QMessageBox::Yes); return false; } else if (ui->workpasslineEdit->text().isEmpty()) { QMessageBox::warning(this, "警告", "密码不能为空", QMessageBox::Yes); return false; } else { return true; } } void WorkerInfo::clearAll() { ui->worknumlineEdit->clear(); ui->workpasslineEdit->clear(); ui->workphonelineEdit->clear(); }有注释版
cpp// ============================================================ // 文件:workerinfo.cpp // 功能:工作人员信息添加界面的实现 // 说明:管理员在此添加新的工作人员账号 // ============================================================ #include "workerinfo.h" // 包含自己的头文件声明 // 让编译器知道类 WorkerInfo 的结构、成员函数和成员变量 #include "ui_workerinfo.h" // 包含由 .ui 文件生成的 UI 类头文件 // 包含了 Ui::WorkerInfo 类的定义,其中有所有控件的指针 // ============================================================ // 构造函数 - 初始化添加工作人员界面 // 参数:parent - 父窗口指针,默认 nullptr // 当管理员点击"添加工作人员"时,此对象被创建 // ============================================================ WorkerInfo::WorkerInfo(QWidget *parent) : QWidget(parent), // 调用父类 QWidget 的构造函数,传入父窗口指针 ui(new Ui::WorkerInfo) // 创建 UI 对象(由 Qt Designer 生成的界面类) { ui->setupUi(this); // setupUi() 加载 .ui 文件,创建所有控件并设置布局 // -------------------------------------------------------- // 1. 创建管理员权限按钮组 // -------------------------------------------------------- isManagerRadioGroup = new QButtonGroup; // 创建按钮组对象 // ⚠️ 问题:没有设置父对象 this,可能导致内存泄漏 // 建议:new QButtonGroup(this) isManagerRadioGroup->addButton(ui->yesradioButton, 0); // 将"是"单选按钮加入组,ID 为 0 isManagerRadioGroup->addButton(ui->noradioButton, 1); // 将"否"单选按钮加入组,ID 为 1 ui->noradioButton->setChecked(true); // 默认选中"否"(普通工作人员) // 用户打开窗口时,默认添加普通工作人员 // -------------------------------------------------------- // 2. 创建数据模型 // -------------------------------------------------------- model = new QSqlTableModel(this); // 创建 SQL 表格模型,设置父对象为 this(自动内存管理) model->setTable("worker"); // 设置要操作的数据表为 "worker"(工作人员表) model->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略为"手动提交" // 修改后需要调用 submitAll() 才会保存到数据库 model->removeColumns(5, 5); // 从第5列开始,移除5列(隐藏不需要显示的列) // ⚠️ 问题:注释不清晰,不确定移除了哪些列 } // ============================================================ // 析构函数 - 释放资源 // 当窗口关闭时自动调用 // ============================================================ WorkerInfo::~WorkerInfo() { delete ui; // 删除 UI 对象,释放界面上所有控件的内存 // model 不需要手动 delete,因为设置了父对象 this // ⚠️ 问题:isManagerRadioGroup 没有父对象,可能内存泄漏 } // ============================================================ // "添加"按钮槽函数 // 当用户点击"添加"按钮时被调用 // 功能:验证输入 → 检查重复 → 添加工作人员到数据库 // ============================================================ void WorkerInfo::on_AddActBtn_clicked() { // -------------------------------------------------------- // 1. 输入验证 // -------------------------------------------------------- if (!this->judgeEmpty()) { // 判断账号和密码是否为空 // 如果为空,judgeEmpty() 已弹出警告框,直接返回 return; } // -------------------------------------------------------- // 2. 检查账号是否已存在 // -------------------------------------------------------- model->select(); // 执行查询,从数据库加载所有工作人员数据 int i; // 用于循环遍历,检查账号是否已存在 for (i = 0; i < model->rowCount(); i++) { // 遍历所有行,检查账号是否重复 if (model->data(model->index(i, 0)).toString() == ui->worknumlineEdit->text()) { // 如果当前行的第0列(账号)与输入匹配 break; // 找到重复,退出循环 } } if (i != model->rowCount()) { // 如果 i 不等于总行数,说明在循环中找到了重复账号(break 提前退出) QMessageBox::information(this, "提示", "该人员已经存在", QMessageBox::Yes); // 弹出提示框 this->clearAll(); // 清空所有输入框 return; // 退出函数 } // -------------------------------------------------------- // 3. 构建工作人员记录 // -------------------------------------------------------- QSqlRecord record = model->record(); // 获取一个空记录结构(包含所有字段,但没有数据) record.setValue("workernum", ui->worknumlineEdit->text()); // 设置 "workernum" 字段(账号) record.setValue("workerpass", ui->workpasslineEdit->text()); // 设置 "workerpass" 字段(密码) record.setValue("workerphone", ui->workphonelineEdit->text()); // 设置 "workerphone" 字段(电话) if (isManagerRadioGroup->checkedId() == 0) { // 如果"是管理员"按钮被选中(ID 为 0) record.setValue("workertype", "是"); // 设置 "workertype" 字段为"是"(管理员) } else { // 如果"否管理员"按钮被选中(ID 为 1) record.setValue("workertype", "否"); // 设置 "workertype" 字段为"否"(普通工作人员) } // -------------------------------------------------------- // 4. 插入记录并提交 // -------------------------------------------------------- model->insertRecord(-1, record); // 插入记录到模型末尾(-1 表示追加到最后) if (model->submitAll()) { // 提交成功 QMessageBox::information(this, "提示", "工作人员添加成功", QMessageBox::Yes); // 弹出提示框 this->clearAll(); // 清空所有输入框,准备添加下一个 } // ⚠️ 问题:提交失败时没有错误提示 } // ============================================================ // "返回"按钮槽函数 // 当用户点击"返回"按钮时被调用 // 功能:关闭当前添加窗口 // ============================================================ void WorkerInfo::on_ReturnBtn_clicked() { // -------------------------------------------------------- // 1. 检查是否有输入内容 // -------------------------------------------------------- if (ui->worknumlineEdit->text().isEmpty() && ui->workpasslineEdit->text().isEmpty() && ui->workphonelineEdit->text().isEmpty()) { // 所有输入框都为空 → 直接关闭 emit EmitWorkerChanged(); // 发射信号(通知其他模块数据已变更) // ⚠️ 问题:信号可能未被连接 this->hide(); // 隐藏窗口 qDebug("addworker"); // 输出调试信息 return; // 退出函数 } // -------------------------------------------------------- // 2. 有输入内容 → 询问是否保存 // -------------------------------------------------------- if (QMessageBox::question(this, "提示", "尚未保存,是否退出", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { // 用户选择"是" → 放弃修改并退出 // emit EmitToTeacherManage(); // 已注释 this->hide(); // 隐藏窗口 } // 用户选择"否" → 什么都不做,继续编辑 } // ============================================================ // 判断输入是否为空 // 返回值:true - 都不为空,false - 至少有一个为空 // ============================================================ bool WorkerInfo::judgeEmpty() { if (ui->worknumlineEdit->text().isEmpty()) { // 如果账号为空 QMessageBox::warning(this, "警告", "人员编号不能为空", QMessageBox::Yes); // 弹出警告框 return false; // 返回 false } else if (ui->workpasslineEdit->text().isEmpty()) { // 如果密码为空 QMessageBox::warning(this, "警告", "密码不能为空", QMessageBox::Yes); // 弹出警告框 return false; // 返回 false } else { // 账号和密码都不为空 return true; // 返回 true } } // ============================================================ // 清空所有输入框 // ============================================================ void WorkerInfo::clearAll() { ui->worknumlineEdit->clear(); // 清空账号输入框 ui->workpasslineEdit->clear(); // 清空密码输入框 ui->workphonelineEdit->clear(); // 清空电话输入框 }9.workerinfo.ui
10.workermanage.h
原始版本一
cpp#ifndef WORKERMANAGE_H #define WORKERMANAGE_H #include <QMainWindow> #include <QTableView> #include <QSqlTableModel> #include <QLabel> #include <QDebug> #include <QSqlError> #include <QString> #include "ownerinfo.h" #include "houseinfo.h" #include "carstationinfo.h" #include "workerfree.h" #include "setowner.h" #include "pricemanage.h" #include "paymanage.h" namespace Ui { class WorkerManage; } //工作人员工作窗口类,公有继承自QMainWindow类 //工作加窗口,使用UI编辑器,构建整个UI界面。 class WorkerManage : public QMainWindow { Q_OBJECT public: explicit WorkerManage(QWidget *parent = 0); ~WorkerManage(); private: Ui::WorkerManage *ui; QLabel *lable; //创建标签对象的一个指针 QTableView *workerTableView;//创建表格试图对象的一个指针 QSqlTableModel *workerModel;//创建SQL表格模型的一个指针 /********以下指针均为各种界面对象的指针,用于打开一个界面************/ OwnerInfo *ownerInfo; //创建业主登记对象的一个指针 HouseInfo *houseInfo; //创建房产登记对象的一个指针 CarStationInfo *carStationInfo;//创建录入车位信息对象的一个指针 PriceManage *pricemanage; //创建价格维护对象的一个指针 PayManage *paymanage; //创建缴费对象的一个指针象指针 WorkerFree *workFree; //创建请假对象的一个指针 SetOwner *owner; /*******************************************************************/ /****指示用户进行的操作,不同取值含义不同,如下:******************* ------------------------------------------------------- | workerManageStatus | 含义 | ------------------------------------------------------- | 0 | 系统初次进入 | | 1 | 已经查询过业主信息 | | 2 | 已经查询过车位信息 | | 3 | 已经查询过故障信息 | | 4 | 已经创建了请假 | | 5 | 已经查询月度出勤信息 | ------------------------------------------------------- * ****************************************************************/ int workerManageStatus; void delCurRow(); //删除当前行 void alterCurRow(); //修改当前行 void setTableHead();//设置当前行 signals: //void EmitToManagerManage(); void EmitOwnerChanged(); private slots: void showOwnerSlot(); //业主查询槽函数 void addOwnerSlot(); //成员登记槽函数 void alterOwnerSlot(); //业主修改槽函数 void delOwnerSlot(); //删除业主槽函数 void addHouseSlot(); //房产登记槽函数 void showCarStationSlot(); //查看车位信息槽函数 void addCarStationSlot(); //录入车位信息槽函数 void alterCarStationSlot(); //修改车位信息槽函数 void delCarStationSlot(); //删除车位信息槽函数 void carStationRentActSlot(); //车位出租槽函数 //void houseInfoSlot(); void priceManageSlot(); //价格维护槽函数 void payInfoSlot(); //缴费查询槽函数 void paySlot(); //缴费槽函数 void issueShowSlot(); //故障查询槽函数 void issueRepairSlot(); //故障维修槽函数 void freeSlot(); //请假槽函数 void freeConfirmSlot(); //销假槽函数 void attendSlot(); //月度出勤槽函数 //void attendWorkerSlot(); void refreshTableViewSlot(); //定义为空 }; #endif // WORKERMANAGE_H修复版本二
无注释版
cpp#ifndef WORKERMANAGE_H #define WORKERMANAGE_H #include <QMainWindow> #include <QTableView> #include <QSqlTableModel> #include <QLabel> #include <QDebug> #include <QSqlError> #include <QString> #include "ownerinfo.h" #include "houseinfo.h" #include "carstationinfo.h" #include "workerfree.h" #include "setowner.h" #include "pricemanage.h" #include "paymanage.h" namespace Ui { class WorkerManage; } class WorkerManage : public QMainWindow { Q_OBJECT public: explicit WorkerManage(QWidget *parent = 0); ~WorkerManage(); private: Ui::WorkerManage *ui; QLabel *lable; QTableView *workerTableView; QSqlTableModel *workerModel; OwnerInfo *ownerInfo; HouseInfo *houseInfo; CarStationInfo *carStationInfo; PriceManage *pricemanage; PayManage *paymanage; WorkerFree *workFree; SetOwner *owner; int workerManageStatus; void delCurRow(); void alterCurRow(); void setTableHead(); signals: void EmitOwnerChanged(); private slots: void showOwnerSlot(); void addOwnerSlot(); void alterOwnerSlot(); void delOwnerSlot(); void addHouseSlot(); void showCarStationSlot(); void addCarStationSlot(); void alterCarStationSlot(); void delCarStationSlot(); void carStationRentActSlot(); void priceManageSlot(); void payInfoSlot(); void paySlot(); void issueShowSlot(); void issueRepairSlot(); void freeSlot(); void freeConfirmSlot(); void attendSlot(); void refreshTableViewSlot(); }; #endif // WORKERMANAGE_H有注释版
cpp// ============================================================ // 文件:workermanage.h // 功能:工作人员管理界面的头文件声明 // 说明:工作人员登录后的主界面,包含业主管理、房产管理、 // 车位管理、缴费管理、请假管理等功能 // ============================================================ #ifndef WORKERMANAGE_H // 作用:防止头文件被多次包含(Include Guard) #define WORKERMANAGE_H // 定义宏 WORKERMANAGE_H // ============================================================ // 头文件包含 // ============================================================ #include <QMainWindow> // 包含 QMainWindow 基类 // 提供菜单栏、工具栏、状态栏等主窗口功能 #include <QTableView> // 包含 QTableView 类 // 用于以表格形式显示数据 #include <QSqlTableModel> // 包含 QSqlTableModel 类 // 用于与数据库表交互,支持增删改查操作 #include <QLabel> // 包含 QLabel 类 // 用于显示文本标签 #include <QDebug> // 包含 QDebug 类 // 用于输出调试信息到控制台 #include <QSqlError> // 包含 QSqlError 类 // 用于获取数据库操作失败时的错误信息 #include <QString> // 包含 QString 类 // Qt 的字符串类 // ============================================================ // 包含其他功能模块的头文件 // ============================================================ #include "ownerinfo.h" // 业主信息登记模块 #include "houseinfo.h" // 房产信息登记模块 #include "carstationinfo.h" // 车位信息录入模块 #include "workerfree.h" // 员工请假模块 #include "setowner.h" // 设置业主模块 #include "pricemanage.h" // 价格维护模块 #include "paymanage.h" // 缴费管理模块 // ============================================================ // UI 命名空间声明 // ============================================================ namespace Ui { class WorkerManage; // 声明 UI 类 // 这个类由 Qt 的 uic 工具根据 workermanage.ui 文件自动生成 } // ============================================================ // WorkerManage 类定义 // 工作人员管理主窗口,继承自 QMainWindow // 工作人员登录后的主界面 // ============================================================ class WorkerManage : public QMainWindow // class WorkerManage : 定义一个名为 WorkerManage 的类 // public QMainWindow : 公有继承自 QMainWindow 基类 { Q_OBJECT // Qt 元对象宏 // 启用信号槽机制、运行时类型信息等 public: // ============================================================ // public 区域:对外公开的接口 // ============================================================ explicit WorkerManage(QWidget *parent = 0); // 构造函数 // explicit: 防止隐式类型转换 ~WorkerManage(); // 析构函数 private: // ============================================================ // private 区域:私有的成员变量 // ============================================================ Ui::WorkerManage *ui; // UI 对象指针 // 指向由 uic 工具生成的 UI 类对象 // ============================================================ // 界面核心组件 // ============================================================ QLabel *lable; // 标签对象指针 // 用于显示提示信息或状态信息 QTableView *workerTableView; // 表格视图对象指针 // 用于以表格形式显示各种数据 QSqlTableModel *workerModel; // SQL 表格模型对象指针 // 用于与数据库表交互 // ============================================================ // 功能模块窗口指针 // ============================================================ OwnerInfo *ownerInfo; // 业主登记窗口指针 // 用于添加或编辑业主信息 HouseInfo *houseInfo; // 房产登记窗口指针 // 用于添加或编辑房屋信息 CarStationInfo *carStationInfo; // 录入车位信息窗口指针 // 用于添加或编辑车位信息 PriceManage *pricemanage; // 价格维护窗口指针 // 用于设置各项收费标准 PayManage *paymanage; // 缴费管理窗口指针 // 用于管理缴费记录 WorkerFree *workFree; // 请假管理窗口指针 // 用于提交请假申请 SetOwner *owner; // 设置业主窗口指针 // 用于为业主分配房屋 // ============================================================ // 状态标志 // ============================================================ int workerManageStatus; // 工作人员管理状态标志 // 用于指示用户当前进行的操作 // // 取值含义: // 0: 系统初次进入 // 1: 已查询过业主信息 // 2: 已查询过车位信息 // 3: 已查询过故障信息 // 4: 已创建请假记录 // 5: 已查询月度出勤信息 // ============================================================ // 私有辅助函数 // ============================================================ void delCurRow(); // 删除当前选中的行 // 从表格中删除当前选中的记录 void alterCurRow(); // 修改当前选中的行 // 编辑当前选中的记录 void setTableHead(); // 设置表头 // 设置当前表格的列标题 signals: // ============================================================ // 信号区域 // ============================================================ //void EmitToManagerManage(); // 已注释:原本可能用于向管理员界面发送信号 void EmitOwnerChanged(); // 业主信息变更信号 // 当业主信息发生变化时发射此信号 private slots: // ============================================================ // 私有槽函数区域 // 响应菜单/按钮点击事件 // ============================================================ // ---------- 业主管理 ---------- void showOwnerSlot(); // 业主查询槽函数 // 显示所有业主信息 void addOwnerSlot(); // 业主登记槽函数 // 打开业主登记窗口 void alterOwnerSlot(); // 业主修改槽函数 // 修改当前选中的业主信息 void delOwnerSlot(); // 删除业主槽函数 // 删除当前选中的业主 // ---------- 房产管理 ---------- void addHouseSlot(); // 房产登记槽函数 // 打开房产登记窗口 // ---------- 车位管理 ---------- void showCarStationSlot(); // 查看车位信息槽函数 // 显示所有车位信息 void addCarStationSlot(); // 录入车位信息槽函数 // 打开录入车位信息窗口 void alterCarStationSlot(); // 修改车位信息槽函数 // 修改当前选中的车位信息 void delCarStationSlot(); // 删除车位信息槽函数 // 删除当前选中的车位 void carStationRentActSlot(); // 车位出租槽函数 // 将车位出租给业主 // ---------- 缴费管理 ---------- void priceManageSlot(); // 价格维护槽函数 // 打开价格维护窗口 void payInfoSlot(); // 缴费查询槽函数 // 显示所有缴费记录 void paySlot(); // 缴费槽函数 // 执行缴费操作 // ---------- 故障管理 ---------- void issueShowSlot(); // 故障查询槽函数 // 显示所有故障报修记录 void issueRepairSlot(); // 故障维修槽函数 // 处理故障维修 // ---------- 考勤管理 ---------- void freeSlot(); // 请假槽函数 // 打开请假申请窗口 void freeConfirmSlot(); // 销假槽函数 // 确认请假结束 void attendSlot(); // 月度出勤槽函数 // 查看月度出勤统计 // ---------- 其他 ---------- void refreshTableViewSlot(); // 刷新表格视图槽函数 // 定义为空,待实现 }; #endif // WORKERMANAGE_H // 结束条件编译块10.workermanage.cpp
原始版本一
cpp#include "workermanage.h" #include "ui_workermanage.h" /*********:WorkerManage类构造函数***********************************/ WorkerManage::WorkerManage(QWidget *parent) : QMainWindow(parent), ui(new Ui::WorkerManage) { ui->setupUi(this); ui->toolBar->setIconSize(QSize(50,50)); //设置工具栏图标的大小 lable=new QLabel; //新建标签对象赋值给指针 setCentralWidget(lable); //设置该指针为窗口中心部件 //该标签用于在主窗口显示一个图片,但实际运行不起来....................................................问题是?? QImage *img=new QImage; //创建图像编辑对象的一个指针 img->load("/image/show.png"); //载入本地图像文件 lable->clear(); //清空标签 lable->setPixmap(QPixmap::fromImage(*img)); //先转换图片为像素图,然后加载图像到Label标签 lable->show(); //显示标签 workerTableView=new QTableView; //新建表格视图对象赋值给指针 setCentralWidget(workerTableView); //设置表格视图为中心部件 workerModel=new QSqlTableModel(this); //创建表格模型对象的一个指针,指向默认数据库 workerModel->setEditStrategy(QSqlTableModel::OnManualSubmit); //设置SQL表格模型编辑策略:数据改变先缓存,直到调用提交 //owner=new SetOwner; //setCentralWidget(owner); workerManageStatus=0; //标定1,表示第一次进入系统 connect(ui->showOwnerAct, SIGNAL(triggered()), this, SLOT(showOwnerSlot())); //"业主查询"按键的"点击信号"与业主查询槽函数连接 connect(ui->addOwnerAct, SIGNAL(triggered()), this, SLOT(addOwnerSlot())); //"成员登记"按键的"点击信号"与成员登记槽函数连接 connect(ui->alterOwnerAct,SIGNAL(triggered(bool)),this,SLOT(alterOwnerSlot())); //"业主修改"按键的"点击信号"与业主修改槽函数连接 connect(ui->delOwnerAct, SIGNAL(triggered()), this, SLOT(delOwnerSlot())); //"删除业主"按键的"点击信号"与删除业主槽函数连接 connect(ui->addHouseAct, SIGNAL(triggered()), this, SLOT(addHouseSlot())); //"房产登记"按键的"点击信号"与房产等级槽函数连接 connect(ui->showCarStationAct, SIGNAL(triggered()), this, SLOT(showCarStationSlot())); //"查看车位信息"按键的"点击信息"与查看车位信息槽函数连接 connect(ui->addCarStationAct,SIGNAL(triggered()),this,SLOT(addCarStationSlot())); //"录入车位信息"按键的"点击信息"与录入车位信息槽函数连接 connect(ui->alterCarStationAct,SIGNAL(triggered()),this,SLOT(alterCarStationSlot())); //"修改车位信息"按键的"点击信息"与修改车位信息槽函数连接 connect(ui->delCarStationAct,SIGNAL(triggered()),this,SLOT(delCarStationSlot())); //"删除车位信息"按键的"点击信息"与删除车位信息槽函数连接 connect(ui->carStationRenAct, SIGNAL(triggered()), this, SLOT(carStationRentActSlot())); //connect(ui->houseInfoAct, SIGNAL(triggered()), this, SLOT(houseInfoSlot())); connect(ui->priceManageAct, SIGNAL(triggered()), this, SLOT(priceManageSlot()));//"价格维护"按键的"点击信息"与价格维护槽函数连接 connect(ui->payInfoAct, SIGNAL(triggered()), this, SLOT(payInfoSlot())); //"缴费查询"按键的"点击信息"与缴费查询槽函数连接 connect(ui->payAct, SIGNAL(triggered()), this, SLOT(paySlot())); //"缴费"按键的"点击信息"与缴费槽函数连接 connect(ui->issueShowAct,SIGNAL(triggered(bool)),this,SLOT(issueShowSlot())); //"故障查询"按键的"点击信息"与故障查询槽函数连接 connect(ui->issueRepairAct,SIGNAL(triggered(bool)),this,SLOT(issueRepairSlot()));//"故障维修"按键的"点击信息"与故障维修槽函数连接 connect(ui->freeAct, SIGNAL(triggered()), this, SLOT(freeSlot())); //"请假"按键的"点击信息"与请假槽函数连接 connect(ui->freeConfirmAct, SIGNAL(triggered()), this, SLOT(freeConfirmSlot()));//"销假"按键的"点击信息"与销假槽函数连接 connect(ui->attendAct, SIGNAL(triggered()), this, SLOT(attendSlot())); //"月度出勤"按键的"点击信息"与月度出勤槽函数连接 //connect(this,SIGNAL(EmitWorkerChanged()),this,SLOT(refreshTableViewSlot())); //connect(workerInfo,SIGNAL(EmitWorkerChanged()),this,SLOT(refreshTableViewSlot())); } WorkerManage::~WorkerManage() { delete ui; } /*********《槽函数》业主查询函数***********************************/ void WorkerManage::showOwnerSlot() { workerManageStatus=1; //标定1,业主查询动作已经完成 workerModel->setTable("houseowner"); //设置查询的表格为"houseowner" workerModel->setHeaderData(0,Qt::Horizontal,tr("业主姓名"));//设置显示的0号字段,最左边位置 workerModel->setHeaderData(1,Qt::Horizontal,tr("业主密码")); workerModel->setHeaderData(2,Qt::Horizontal,tr("地址")); workerModel->setHeaderData(3,Qt::Horizontal,tr("电话")); workerModel->select(); //进行数据查询 workerTableView->setModel(workerModel); //数据显示 } /*********《槽函数》业主信息登记函数***********************************/ void WorkerManage::addOwnerSlot() { if(workerManageStatus==1) //如果已经查询过业主信息,则允许登记成员 { ownerInfo=new OwnerInfo;//创建业主信息登记对象 ownerInfo->show(); //显示登记界面 } } /*********《槽函数》业主修改函数***********************************/ void WorkerManage::alterOwnerSlot() { if(workerManageStatus==1)//如果已经查询过业主信息,则允许修改成员 { alterCurRow(); //修改当前行数据 } } /*********《槽函数》删除业主函数***********************************/ void WorkerManage::delOwnerSlot() { if(workerManageStatus==1)//如果已经查询过业主信息,则允许删除成员 { delCurRow(); //删除当前行数据 } } /*********《槽函数》房产登记函数***********************************/ void WorkerManage::addHouseSlot() { houseInfo=new HouseInfo; //创建房产信息对象 houseInfo->show(); //显示房产登记界面 } /*********《槽函数》查看车位信息函数***********************************/ void WorkerManage::showCarStationSlot() { workerManageStatus=2; //标定2,表示已经查询过车位信息 workerModel->setTable("carstation"); //设置查询的表格为"carstation" workerModel->select(); //进行数据查询 workerModel->setHeaderData(0,Qt::Horizontal,tr("车位号")); //设置显示的0号字段,最左边位置 workerModel->setHeaderData(1,Qt::Horizontal,tr("地上/地下")); workerModel->setHeaderData(2,Qt::Horizontal,tr("大/小")); workerModel->setHeaderData(3,Qt::Horizontal,tr("能否充电")); workerModel->setHeaderData(4,Qt::Horizontal,tr("所属业主")); workerModel->setHeaderData(5,Qt::Horizontal,tr("缴费状态")); workerTableView->setModel(workerModel); } /*********《槽函数》录入车位信息********************************/ void WorkerManage::addCarStationSlot() { if(workerManageStatus==2) //如果已经查看过车位信息 { carStationInfo=new CarStationInfo; //创建添加车位信息对象 carStationInfo->show(); //显示窗口 } } /*********《槽函数》删除车位信息********************************/ void WorkerManage::delCarStationSlot() { if(workerManageStatus==2) //如果已经查看过车位信息 { delCurRow(); //删除当前行车位信息 } } /*********《槽函数》修改车位信息********************************/ void WorkerManage::alterCarStationSlot() { if(workerManageStatus==2) //如果已经查看过车位信息 { alterCurRow();//修改当前行 } } /*********《槽函数》车位出租信息函数***********************************/ void WorkerManage::carStationRentActSlot() { if(workerManageStatus == 2) //如果车位信息已经查询显示过了 { workerModel->setTable("carstation"); //设置查询的表格为"carstation" workerModel->setFilter("ownername is null ");//设置过滤器,如果"ownername"字段为空,说明没人租,则显示 workerModel->select(); //数据查询 workerTableView->setModel(workerModel); //显示出局 } } /*********《槽函数》价格维护函数***********************************/ void WorkerManage::priceManageSlot() { pricemanage=new PriceManage; //创建价格维护对象 pricemanage->show(); //显示 } /*********《槽函数》缴费查询函数***********************************/ void WorkerManage::payInfoSlot() { workerModel->setTable("priceRecord"); //设置查询的表格为"priceRecord" workerModel->select(); workerModel->setHeaderData(0,Qt::Horizontal,tr("缴费人")); workerModel->setHeaderData(1,Qt::Horizontal,tr("缴费类型")); workerModel->setHeaderData(2,Qt::Horizontal,tr("缴费金额")); workerModel->setHeaderData(3,Qt::Horizontal,tr("缴费时间")); workerTableView->setModel(workerModel); } /*********《槽函数》缴费函数***********************************/ void WorkerManage::paySlot() { paymanage=new PayManage; paymanage->show(); } /*********《槽函数》故障查询函数********************************/ void WorkerManage::issueShowSlot() { workerManageStatus=3; //标记3,表示已查询过故障信息 workerModel->setTable("errorinfo"); //设置查询的表格为"errorinfo" workerModel->select(); workerModel->setHeaderData(0,Qt::Horizontal,tr("故障编号")); workerModel->setHeaderData(1,Qt::Horizontal,tr("报修人")); workerModel->setHeaderData(2,Qt::Horizontal,tr("故障信息")); workerModel->setHeaderData(3,Qt::Horizontal,tr("报修时间")); workerModel->setHeaderData(4,Qt::Horizontal,tr("报修状态")); workerModel->setHeaderData(5,Qt::Horizontal,tr("处理时间")); workerTableView->setModel(workerModel); } /*********《槽函数》故障维修函数********************************/ void WorkerManage::issueRepairSlot() { if(workerManageStatus==3)//如果已经查询了故障信息 { alterCurRow(); //修改当前行 } } /*********《槽函数》请假函数********************************/ void WorkerManage::freeSlot() { workerManageStatus=4; //标记4,表示已经创建请假 workFree=new WorkerFree;//创建请假对象 workFree->show(); //显示 } /*********《槽函数》请假审批函数********************************/ void WorkerManage::freeConfirmSlot() { if(workerManageStatus==4) //如果已创建请假 { QString name = this->windowTitle(); workerModel->setTable("workerattend"); workerModel->setFilter(QString("worknum= '%1'and freeact ='未销假'").arg(name)); setTableHead(); //设置SQL表格模型字段并显示 } } /*********《槽函数》月度出勤函数********************************/ void WorkerManage::attendSlot() { workerManageStatus=5;//标记5,表示已查看月度出勤 QString name = this->windowTitle(); workerModel->setTable("workerattend"); workerModel->setFilter(QString("workernum= '%1'").arg(name)); setTableHead(); //设置SQL表格模型字段并显示 } /*********《槽函数》刷新视图函数,未使用************************/ void WorkerManage::refreshTableViewSlot() { } /*********删除当前行数据函数***********************************/ void WorkerManage::delCurRow() { int curRow=workerTableView->currentIndex().row(); //获取当前鼠标行 workerModel->removeRow(curRow); //删除当前行 int ok=QMessageBox::warning(this,tr("删除当前信息") //显示警告信息窗口 ,tr("你确定删除此信息吗?"),QMessageBox::Yes,QMessageBox::No); if(ok==QMessageBox::No) //如果点击"No"按键 { workerModel->revertAll(); //恢复数据 } else //如果点击"Yes"按键 { workerModel->submitAll(); //提交数据 } } /*********修改当前行数据函数***********************************/ void WorkerManage::alterCurRow() { workerModel->database().transaction(); //启动并判断是否支持事务 if(workerModel->submitAll()) //提交所有数据到缓存 { workerModel->database().commit(); //正式提交数据到数据库 } else //提交失败 { workerModel->database().rollback();//数据回滚 //创建警告信息窗口,并输出信息 QMessageBox::warning(this,tr("tabalModel"), tr("数据库错误:% 1").arg(workerModel->lastError().text())); } } /*********设置表格模型的字段函数***********************************/ void WorkerManage::setTableHead() { workerModel->setHeaderData(0,Qt::Horizontal,tr("员工账号")); workerModel->setHeaderData(1,Qt::Horizontal,tr("请假/出勤")); workerModel->setHeaderData(2,Qt::Horizontal,tr("请假/出勤时间")); workerModel->setHeaderData(3,Qt::Horizontal,tr("请假理由")); workerModel->setHeaderData(4,Qt::Horizontal,tr("是否销假")); workerModel->setHeaderData(5,Qt::Horizontal,tr("销假时间")); workerModel->setHeaderData(6,Qt::Horizontal,tr("是否批准")); workerModel->select(); workerTableView->setModel(workerModel); }修复版本二
无注释版
cpp#include "workermanage.h" #include "ui_workermanage.h" WorkerManage::WorkerManage(QWidget *parent) : QMainWindow(parent), ui(new Ui::WorkerManage) { ui->setupUi(this); ui->toolBar->setIconSize(QSize(50, 50)); lable = new QLabel; setCentralWidget(lable); QImage *img = new QImage; img->load("/image/show.png"); lable->clear(); lable->setPixmap(QPixmap::fromImage(*img)); lable->show(); workerTableView = new QTableView; setCentralWidget(workerTableView); workerModel = new QSqlTableModel(this); workerModel->setEditStrategy(QSqlTableModel::OnManualSubmit); workerManageStatus = 0; connect(ui->showOwnerAct, SIGNAL(triggered()), this, SLOT(showOwnerSlot())); connect(ui->addOwnerAct, SIGNAL(triggered()), this, SLOT(addOwnerSlot())); connect(ui->alterOwnerAct, SIGNAL(triggered(bool)), this, SLOT(alterOwnerSlot())); connect(ui->delOwnerAct, SIGNAL(triggered()), this, SLOT(delOwnerSlot())); connect(ui->addHouseAct, SIGNAL(triggered()), this, SLOT(addHouseSlot())); connect(ui->showCarStationAct, SIGNAL(triggered()), this, SLOT(showCarStationSlot())); connect(ui->addCarStationAct, SIGNAL(triggered()), this, SLOT(addCarStationSlot())); connect(ui->alterCarStationAct, SIGNAL(triggered()), this, SLOT(alterCarStationSlot())); connect(ui->delCarStationAct, SIGNAL(triggered()), this, SLOT(delCarStationSlot())); connect(ui->carStationRenAct, SIGNAL(triggered()), this, SLOT(carStationRentActSlot())); connect(ui->priceManageAct, SIGNAL(triggered()), this, SLOT(priceManageSlot())); connect(ui->payInfoAct, SIGNAL(triggered()), this, SLOT(payInfoSlot())); connect(ui->payAct, SIGNAL(triggered()), this, SLOT(paySlot())); connect(ui->issueShowAct, SIGNAL(triggered(bool)), this, SLOT(issueShowSlot())); connect(ui->issueRepairAct, SIGNAL(triggered(bool)), this, SLOT(issueRepairSlot())); connect(ui->freeAct, SIGNAL(triggered()), this, SLOT(freeSlot())); connect(ui->freeConfirmAct, SIGNAL(triggered()), this, SLOT(freeConfirmSlot())); connect(ui->attendAct, SIGNAL(triggered()), this, SLOT(attendSlot())); } WorkerManage::~WorkerManage() { delete ui; } void WorkerManage::showOwnerSlot() { workerManageStatus = 1; workerModel->setTable("houseowner"); workerModel->setHeaderData(0, Qt::Horizontal, tr("业主姓名")); workerModel->setHeaderData(1, Qt::Horizontal, tr("业主密码")); workerModel->setHeaderData(2, Qt::Horizontal, tr("地址")); workerModel->setHeaderData(3, Qt::Horizontal, tr("电话")); workerModel->select(); workerTableView->setModel(workerModel); } void WorkerManage::addOwnerSlot() { if (workerManageStatus == 1) { ownerInfo = new OwnerInfo; ownerInfo->show(); } } void WorkerManage::alterOwnerSlot() { if (workerManageStatus == 1) { alterCurRow(); } } void WorkerManage::delOwnerSlot() { if (workerManageStatus == 1) { delCurRow(); } } void WorkerManage::addHouseSlot() { houseInfo = new HouseInfo; houseInfo->show(); } void WorkerManage::showCarStationSlot() { workerManageStatus = 2; workerModel->setTable("carstation"); workerModel->select(); workerModel->setHeaderData(0, Qt::Horizontal, tr("车位号")); workerModel->setHeaderData(1, Qt::Horizontal, tr("地上/地下")); workerModel->setHeaderData(2, Qt::Horizontal, tr("大/小")); workerModel->setHeaderData(3, Qt::Horizontal, tr("能否充电")); workerModel->setHeaderData(4, Qt::Horizontal, tr("所属业主")); workerModel->setHeaderData(5, Qt::Horizontal, tr("缴费状态")); workerTableView->setModel(workerModel); } void WorkerManage::addCarStationSlot() { if (workerManageStatus == 2) { carStationInfo = new CarStationInfo; carStationInfo->show(); } } void WorkerManage::delCarStationSlot() { if (workerManageStatus == 2) { delCurRow(); } } void WorkerManage::alterCarStationSlot() { if (workerManageStatus == 2) { alterCurRow(); } } void WorkerManage::carStationRentActSlot() { if (workerManageStatus == 2) { workerModel->setTable("carstation"); workerModel->setFilter("ownername is null"); workerModel->select(); workerTableView->setModel(workerModel); } } void WorkerManage::priceManageSlot() { pricemanage = new PriceManage; pricemanage->show(); } void WorkerManage::payInfoSlot() { workerModel->setTable("priceRecord"); workerModel->select(); workerModel->setHeaderData(0, Qt::Horizontal, tr("缴费人")); workerModel->setHeaderData(1, Qt::Horizontal, tr("缴费类型")); workerModel->setHeaderData(2, Qt::Horizontal, tr("缴费金额")); workerModel->setHeaderData(3, Qt::Horizontal, tr("缴费时间")); workerTableView->setModel(workerModel); } void WorkerManage::paySlot() { paymanage = new PayManage; paymanage->show(); } void WorkerManage::issueShowSlot() { workerManageStatus = 3; workerModel->setTable("errorinfo"); workerModel->select(); workerModel->setHeaderData(0, Qt::Horizontal, tr("故障编号")); workerModel->setHeaderData(1, Qt::Horizontal, tr("报修人")); workerModel->setHeaderData(2, Qt::Horizontal, tr("故障信息")); workerModel->setHeaderData(3, Qt::Horizontal, tr("报修时间")); workerModel->setHeaderData(4, Qt::Horizontal, tr("报修状态")); workerModel->setHeaderData(5, Qt::Horizontal, tr("处理时间")); workerTableView->setModel(workerModel); } void WorkerManage::issueRepairSlot() { if (workerManageStatus == 3) { alterCurRow(); } } void WorkerManage::freeSlot() { workerManageStatus = 4; workFree = new WorkerFree; workFree->show(); } void WorkerManage::freeConfirmSlot() { if (workerManageStatus == 4) { QString name = this->windowTitle(); workerModel->setTable("workerattend"); workerModel->setFilter(QString("worknum= '%1' and freeact ='未销假'").arg(name)); setTableHead(); } } void WorkerManage::attendSlot() { workerManageStatus = 5; QString name = this->windowTitle(); workerModel->setTable("workerattend"); workerModel->setFilter(QString("workernum= '%1'").arg(name)); setTableHead(); } void WorkerManage::refreshTableViewSlot() { } void WorkerManage::delCurRow() { int curRow = workerTableView->currentIndex().row(); workerModel->removeRow(curRow); int ok = QMessageBox::warning(this, tr("删除当前信息"), tr("你确定删除此信息吗?"), QMessageBox::Yes, QMessageBox::No); if (ok == QMessageBox::No) { workerModel->revertAll(); } else { workerModel->submitAll(); } } void WorkerManage::alterCurRow() { workerModel->database().transaction(); if (workerModel->submitAll()) { workerModel->database().commit(); } else { workerModel->database().rollback(); QMessageBox::warning(this, tr("tabalModel"), tr("数据库错误:% 1").arg(workerModel->lastError().text())); } } void WorkerManage::setTableHead() { workerModel->setHeaderData(0, Qt::Horizontal, tr("员工账号")); workerModel->setHeaderData(1, Qt::Horizontal, tr("请假/出勤")); workerModel->setHeaderData(2, Qt::Horizontal, tr("请假/出勤时间")); workerModel->setHeaderData(3, Qt::Horizontal, tr("请假理由")); workerModel->setHeaderData(4, Qt::Horizontal, tr("是否销假")); workerModel->setHeaderData(5, Qt::Horizontal, tr("销假时间")); workerModel->setHeaderData(6, Qt::Horizontal, tr("是否批准")); workerModel->select(); workerTableView->setModel(workerModel); }有注释版
cpp// ============================================================ // 文件:workermanage.cpp // 功能:工作人员管理界面的实现 // 说明:工作人员登录后的主界面,包含业主管理、房产管理、 // 车位管理、缴费管理、故障管理、考勤管理等功能 // ============================================================ #include "workermanage.h" // 包含自己的头文件声明 // 让编译器知道类 WorkerManage 的结构、成员函数和成员变量 #include "ui_workermanage.h" // 包含由 .ui 文件生成的 UI 类头文件 // 包含了 Ui::WorkerManage 类的定义,其中有所有控件的指针 // ============================================================ // 构造函数 - 初始化工作人员管理界面 // 参数:parent - 父窗口指针,默认 nullptr // 当工作人员登录成功后,此对象被创建 // ============================================================ WorkerManage::WorkerManage(QWidget *parent) : QMainWindow(parent), // 调用父类 QMainWindow 的构造函数,传入父窗口指针 ui(new Ui::WorkerManage) // 创建 UI 对象(由 Qt Designer 生成的界面类) { ui->setupUi(this); // setupUi() 加载 .ui 文件,创建所有控件并设置布局 ui->toolBar->setIconSize(QSize(50, 50)); // 设置工具栏中图标的大小为 50x50 像素 // -------------------------------------------------------- // 尝试在标签中显示图片(但实际运行不起来) // -------------------------------------------------------- lable = new QLabel; // 创建标签对象 setCentralWidget(lable); // 设置标签为中心部件(临时) // 该标签用于在主窗口显示一个图片,但实际运行不起来 QImage *img = new QImage; // 创建图像对象 // ⚠️ 问题:没有设置父对象,可能导致内存泄漏 img->load("/image/show.png"); // 载入本地图像文件 // ⚠️ 问题:路径错误,应该是相对路径或资源路径 lable->clear(); // 清空标签 lable->setPixmap(QPixmap::fromImage(*img)); // 将图像转换为像素图并设置到标签 lable->show(); // 显示标签 // -------------------------------------------------------- // 创建表格视图作为中央部件 // -------------------------------------------------------- workerTableView = new QTableView; // 创建表格视图对象 setCentralWidget(workerTableView); // 设置表格视图为中心部件(覆盖了之前的标签) // -------------------------------------------------------- // 创建数据模型 // -------------------------------------------------------- workerModel = new QSqlTableModel(this); // 创建 SQL 表格模型,设置父对象为 this(自动内存管理) workerModel->setEditStrategy(QSqlTableModel::OnManualSubmit); // 设置编辑策略为"手动提交" // 修改后需要调用 submitAll() 才会保存到数据库 // owner = new SetOwner; // setCentralWidget(owner); // 已注释:原本可能显示设置业主窗口 workerManageStatus = 0; // 标定1,表示第一次进入系统 // -------------------------------------------------------- // 信号槽连接(Qt 4 旧语法) // 连接菜单/工具栏按钮的 triggered 信号到对应的槽函数 // ⚠️ 问题:使用 Qt 4 旧语法,建议升级到 Qt 5 新语法 // -------------------------------------------------------- // ---------- 业主管理 ---------- connect(ui->showOwnerAct, SIGNAL(triggered()), this, SLOT(showOwnerSlot())); // "业主查询"按键 → 业主查询槽函数 connect(ui->addOwnerAct, SIGNAL(triggered()), this, SLOT(addOwnerSlot())); // "成员登记"按键 → 成员登记槽函数 connect(ui->alterOwnerAct, SIGNAL(triggered(bool)), this, SLOT(alterOwnerSlot())); // "业主修改"按键 → 业主修改槽函数 connect(ui->delOwnerAct, SIGNAL(triggered()), this, SLOT(delOwnerSlot())); // "删除业主"按键 → 删除业主槽函数 connect(ui->addHouseAct, SIGNAL(triggered()), this, SLOT(addHouseSlot())); // "房产登记"按键 → 房产登记槽函数 // ---------- 车位管理 ---------- connect(ui->showCarStationAct, SIGNAL(triggered()), this, SLOT(showCarStationSlot())); // "查看车位信息"按键 → 查看车位信息槽函数 connect(ui->addCarStationAct, SIGNAL(triggered()), this, SLOT(addCarStationSlot())); // "录入车位信息"按键 → 录入车位信息槽函数 connect(ui->alterCarStationAct, SIGNAL(triggered()), this, SLOT(alterCarStationSlot())); // "修改车位信息"按键 → 修改车位信息槽函数 connect(ui->delCarStationAct, SIGNAL(triggered()), this, SLOT(delCarStationSlot())); // "删除车位信息"按键 → 删除车位信息槽函数 connect(ui->carStationRenAct, SIGNAL(triggered()), this, SLOT(carStationRentActSlot())); // "车位出租"按键 → 车位出租槽函数 // ---------- 缴费管理 ---------- connect(ui->priceManageAct, SIGNAL(triggered()), this, SLOT(priceManageSlot())); // "价格维护"按键 → 价格维护槽函数 connect(ui->payInfoAct, SIGNAL(triggered()), this, SLOT(payInfoSlot())); // "缴费查询"按键 → 缴费查询槽函数 connect(ui->payAct, SIGNAL(triggered()), this, SLOT(paySlot())); // "缴费"按键 → 缴费槽函数 // ---------- 故障管理 ---------- connect(ui->issueShowAct, SIGNAL(triggered(bool)), this, SLOT(issueShowSlot())); // "故障查询"按键 → 故障查询槽函数 connect(ui->issueRepairAct, SIGNAL(triggered(bool)), this, SLOT(issueRepairSlot())); // "故障维修"按键 → 故障维修槽函数 // ---------- 考勤管理 ---------- connect(ui->freeAct, SIGNAL(triggered()), this, SLOT(freeSlot())); // "请假"按键 → 请假槽函数 connect(ui->freeConfirmAct, SIGNAL(triggered()), this, SLOT(freeConfirmSlot())); // "销假"按键 → 销假槽函数 connect(ui->attendAct, SIGNAL(triggered()), this, SLOT(attendSlot())); // "月度出勤"按键 → 月度出勤槽函数 // 已注释的信号连接 // connect(this,SIGNAL(EmitWorkerChanged()),this,SLOT(refreshTableViewSlot())); // connect(workerInfo,SIGNAL(EmitWorkerChanged()),this,SLOT(refreshTableViewSlot())); } // ============================================================ // 析构函数 - 释放资源 // ============================================================ WorkerManage::~WorkerManage() { delete ui; // 删除 UI 对象,释放界面上所有控件的内存 // workerModel、workerTableView 等不需要手动 delete // 因为设置了父对象 this 或由 Qt 对象树管理 } // ============================================================ // 《槽函数》业主查询函数 // 功能:查询并显示所有业主信息 // ============================================================ void WorkerManage::showOwnerSlot() { workerManageStatus = 1; // 标定1,业主查询动作已经完成 workerModel->setTable("houseowner"); // 设置查询的表格为 "houseowner"(业主表) // 设置表头显示名称 workerModel->setHeaderData(0, Qt::Horizontal, tr("业主姓名")); // 第0列显示为"业主姓名" workerModel->setHeaderData(1, Qt::Horizontal, tr("业主密码")); // 第1列显示为"业主密码" workerModel->setHeaderData(2, Qt::Horizontal, tr("地址")); // 第2列显示为"地址" workerModel->setHeaderData(3, Qt::Horizontal, tr("电话")); // 第3列显示为"电话" workerModel->select(); // 执行查询 workerTableView->setModel(workerModel); // 将数据模型设置到表格视图 } // ============================================================ // 《槽函数》业主信息登记函数 // 功能:打开业主信息登记窗口 // ============================================================ void WorkerManage::addOwnerSlot() { if (workerManageStatus == 1) { // 如果已经查询过业主信息,则允许登记成员 ownerInfo = new OwnerInfo; // 创建业主信息登记对象 // ⚠️ 问题:没有设置父对象,可能导致内存泄漏 ownerInfo->show(); // 显示登记界面 } } // ============================================================ // 《槽函数》业主修改函数 // 功能:修改当前选中的业主信息 // ============================================================ void WorkerManage::alterOwnerSlot() { if (workerManageStatus == 1) { // 如果已经查询过业主信息,则允许修改成员 alterCurRow(); // 修改当前行数据 } } // ============================================================ // 《槽函数》删除业主函数 // 功能:删除当前选中的业主 // ============================================================ void WorkerManage::delOwnerSlot() { if (workerManageStatus == 1) { // 如果已经查询过业主信息,则允许删除成员 delCurRow(); // 删除当前行数据 } } // ============================================================ // 《槽函数》房产登记函数 // 功能:打开房产信息登记窗口 // ============================================================ void WorkerManage::addHouseSlot() { houseInfo = new HouseInfo; // 创建房产信息对象 // ⚠️ 问题:没有设置父对象,可能导致内存泄漏 houseInfo->show(); // 显示房产登记界面 } // ============================================================ // 《槽函数》查看车位信息函数 // 功能:查询并显示所有车位信息 // ============================================================ void WorkerManage::showCarStationSlot() { workerManageStatus = 2; // 标定2,表示已经查询过车位信息 workerModel->setTable("carstation"); // 设置查询的表格为 "carstation"(车位表) workerModel->select(); // 执行查询 // 设置表头 workerModel->setHeaderData(0, Qt::Horizontal, tr("车位号")); workerModel->setHeaderData(1, Qt::Horizontal, tr("地上/地下")); workerModel->setHeaderData(2, Qt::Horizontal, tr("大/小")); workerModel->setHeaderData(3, Qt::Horizontal, tr("能否充电")); workerModel->setHeaderData(4, Qt::Horizontal, tr("所属业主")); workerModel->setHeaderData(5, Qt::Horizontal, tr("缴费状态")); workerTableView->setModel(workerModel); // 将数据模型设置到表格视图 } // ============================================================ // 《槽函数》录入车位信息 // 功能:打开录入车位信息窗口 // ============================================================ void WorkerManage::addCarStationSlot() { if (workerManageStatus == 2) { // 如果已经查看过车位信息 carStationInfo = new CarStationInfo; // 创建添加车位信息对象 carStationInfo->show(); // 显示窗口 } } // ============================================================ // 《槽函数》删除车位信息 // 功能:删除当前选中的车位 // ============================================================ void WorkerManage::delCarStationSlot() { if (workerManageStatus == 2) { // 如果已经查看过车位信息 delCurRow(); // 删除当前行车位信息 } } // ============================================================ // 《槽函数》修改车位信息 // 功能:修改当前选中的车位信息 // ============================================================ void WorkerManage::alterCarStationSlot() { if (workerManageStatus == 2) { // 如果已经查看过车位信息 alterCurRow(); // 修改当前行 } } // ============================================================ // 《槽函数》车位出租信息函数 // 功能:显示空闲车位列表,用于出租 // ============================================================ void WorkerManage::carStationRentActSlot() { if (workerManageStatus == 2) { // 如果车位信息已经查询显示过了 workerModel->setTable("carstation"); // 设置查询的表格为 "carstation" workerModel->setFilter("ownername is null"); // 设置过滤器:只显示 "ownername" 字段为空的车位(无人租用) workerModel->select(); // 执行查询 workerTableView->setModel(workerModel); // 显示数据 } } // ============================================================ // 《槽函数》价格维护函数 // 功能:打开价格维护窗口 // ============================================================ void WorkerManage::priceManageSlot() { pricemanage = new PriceManage; // 创建价格维护对象 // ⚠️ 问题:没有设置父对象,可能导致内存泄漏 pricemanage->show(); // 显示 } // ============================================================ // 《槽函数》缴费查询函数 // 功能:查询并显示所有缴费记录 // ============================================================ void WorkerManage::payInfoSlot() { workerModel->setTable("priceRecord"); // 设置查询的表格为 "priceRecord"(缴费记录表) workerModel->select(); // 执行查询 // 设置表头 workerModel->setHeaderData(0, Qt::Horizontal, tr("缴费人")); workerModel->setHeaderData(1, Qt::Horizontal, tr("缴费类型")); workerModel->setHeaderData(2, Qt::Horizontal, tr("缴费金额")); workerModel->setHeaderData(3, Qt::Horizontal, tr("缴费时间")); workerTableView->setModel(workerModel); // 将数据模型设置到表格视图 } // ============================================================ // 《槽函数》缴费函数 // 功能:打开缴费管理窗口 // ============================================================ void WorkerManage::paySlot() { paymanage = new PayManage; // 创建缴费管理对象 // ⚠️ 问题:没有设置父对象,可能导致内存泄漏 paymanage->show(); // 显示 } // ============================================================ // 《槽函数》故障查询函数 // 功能:查询并显示所有故障报修记录 // ============================================================ void WorkerManage::issueShowSlot() { workerManageStatus = 3; // 标记3,表示已查询过故障信息 workerModel->setTable("errorinfo"); // 设置查询的表格为 "errorinfo"(故障信息表) workerModel->select(); // 执行查询 // 设置表头 workerModel->setHeaderData(0, Qt::Horizontal, tr("故障编号")); workerModel->setHeaderData(1, Qt::Horizontal, tr("报修人")); workerModel->setHeaderData(2, Qt::Horizontal, tr("故障信息")); workerModel->setHeaderData(3, Qt::Horizontal, tr("报修时间")); workerModel->setHeaderData(4, Qt::Horizontal, tr("报修状态")); workerModel->setHeaderData(5, Qt::Horizontal, tr("处理时间")); workerTableView->setModel(workerModel); // 将数据模型设置到表格视图 } // ============================================================ // 《槽函数》故障维修函数 // 功能:修改当前选中的故障记录(更新维修状态) // ============================================================ void WorkerManage::issueRepairSlot() { if (workerManageStatus == 3) { // 如果已经查询了故障信息 alterCurRow(); // 修改当前行 } } // ============================================================ // 《槽函数》请假函数 // 功能:打开请假申请窗口 // ============================================================ void WorkerManage::freeSlot() { workerManageStatus = 4; // 标记4,表示已经创建请假 workFree = new WorkerFree; // 创建请假对象 // ⚠️ 问题:没有设置父对象,可能导致内存泄漏 workFree->show(); // 显示 } // ============================================================ // 《槽函数》请假审批函数(销假) // 功能:查询并显示未销假的请假记录 // ============================================================ void WorkerManage::freeConfirmSlot() { if (workerManageStatus == 4) { // 如果已创建请假 QString name = this->windowTitle(); // 获取当前工作人员姓名 workerModel->setTable("workerattend"); // 设置查询的表格为 "workerattend"(考勤表) workerModel->setFilter(QString("worknum= '%1' and freeact ='未销假'").arg(name)); // 过滤条件:当前员工 + 未销假 // ⚠️ SQL 注入风险 setTableHead(); // 设置表头并显示 } } // ============================================================ // 《槽函数》月度出勤函数 // 功能:查询并显示当前员工的月度出勤记录 // ============================================================ void WorkerManage::attendSlot() { workerManageStatus = 5; // 标记5,表示已查看月度出勤 QString name = this->windowTitle(); // 获取当前工作人员姓名 workerModel->setTable("workerattend"); // 设置查询的表格为 "workerattend" workerModel->setFilter(QString("workernum= '%1'").arg(name)); // 过滤条件:当前员工 // ⚠️ SQL 注入风险 setTableHead(); // 设置表头并显示 } // ============================================================ // 《槽函数》刷新视图函数(未使用) // ============================================================ void WorkerManage::refreshTableViewSlot() { // 空函数,待实现 } // ============================================================ // 删除当前行数据函数 // 功能:删除表格中当前选中的行 // ============================================================ void WorkerManage::delCurRow() { int curRow = workerTableView->currentIndex().row(); // 获取当前选中的行索引 workerModel->removeRow(curRow); // 从模型中移除该行(内存操作) int ok = QMessageBox::warning(this, tr("删除当前信息"), tr("你确定删除此信息吗?"), QMessageBox::Yes, QMessageBox::No); // 弹出确认对话框 if (ok == QMessageBox::No) { // 如果用户点击"否" workerModel->revertAll(); // 恢复数据(撤销删除) } else { // 如果用户点击"是" workerModel->submitAll(); // 提交数据到数据库(确认删除) } } // ============================================================ // 修改当前行数据函数 // 功能:提交当前表格的修改到数据库 // ============================================================ void WorkerManage::alterCurRow() { workerModel->database().transaction(); // 启动事务 if (workerModel->submitAll()) { // 提交所有数据到缓存 workerModel->database().commit(); // 正式提交数据到数据库 } else { // 提交失败 workerModel->database().rollback(); // 数据回滚 QMessageBox::warning(this, tr("tabalModel"), tr("数据库错误:% 1").arg(workerModel->lastError().text())); // 显示错误信息 // ⚠️ 问题:标题 "tabalModel" 拼写错误,应为 "TableModel" } } // ============================================================ // 设置表格模型的字段函数 // 功能:设置考勤表的表头并显示数据 // ============================================================ void WorkerManage::setTableHead() { workerModel->setHeaderData(0, Qt::Horizontal, tr("员工账号")); workerModel->setHeaderData(1, Qt::Horizontal, tr("请假/出勤")); workerModel->setHeaderData(2, Qt::Horizontal, tr("请假/出勤时间")); workerModel->setHeaderData(3, Qt::Horizontal, tr("请假理由")); workerModel->setHeaderData(4, Qt::Horizontal, tr("是否销假")); workerModel->setHeaderData(5, Qt::Horizontal, tr("销假时间")); workerModel->setHeaderData(6, Qt::Horizontal, tr("是否批准")); workerModel->select(); // 执行查询 workerTableView->setModel(workerModel); // 将数据模型设置到表格视图 }10.workermanage.ui
连接数据库
在vscode里打开.dbSQLite 数据库文件
下载安装扩展
选择打开编辑器的方式为SQLite Viewer
找到数据库后还要连接数据库,即把数据库配置到正确位置
我的数据库原来在这个路径下
cppD:\重要文件\资料\技术\c++\IntelligentCommunity-2但是程序找的数据库在这个路径下
cppD:\重要文件\资料\技术\c++\IntelligentCommunity-2\build\Desktop_Qt_6_10_3_MinGW_64_bit_Debug\debug\IntelligentCommunity.db因此需要把数据库复制到该路径下
然后就有记录了
项目整体架构图
cpp┌─────────────────────────────────────────────────────────────────────┐ │ IntelligentCommunity 智慧社区管理系统 │ ├─────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────┐ │ │ │ 登录界面 (LoginDialog) │ │ │ │ 用户名 + 密码 + 角色选择 │ │ │ └──────────────────────┬──────────────────────────────────────┘ │ │ │ 登录成功 │ │ ┌───────────────┼───────────────┐ │ │ ▼ ▼ ▼ │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ 管理员界面 │ │ 工作人员 │ │ 业主界面 │ │ │ │Manager │ │ 界面 │ │Owner │ │ │ │Manage │ │Worker │ │Manage │ │ │ │ │ │Manage │ │ │ │ │ └───────────┘ └───────────┘ └───────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────┘登录界面 (LoginDialog)
运行效果图
交互流程
cpp用户操作: 1. 输入用户名 "123456" 2. 输入密码 "123456" 3. 选择角色 "管理员" 5. 点击 "登录" 系统响应: - 验证用户名密码 - 检查角色权限 - 跳转到对应主界面此为管理员界面
点击第一个图标业主管理
人事管理菜单栏可以查看/管理所有物业工作人员的账号信息
系统参数
功能 说明 系统设置 修改系统配置(如公司名称、缴费标准等) 权限管理 设置不同角色的操作权限 数据备份 备份数据库文件 下为工作人员的界面图
下位业主界面图
管理员 vs 工作人员
总结
角色 核心区别 管理员 管理整个系统,拥有所有权限 工作人员 执行具体任务,权限受限 详细对比表
对比项 管理员 工作人员 数据库标记 workertype = "是"workertype = "否"登录角色选择 选择 "管理员" 选择 "工作人员" 看到的主界面 管理员主界面 (ManagerManage) 工作人员主界面 (WorkerManage) 可查看业主信息 ✅ 是 ⚠️ 受限 可管理工作人员 ✅ 是 ❌ 否 可添加/删除业主 ✅ 是 ❌ 否 可处理缴费 ✅ 是 ⚠️ 只能查看/收取 可分配工单 ✅ 是 ❌ 否 可查看系统参数 ✅ 是 ❌ 否 可修改权限 ✅ 是 ❌ 否 可查看所有数据 ✅ 是 ⚠️ 仅部分数据


























