#include "studentpage.h" #include "appevent.h" #include "cwf/sqlquerymanager.h" #include "qcombobox.h" #include "qjsonarray.h" #include "qjsonvalue.h" #include "qnamespace.h" #include "tmodel.h" #include "widgets/pagination.h" #include "widgets/studentmodel.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "cwf/sqlquery.h" #include #include #include #include #include "teachertr.h" static CWF::SqlDatabaseStorage storage("QSQLITE", "localhost", "data.db", "", ""); class TagDelegate : public QStyledItemDelegate { public: TagDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {} void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override { QStyledItemDelegate::paint(painter, option, index); // 获取数据 QString tagText = index.data(Qt::DisplayRole).toString(); QColor color = Qt::lightGray; if (tagText == "1") { tagText = TeacherServer::Tr::tr("online"); color = Qt::green; } else { tagText = TeacherServer::Tr::tr("outline"); } // 设置背景色和边框 painter->save(); painter->setRenderHint(QPainter::Antialiasing); painter->setPen(Qt::NoPen); painter->setBrush(color); // 背景色 painter->drawRoundedRect(option.rect.adjusted(2, 2, -2, -2), 5, 5); // 圆角矩形 // 设置文本颜色和对齐方式 painter->setPen(QColor("#0078D4")); // 文本颜色 painter->setFont(QFont("Arial", 10)); painter->drawText(option.rect.adjusted(5, 2, -5, -2), Qt::AlignCenter, tagText); painter->restore(); } QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override { // 返回标签的合适大小 QString tagText = index.data(Qt::DisplayRole).toString(); QFontMetrics fm(option.font); QSize size = fm.size(0, tagText); return size + QSize(10, 4); // 调整大小,以适应内容 } }; StudentPage::StudentPage(QWidget *parent) : QWidget{parent} { using namespace Layouting; studentView = new QTableView; pagination = new Pagination; pageSize = new QComboBox; pageSize->addItem("10", 10); pageSize->addItem("20", 20); pageSize->addItem("30", 30); pageSize->addItem("50", 50); pageSize->addItem("100", 100); studentNameLineEdit = new QLineEdit; studentSwLineEdit = new QLineEdit; examineeNumberLineEdit = new QLineEdit; checkinNumberLineEdit = new QLineEdit; examsTestLineEdit = new QLineEdit; groupNameComboBox = new QComboBox; groupNameComboBox->addItem("小学"); groupNameComboBox->addItem("初中"); groupNameComboBox->addItem("高中"); auto studentEditor = Form{tr("name"), studentNameLineEdit, br, tr("swID"), studentSwLineEdit, br, tr("examinee number"), examineeNumberLineEdit, noMargin()} .emerge(); auto studentEditorRight = Form{tr("checkin number"), checkinNumberLineEdit, br, tr("group name"), groupNameComboBox, br, tr("exams test"), examsTestLineEdit, noMargin()} .emerge(); auto op = Column{PushButton{text(tr("Add")), onClicked([this]() { addStudent(); })}, PushButton{text(tr("Remove")), onClicked([this]() { removeStudent(); })}, PushButton{text(tr("Set as Default")), onClicked([this]() { setDefault(); })}, st, PushButton{text(tr("Clear...")), onClicked([this]() { Clear(); })}, PushButton{text(tr("Import...")), onClicked([this]() { importFile(); })}, PushButton{text(tr("Export...")), onClicked([this]() { exportFile(); })}, st, PushButton{text(tr("Save")), onClicked([this]() { save(); })}} .emerge(); // examsEditor->setMinimumWidth(300); op->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); auto pageWidget = Row{pagination, st, tr("pageSize"), pageSize, st}; Row{Column{studentView, pageWidget, Row{studentEditor, studentEditorRight}}, op}.attachTo(this); // 创建数据模型 StudentTableModel *model = new StudentTableModel; // 创建表格视图 studentView->setModel(model); studentView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); studentView->setSelectionBehavior(QAbstractItemView::SelectRows); studentView->setSelectionMode(QAbstractItemView::SingleSelection); studentView->setItemDelegateForColumn(StudentTableModel::STATE, new TagDelegate(this)); // 设置第0列应用委托 AppEvent *appEvent = AppEvent::instance(); // 连接信号和槽 QObject::connect(appEvent, &AppEvent::loginUserSignal, [this](int) { updateStudentView(); }); QObject::connect(appEvent, &AppEvent::loginOutUserSignal, [this](int) { updateStudentView(); }); QObject::connect(pagination, &Pagination::valueChanged, [this](int) { updateStudentView(); }); QObject::connect(pageSize, &QComboBox::currentTextChanged, [this](const QString &) { updateStudentView(); }); connect(studentView, &QTableView::clicked, this, [=](const QModelIndex &index) { StudentTableModel *model = qobject_cast(studentView->model()); StudentTableModel::Student student = model->getCurrentStudent(index); studentNameLineEdit->setText(student.name); studentSwLineEdit->setText(student.swID); examineeNumberLineEdit->setText(student.examineeNumber); checkinNumberLineEdit->setText(student.checkinNumber); groupNameComboBox->setCurrentText(student.groupName); examsTestLineEdit->setText(student.examTest); }); updateStudentView(); } void StudentPage::updateStudentView() { int size = pageSize->currentData().toInt(); pagination->setPageSizes(size); UserModel userModel(storage); StudentTableModel *model = qobject_cast(studentView->model()); CWF::SqlQueryManager queryManager(storage); queryManager.select("COUNT(*) AS total", userModel.getTableName()); queryManager.exec(queryManager.getQueryText()); QJsonArray array = queryManager.toJson(); if (!array.isEmpty()) { QJsonObject object = array[0].toObject(); qint64 total = object["total"].toVariant().toLongLong(); pagination->setTotal(total); } int pageNumber = pagination->currentPage(); int pageSize = pagination->pageSizes(); QString queryStr = QString("SELECT * FROM %1 LIMIT %2 OFFSET %3") .arg(userModel.getTableName()) .arg(pageSize) .arg((pageNumber - 1) * pageSize); queryManager.exec(queryStr); model->loadJsonData(queryManager.toJson()); } void StudentPage::addStudent() { UserModel userModel(storage); CWF::SqlQueryManager queryManager(storage); queryManager.insert(userModel.getTableName(), "name,swID,state,examineeNumber,maxTime"); queryManager.prepare(); queryManager.addBindValue(""); queryManager.addBindValue(""); queryManager.addBindValue("0"); queryManager.addBindValue(""); queryManager.addBindValue(0); QJsonObject status = queryManager.exec(); if (status["success"].toBool()) { updateStudentView(); } } void StudentPage::setDefault() {} void StudentPage::removeStudent() { StudentTableModel *model = qobject_cast(studentView->model()); const QModelIndex index = studentView->currentIndex(); StudentTableModel::Student student = model->getCurrentStudent(index); if (student.id == 0) { return; } UserModel userModel(storage); CWF::SqlQueryManager queryManager(storage); //queryManager.select("*", examsModel.getTableName()).where("isSelect = ?"); queryManager.remove(userModel.getTableName(), "id = ?"); queryManager.prepare(); queryManager.addBindValue(student.id); QJsonObject status = queryManager.exec(); if (status["success"].toBool()) { updateStudentView(); studentView->setCurrentIndex(index); } } void StudentPage::save() { StudentTableModel *model = qobject_cast(studentView->model()); const QModelIndex index = studentView->currentIndex(); StudentTableModel::Student student = model->getCurrentStudent(index); if (student.id == 0) { return; } UserModel userModel(storage); CWF::SqlQueryManager queryManager(storage); queryManager .update(userModel.getTableName(), "name=?,swID=?,state=?,examineeNumber=?,checkinNumber=?,groupName=?,examTest=?") .where("id = ?"); queryManager.prepare(); queryManager.addBindValue(studentNameLineEdit->text()); queryManager.addBindValue(studentSwLineEdit->text()); queryManager.addBindValue("0"); queryManager.addBindValue(examineeNumberLineEdit->text()); queryManager.addBindValue(checkinNumberLineEdit->text()); queryManager.addBindValue(groupNameComboBox->currentText()); queryManager.addBindValue(examsTestLineEdit->text()); queryManager.addBindValue(student.id); QJsonObject status = queryManager.exec(); if (status["success"].toBool()) { updateStudentView(); studentView->setCurrentIndex(index); } } void StudentPage::Clear() { QMessageBox msgBox; msgBox.setInformativeText(QString(tr("This will clear up all grades and student information"))); msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Ok); msgBox.setButtonText(QMessageBox::Ok, tr("OK")); msgBox.setButtonText(QMessageBox::Cancel, tr("Cancel")); int ret = msgBox.exec(); if (ret == QMessageBox::Ok) { CWF::SqlQueryManager queryManager(storage); queryManager.exec("DELETE FROM user;"); queryManager.exec("DELETE FROM exams_test;"); } // 清理学生信息 updateStudentView(); // 通知成绩信息更新 AppEvent::instance()->examsTestUpdate(); } void StudentPage::importFile() { QString filePath = QFileDialog::getOpenFileName(nullptr, tr("file"), "", "xlsx Files (*.xlsx);;All Files (*)"); // 如果用户选择了文件,输出文件路径 if (filePath.isEmpty()) { return; } QXlsx::Document xlsx = QXlsx::Document(filePath); int nameIndex = -1; int SWIDIndex = -1; int examineeNumberIndex = -1; int examTestIndex = -1; int groupIndex = -1; int maxTimeIndex = -1; int timeIndex = -1; int AnswerFileNameIndex = -1; int checkinNumberIndex = -1; int schoolIndex = -1; for (int col = 0; col < 8; ++col) { QVariant value = xlsx.read(1, col); QString strValue = value.toString(); if (strValue == "\xE5\xA7\x93\xE5\x90\x8D") { // UTF-8 编码的 "姓名" nameIndex = col; } else if (strValue == "\x53\x57\x5F\x49\x44") { // UTF-8 编码的 "SW_ID" SWIDIndex = col; } else if (strValue == "\xE8\x80\x83\xE8\xAF\x95\xE7\xBC\x96\xE5\x8F\xB7") { // UTF-8 编码的 "考试编号" examineeNumberIndex = col; } else if (strValue == "\xE8\x80\x83\xE8\xAF\x95\xE5\x86\x85\xE5\xAE\xB9") { // UTF-8 编码的 "考试内容" examTestIndex = col; } else if (strValue == "\xE7\xBB\x84\xE5\x88\xAB") { // UTF-8 编码的 "组别" groupIndex = col; } else if (strValue == "\xE6\x9C\x80\xE5\xA4\xA7\xE5\xAE\x8C\xE6\x88\x90\xE6\x97\xB6\xE9\x97" "\xB4") { // UTF-8 编码的 "最大完成时间" maxTimeIndex = col; } else if (strValue == "\xE5\xAE\x8C\xE6\x88\x90\xE6\x97\xB6\xE9\x97\xB4") { // UTF-8 编码的 "完成时间" timeIndex = col; } else if (strValue == "\xE7\xAD\x94\xE6\xA1\x88\xE6\x96\x87\xE4\xBB\xB6\xE5\x90\x8D\xE7\xA7" "\xB0") { // UTF-8 编码的 "答案文件名称" AnswerFileNameIndex = col; } else if (strValue == "\347\255\276\345\210\260\345\217\267") { // UTF-8 编码的 "签到号" checkinNumberIndex = col; } else if (strValue == "\345\255\246\346\240\241") { // UTF-8 编码的 "学校" schoolIndex = col; } } UserModel userModel(storage); for (int row = 2;; ++row) { QVariant nameValue = xlsx.read(row, nameIndex); QVariant SWIDValue = xlsx.read(row, SWIDIndex); QVariant examineeNumberValue = xlsx.read(row, examineeNumberIndex); QVariant examTestValue = xlsx.read(row, examTestIndex); QVariant groupNameValue = xlsx.read(row, groupIndex); QVariant maxTimeValue = xlsx.read(row, maxTimeIndex); QVariant timeValue = xlsx.read(row, timeIndex); QVariant AnswerFileNameValue = xlsx.read(row, AnswerFileNameIndex); QVariant checkinNumberValue = xlsx.read(row, checkinNumberIndex); QVariant schoolValue = xlsx.read(row, schoolIndex); if (nameValue.isNull() && SWIDValue.isNull() && examineeNumberValue.isNull() && examTestValue.isNull() && groupNameValue.isNull() && maxTimeValue.isNull() && timeValue.isNull() && AnswerFileNameValue.isNull() && checkinNumberValue.isNull()) { break; } qDebug() << "Row:" << row // << "Name:" << nameValue.toString() // << "SWID:" << SWIDValue.toString() // << "Examinee Number:" << examineeNumberValue.toString() // << "Exam Test:" << examTestValue.toString() // << "Group:" << groupNameValue.toString() // << "Max Time:" << maxTimeValue.toString() // << "Time:" << timeValue.toString() // << "Answer File Name:" << AnswerFileNameValue.toString() // << "checkin Number Value" << checkinNumberValue.toString(); if (nameValue.isNull()) { // 错误处理 } // 考试编号 和 SW_ID 必须存在一个 if (examineeNumberValue.isNull() && SWIDValue.isNull()) { // 错误处理 continue; } CWF::SqlQueryManager queryManager(storage); queryManager.insert( userModel.getTableName(), "name,swID,examineeNumber,examTest,groupName,maxTime,checkinNumber,school,state"); queryManager.prepare(); queryManager.addBindValue(nameValue.toString()); queryManager.addBindValue(SWIDValue.toString()); queryManager.addBindValue(examineeNumberValue.toString()); queryManager.addBindValue(examTestValue.toString()); queryManager.addBindValue(groupNameValue.toString()); queryManager.addBindValue(maxTimeValue.toInt()); queryManager.addBindValue(checkinNumberValue.toString()); queryManager.addBindValue(schoolValue.toString()); queryManager.addBindValue("0"); QJsonObject status = queryManager.exec(); if (status["success"].toBool()) { updateStudentView(); } } } void StudentPage::exportFile() { QString filePath = QFileDialog::getSaveFileName(nullptr, tr("file"), "", "xlsx Files (*.xlsx);;All Files (*)"); // 如果用户选择了文件,输出文件路径 if (filePath.isEmpty()) { return; } QXlsx::Document xlsx = QXlsx::Document(filePath); int nameIndex = 1; int SWIDIndex = 2; int examineeNumberIndex = 3; int examTestIndex = 4; int groupIndex = 5; int maxTimeIndex = 6; int timeIndex = 7; int AnswerFileNameIndex = 8; int checkinNumberIndex = 9; // int timeSecondIndex = 10; int schoolIndex = 11; QStringList colName = { "", "\xE5\xA7\x93\xE5\x90\x8D", // UTF-8 编码的 "姓名" "\x53\x57\x5F\x49\x44", // UTF-8 编码的 "SW_ID" "\xE8\x80\x83\xE8\xAF\x95\xE7\xBC\x96\xE5\x8F\xB7", // UTF-8 编码的 "考试编号" "\xE8\x80\x83\xE8\xAF\x95\xE5\x86\x85\xE5\xAE\xB9", // UTF-8 编码的 "考试内容" "\xE7\xBB\x84\xE5\x88\xAB", // UTF-8 编码的 "组别" "\xE6\x9C\x80\xE5\xA4\xA7\xE5\xAE\x8C\xE6\x88\x90\xE6\x97\xB6\xE9\x97\xB4", // UTF-8 编码的 "最大完成时间" "\xE5\xAE\x8C\xE6\x88\x90\xE6\x97\xB6\xE9\x97\xB4", // UTF-8 编码的 "完成时间" "\xE7\xAD\x94\xE6\xA1\x88\xE6\x96\x87\xE4\xBB\xB6\xE5\x90\x8D\xE7\xA7\xB0", // UTF-8 编码的 "答案文件名称" "\347\255\276\345\210\260\345\217\267", // UTF-8 编码的 "签到号" "\347\247\222", // 秒 "\345\255\246\346\240\241" // 学校 }; for (int col = 1; col < colName.size(); ++col) { QVariant value = xlsx.read(1, col); QString strValue = value.toString(); xlsx.write(1, col, colName[col]); } UserModel userModel(storage); CWF::SqlQueryManager queryManager(storage); queryManager.select("*", userModel.getTableName()); int row = 2; QJsonObject status = queryManager.exec(queryManager.getQueryText()); if (status["success"].toBool()) { const QJsonArray jsonArray = queryManager.toJson(); for (const QJsonValue &json : jsonArray) { const QJsonObject &object = json.toObject(); // QString name; // 姓名 // QString swID; // SW_ID // QString state; // 在线状态 // QString examineeNumber; // 考试编号 // QString examTest; // 考试内容 // QString checkinNumber; // 签到号 // QString groupName; // 组别 // int maxTime; // 最大完成时间 // int answerTime; // 完成时间 // QString answerFileName; // 完成时间 QString name = object["name"].toString(); // 姓名 QString swID = object["SW_ID"].toString(); // SW_ID QString state = object["state"].toString(); // 在线状态 QString examineeNumber = object["examineeNumber"].toString(); // 考试编号 QString examTest = object["examTest"].toString(); // 考试内容 QString checkinNumber = object["checkinNumber"].toString(); // 签到号 QString groupName = object["groupName"].toString(); // 组别 int maxTime = object["maxTime"].toInt(); // 最大完成时间 int answerTime = object["answerTime"].toInt(); // 完成时间 QString answerFileName = object["answerFileName"].toString(); // 答案文件名称 QString school = object["school"].toString(); // 答案文件名称 // Writing data to Excel file xlsx.write(row, nameIndex, name); xlsx.write(row, SWIDIndex, swID); xlsx.write(row, examineeNumberIndex, examineeNumber); xlsx.write(row, examTestIndex, examTest); xlsx.write(row, groupIndex, groupName); xlsx.write(row, maxTimeIndex, maxTime); xlsx.write(row, timeIndex, answerTime); xlsx.write(row, AnswerFileNameIndex, answerFileName); xlsx.write(row, checkinNumberIndex, checkinNumber); xlsx.write(row, timeSecondIndex, int(answerTime / 1000)); xlsx.write(row, schoolIndex, school); row++; } } xlsx.save(); }