#include "gradespage.h" #include "appevent.h" #include "qjsonobject.h" #include "qpainter.h" #include "tmodel.h" #include "widgets/examsmodel.h" #include "widgets/gradsmodel.h" #include "widgets/pagination.h" #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" #include "widgets/studentmodel.h" static CWF::SqlDatabaseStorage storage("QSQLITE", "localhost", "data.db", "", ""); class CheckDelegate : public QStyledItemDelegate { public: CheckDelegate(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 == "true") { tagText = TeacherServer::Tr::tr("Select"); color = Qt::green; } else { tagText = TeacherServer::Tr::tr("Not Selected"); } // 设置背景色和边框 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); // 调整大小,以适应内容 } }; GradesPage::GradesPage(QWidget *parent) : QWidget{parent} { examsLineEdit = new QLineEdit; view = new QTableView; pagination = new Pagination; examsNameLineEdit = new QLineEdit; fileDirLineEdit = new QLineEdit; selectCheckBox = new QCheckBox; selectCheckBox->setDisabled(true); pageSize = new QComboBox; pageSize->addItem("10", 10); pageSize->addItem("20", 20); pageSize->addItem("30", 30); pageSize->addItem("50", 50); pageSize->addItem("100", 100); using namespace Layouting; auto examsEditor = Group{title(tr("Test question information")), Form{ tr("exams name"), examsNameLineEdit, br, tr("file dir"), fileDirLineEdit, PushButton{text(tr("open dir"))}, br, tr("select"), selectCheckBox, }, normalMargin} .emerge(); // PushButton{text(tr("Add")), onClicked([this]() { addExamsQuestion(); })}, // PushButton{text(tr("Remove")), onClicked([this]() { removeExamsQuestion(); })}, // PushButton{text(tr("Set as Default")), onClicked([this]() { setDefault(); })}, auto op = Column{st, PushButton{text(tr("Clear...")), onClicked([this]() { Clear(); })}, 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); // Form{"examsPath:", examsLineEdit, PushButton{text(tr("path"))}},} auto pageWidget = Row{pagination, st, tr("pageSize"), pageSize, st}; Row{Column{view, pageWidget}, op}.attachTo(this); // 考试系统 // 创建数据模型 GradsTableModel *model = new GradsTableModel; // 创建表格视图 view->setModel(model); view->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); view->setSelectionBehavior(QAbstractItemView::SelectRows); view->setSelectionMode(QAbstractItemView::SingleSelection); // 连接信号和槽 QObject::connect(pageSize, &QComboBox::currentTextChanged, [this](const QString &) { updateView(); }); QObject::connect(pagination, &Pagination::valueChanged, [this](int) { updateView(); }); connect(view, &QTableView::clicked, this, [=](const QModelIndex &index) { // GradsTableModel *model = qobject_cast(view->model()); // ExamsTableModel::Exams exam = model->getCurrentExam(index); // examsNameLineEdit->setText(exam.name); // fileDirLineEdit->setText(exam.fileDir); // fileDirLineEdit->setToolTip(exam.fileDir); // selectCheckBox->setChecked(exam.select); }); AppEvent *appEvent = AppEvent::instance(); QObject::connect(appEvent, &AppEvent::examsTestUpdateSignal, [this]() { updateView(); }); QObject::connect(appEvent, &AppEvent::beginExamSignal, [this]() { pagination->setCurrentPage(1); }); updateView(); } void GradesPage::updateView() { const QString sql = R"__( SELECT s.name, s.swID, s.examineeNumber, s.checkinNumber, s.groupName, s.answerFileName, s.school, e.end_time AS exam_time, e.exam_room, e.exam_sessions, eq.name AS examName FROM user s JOIN exams_test e ON s.id = e.user_id JOIN exams_question eq ON e.exams_id = eq.id)__"; const QString sqlTotal = R"__( SELECT COUNT(*) AS total FROM user s JOIN exams_test e ON s.id = e.user_id JOIN exams_question eq ON e.exams_id = eq.id)__"; int size = pageSize->currentData().toInt(); pagination->setPageSizes(size); ExamsTestModel examsTestModel(storage); GradsTableModel *model = qobject_cast(view->model()); CWF::SqlQueryManager queryManager(storage); queryManager.exec(sqlTotal); 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("%1 LIMIT %2 OFFSET %3").arg(sql).arg(pageSize).arg((pageNumber - 1) * pageSize); queryManager.exec(queryStr); model->loadJsonData(queryManager.toJson()); } void GradesPage::addExamsQuestion() {} void GradesPage::setDefault() {} void GradesPage::removeExamsQuestion() {} void GradesPage::save() { // GradsTableModel *model = qobject_cast(studentView->model()); // const QModelIndex index = view->currentIndex(); // ExamsTableModel::Exams exams = model->getCurrentExam(index); // if (exams.id == 0) { // return; // } // ExamsQuestionModel examsModel(storage); // CWF::SqlQueryManager queryManager(storage); // //queryManager.select("*", examsModel.getTableName()).where("isSelect = ?"); // queryManager.update(examsModel.getTableName(), "name=?,fileDir=?,isSelect=?").where("id = ?"); // queryManager.prepare(); // queryManager.addBindValue(examsNameLineEdit->text()); // queryManager.addBindValue(fileDirLineEdit->text()); // queryManager.addBindValue(selectCheckBox->isChecked()); // queryManager.addBindValue(exams.id); // QJsonObject status = queryManager.exec(); // if (status["success"].toBool()) { // updateView(); // view->setCurrentIndex(index); // } } void GradesPage::Clear() { QMessageBox msgBox; msgBox.setInformativeText(QString(tr("This will clear up all grades 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 exams_test;"); } updateView(); } void GradesPage::exportFile() { QString filePath = QFileDialog::getSaveFileName(nullptr, tr("file"), "", "xlsx Files (*.xlsx);;All Files (*)"); // 如果用户选择了文件,输出文件路径 if (filePath.isEmpty()) { return; } QXlsx::Document xlsx = QXlsx::Document(filePath); enum { __INDEX, nameIndex = 1, SWIDIndex, examineeNumberIndex, examTestIndex, groupIndex, timeIndex, AnswerFileNameIndex, checkinNumberIndex, timeSecondIndex, schoolIndex, examRoomIndex, examSessionsIndex, }; static QMap colNameMap = { { nameIndex, "\xE5\xA7\x93\xE5\x90\x8D" // UTF-8 编码的 "姓名" }, { SWIDIndex, "\x53\x57\x5F\x49\x44" // UTF-8 编码的 "SW_ID" }, { examineeNumberIndex, "\xE8\x80\x83\xE8\xAF\x95\xE7\xBC\x96\xE5\x8F\xB7" // UTF-8 编码的 "考试编号" }, { examTestIndex, "\xE8\x80\x83\xE8\xAF\x95\xE5\x86\x85\xE5\xAE\xB9" // UTF-8 编码的 "考试内容" }, { groupIndex, "\xE7\xBB\x84\xE5\x88\xAB" // UTF-8 编码的 "组别" }, { timeIndex, "\xE5\xAE\x8C\xE6\x88\x90\xE6\x97\xB6\xE9\x97\xB4" // UTF-8 编码的 "完成时间" }, { AnswerFileNameIndex, "\xE7\xAD\x94\xE6\xA1\x88\xE6\x96\x87\xE4\xBB\xB6\xE5\x90\x8D\xE7\xA7\xB0" // UTF-8 编码的 "答案文件名称" }, { checkinNumberIndex, "\347\255\276\345\210\260\345\217\267" // UTF-8 编码的 "签到号" }, { timeSecondIndex, "\xE5\xAE\x8C\xE6\x88\x90\xE6\x97\xB6\xE9\x97\xB4_s" // UTF-8 编码的 "完成时间" }, { schoolIndex, "\345\255\246\346\240\241" //学校 }, { examRoomIndex, "\350\200\203\350\257\225\346\225\231\345\256\244" // UTF-8 编码的 "考试教室" }, { examSessionsIndex, "\350\200\203\350\257\225\345\234\272\346\254\241" // UTF-8 编码的 "考试场次" }, }; for (int col = 1; col <= colNameMap.size(); ++col) { xlsx.write(1, col, colNameMap[col]); } UserModel userModel(storage); CWF::SqlQueryManager queryManager(storage); const QString sql = R"__( SELECT s.name, s.swID, s.examineeNumber, s.checkinNumber, s.groupName, s.answerFileName, s.school, e.end_time AS exam_time, e.exam_room, e.exam_sessions, eq.name AS examName FROM user s JOIN exams_test e ON s.id = e.user_id JOIN exams_question eq ON e.exams_id = eq.id)__"; int row = 2; QJsonObject status = queryManager.exec(sql); if (status["success"].toBool()) { const QJsonArray jsonArray = queryManager.toJson(); for (const QJsonValue &json : jsonArray) { const QJsonObject &object = json.toObject(); const QString name = object.value("name").toString(); const QString swID = object.value("swID").toString(); const QString examineeNumber = object.value("examineeNumber").toString(); const QString examName = object.value("examName").toString(); const QString checkinNumber = object.value("checkinNumber").toString(); const QString groupName = object.value("groupName").toString(); const int answerTime = object.value("exam_time").toInt(); const QString answerFileName = object.value("answerFileName").toString(); const QString school = object.value("school").toString(); const QString exam_room = object.value("exam_room").toString(); const QString exam_sessions = object.value("exam_sessions").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, examName); xlsx.write(row, checkinNumberIndex, checkinNumber); xlsx.write(row, groupIndex, groupName); xlsx.write(row, timeIndex, answerTime); xlsx.write(row, AnswerFileNameIndex, answerFileName); xlsx.write(row, timeSecondIndex, int(answerTime / 1000)); xlsx.write(row, schoolIndex, school); xlsx.write(row, examRoomIndex, exam_room); xlsx.write(row, examSessionsIndex, exam_sessions); row++; } } xlsx.save(); }