#include "blastopepage.h" #include "ui_blastopepage.h" #include "countdownwidget.h" #include BlastOpePage::BlastOpePage(QWidget *parent) : QWidget(parent), ui(new Ui::BlastOpePage), dao(DatabaseManager::getInstance().getDatabase()) { ui->setupUi(this); initPagination(); } void BlastOpePage::showDownWidget(QString uuid,const QString &topic,const QString &message){ CountdownWidget *countdownWidget = new CountdownWidget(this); countdownWidget->resize(200, 200); int x = (this->width() - countdownWidget->width()) / 2; int y = (this->height() - countdownWidget->height()) / 2; countdownWidget->move(x, y); countdownWidget->show(); firingWidget *widget = uuidWidgetMap.value(uuid); if (widget) { connect(countdownWidget, &CountdownWidget::countdownFinished, widget, [widget,topic,message,countdownWidget](){ widget->onCountdownFinished(topic,message); }, Qt::SingleShotConnection); } } void BlastOpePage::InitFace() { layout = new QVBoxLayout(this); view = new QWebEngineView(this); view->setAttribute(Qt::WA_OpaquePaintEvent); QWebEnginePage *page = view->page(); QJsonObject metaInfo = getMetaInfo(); QObject::connect(page, &QWebEnginePage::featurePermissionRequested, [this,page](const QUrl &securityOrigin, QWebEnginePage::Feature feature) { handleFeaturePermission(page, securityOrigin, feature); }); QUrl postUrl("http://192.168.0.255:8000/api/v1/h-face-verify/pc"); QJsonObject response = sendPostRequest(postUrl, metaInfo); QString certifyUrl; if (response.contains("data") && response["data"].isObject()) { QJsonObject dataObject = response["data"].toObject(); if (dataObject.contains("ResultObject") && dataObject["ResultObject"].isObject()) { QJsonObject resultObject = dataObject["ResultObject"].toObject(); if (resultObject.contains("CertifyId") && resultObject["CertifyId"].isString()) { certifyId= resultObject["CertifyId"].toString(); } if (resultObject.contains("CertifyUrl") && resultObject["CertifyUrl"].isString()) { certifyUrl = resultObject["CertifyUrl"].toString(); } } } if (!certifyUrl.isEmpty()) { view->load(QUrl(certifyUrl)); layout->addWidget(view); layout->setStretchFactor(view, 1); QObject::connect(page, &QWebEnginePage::urlChanged, this, &BlastOpePage::onUrlChanged); } else { qDebug() << "Failed to get certifyUrl."; } } void BlastOpePage::closeWebViewAndRestoreUI() { if (view) { layout->removeWidget(view); delete view; view = nullptr; } if (layout) { delete layout; layout = nullptr; } } // 槽函数:处理 URL 改变事件 void BlastOpePage::onUrlChanged(const QUrl &newUrl) { if (newUrl.scheme() == "https" && newUrl.host() == "www.baidu.com") { closeWebViewAndRestoreUI(); QNetworkAccessManager manager; QUrl requestUrl(QString("http://localhost:8000/api/v1/h-face-verify/certifyId/%1").arg(certifyId)); QNetworkRequest request(requestUrl); QNetworkReply *reply = manager.get(request); QEventLoop loop; QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); if (reply->error() == QNetworkReply::NoError) { QByteArray responseData = reply->readAll(); QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData); if (!jsonDoc.isNull() && jsonDoc.isObject()) { QJsonObject rootObj = jsonDoc.object(); QJsonObject dataObj = rootObj["data"].toObject(); QString message = dataObj["Message"].toString(); QJsonObject resultObj = dataObj["ResultObject"].toObject(); if (resultObj.isEmpty()) { int ret = QMessageBox::information(nullptr, "提示", message+" ,请重新认证!"); if (ret == QMessageBox::Ok) { InitFace(); } } else { QString passed = resultObj["Passed"].toString(); if (passed == "T") { QMessageBox::information(nullptr, "提示", "操作成功!"); ui->setupUi(this); initPagination(); } else if (passed == "F") { int ret = QMessageBox::critical(nullptr, "提示", "操作失败,请重新认证!"); if (ret == QMessageBox::Ok) { InitFace(); } } } } } else { qDebug() << "Request failed:" << reply->errorString(); } reply->deleteLater(); } } BlastOpePage::~BlastOpePage() { delete ui; if (view) { delete view; } if (layout) { delete layout; } } QJsonObject BlastOpePage::sendPostRequest(const QUrl &url, const QJsonObject &data) { QNetworkAccessManager manager; QNetworkRequest request(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); QJsonDocument doc(data); QByteArray postData = doc.toJson(); QNetworkReply *reply = manager.post(request, postData); QEventLoop loop; QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); loop.exec(); QJsonObject responseJson; if (reply->error() == QNetworkReply::NoError) { QByteArray responseData = reply->readAll(); QJsonDocument responseDoc = QJsonDocument::fromJson(responseData); if (!responseDoc.isNull() && responseDoc.isObject()) { responseJson = responseDoc.object(); } } else { qDebug() << "Error fetching content: " << reply->errorString(); } reply->deleteLater(); return responseJson; } void BlastOpePage::handleFeaturePermission(QWebEnginePage *page, const QUrl &securityOrigin, QWebEnginePage::Feature feature) { if (feature == QWebEnginePage::MediaAudioCapture || feature == QWebEnginePage::MediaAudioVideoCapture || feature == QWebEnginePage::MediaVideoCapture) { page->setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionGrantedByUser); } else { page->setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionDeniedByUser); } } QJsonObject BlastOpePage::getMetaInfo() { QJsonObject metaInfo; metaInfo["certName"] = ""; metaInfo["certNo"] = ""; return metaInfo; } void BlastOpePage::initPagination(){ pageWidget= new PageWidget; connect(pageWidget, &PageWidget::currentPageChanged, this, &BlastOpePage::PageChanged); connect(pageWidget->getComboBox(), QOverload::of(&QComboBox::currentIndexChanged), this, &BlastOpePage::onComboBoxIndexChanged); ui->verticalLayout_4->addWidget(pageWidget);; pageSize = 10; currentPage = 1; RefreshData(); } void BlastOpePage::RefreshData() { loadDataFromSource(currentPage,pageSize); } void BlastOpePage::loadDataFromSource(int currentPage, int pageSize) { PaginatedHProjectResult result =dao.getAllHProjectsByOpera(currentPage,pageSize); QList> projectList = result.projects; totalCount = result.totalCount; pageWidget->setMaxPage(ceil(static_cast(totalCount)/pageSize)); model = new QStandardItemModel(this); headers = { {"选择", ""}, // 新增选择列 {"工程名称", "name"}, {"操作员", "operatorName"}, {"爆破员", "blasterName"}, {"井下地址", "addressUuid"}, {"雷管数量", "detSum"}, {"起爆器数量", "blastCount"}, {"起爆状态", "blastStatus"}, {"进度", ""}, {"操作",""}, }; int headerCount = headers.size(); QStringList headerLabels; QMap propMap; for (int i = 0; i < headers.size(); ++i) { headerLabels << headers[i].label; propMap[i] = headers[i].prop; } model->setHorizontalHeaderLabels(headerLabels); for (int row = 0; row < projectList.size(); ++row) { HProject& HProject = *projectList.at(row).data(); QStandardItem* uuidItem = new QStandardItem(); uuidItem->setData(HProject.getUuid(), Qt::UserRole); model->setItem(row, headerCount, uuidItem); for (int col = 0; col < headerCount; ++col) { QString prop = propMap[col]; QStandardItem* item = nullptr; if(col ==0){ item = new QStandardItem(); item->setCheckable(true); item->setCheckState(Qt::Unchecked); item->setText(""); } if (!prop.isEmpty()) { QMetaProperty metaProp = HProject.metaObject()->property(HProject.metaObject()->indexOfProperty(prop.toUtf8())); QVariant value = metaProp.read(&HProject); if (prop == "blastStatus") { QString statusText; if (value.toString() == "1") { statusText = "未 注 册"; item = new QStandardItem(statusText); item->setForeground(QColor("#e7c66b")); } else if (value.toString() == "2") { statusText = "待 起 爆"; item = new QStandardItem(statusText); item->setForeground(QColor("#f3a361")); } else if (value.toString() == "3") { statusText = "起 爆 完 成"; item = new QStandardItem(statusText); item->setForeground(QColor("#90d543")); } else { item = new QStandardItem(value.toString()); } } else { item = new QStandardItem(value.toString()); } } if (item) { item->setTextAlignment(Qt::AlignCenter); // 设置文本居中对齐 model->setItem(row, col, item); } } } ui->tableView->setModel(model); connectionItem = QObject::connect(model, &QStandardItemModel::itemChanged, this, &BlastOpePage::onItemChanged); ui->tableView->setColumnWidth(0, 20); for (int i = 1; i < headerCount; ++i) { ui->tableView->horizontalHeader()->setSectionResizeMode(i, QHeaderView::Stretch); } ui->tableView->setColumnHidden(headerCount, true); ui->tableView->setAlternatingRowColors(true); ui->tableView->verticalHeader()->setDefaultSectionSize(50); for (int row = 0; row < projectList.size(); ++row) { int progressCol = headers.size() - 2; // QProgressBar *progressBar1 = new QProgressBar(ui->tableView); progressBar1->setRange(0, 100); // 设置范围为0到100 progressBar1->setValue(0); progressBar1->setAlignment(Qt::AlignCenter); progressBar1->setStyleSheet("QProgressBar { border: 1px solid grey; border-radius: 5px; background-color: #EEEEEE; height: 10px; }" "QProgressBar::chunk { background-color: #05B8CC; width: 2px; margin: 0.5px; border - radius: 10px; }"); progressBar1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QProgressBar *progressBar2 = new QProgressBar(ui->tableView); progressBar2->setRange(0, 100); // 设置范围为0到100 progressBar2->setValue(0); progressBar2->setAlignment(Qt::AlignRight); progressBar2->setStyleSheet("QProgressBar { border: 1px solid grey; border-radius: 5px; background-color: #EEEEEE; height: 20px; }" "QProgressBar::chunk { background-color: #05B8CC; width: 20px; margin: 0.5px; border - radius: 10px; }"); progressBar2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QProgressBar *progressBar3 = new QProgressBar(ui->tableView); progressBar3->setRange(0, 100); // 设置范围为0到100 progressBar3->setValue(0); progressBar3->setAlignment(Qt::AlignRight); progressBar3->setStyleSheet("QProgressBar { border: 1px solid grey; border-radius: 5px; background-color: #EEEEEE; height: 20px; }" "QProgressBar::chunk { background-color: #05B8CC; width: 20px; margin: 0.5px; border - radius: 10px; }"); progressBar3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); progressBars.append(ProgressBarTriple(progressBar1, progressBar2,progressBar3)); QHBoxLayout *progressBarLayout = new QHBoxLayout; progressBarLayout->addWidget(progressBar1); progressBarLayout->addWidget(progressBar2); progressBarLayout->addWidget(progressBar3); progressBarLayout->setAlignment(Qt::AlignCenter); progressBarLayout->setContentsMargins(0, 0, 0, 0); QWidget *progressBarContainer = new QWidget(ui->tableView); progressBarContainer->setLayout(progressBarLayout); QModelIndex progressIndex = model->index(row, progressCol); if (progressIndex.isValid()) { ui->tableView->setIndexWidget(progressIndex, progressBarContainer); } int col = headers.size() - 1; // 创建一个按钮 QWidget* widget = new QWidget(ui->tableView); QPushButton* button = new QPushButton(widget); button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); QModelIndex statusIndex = model->index(row, propMap.key("blastStatus")); if (statusIndex.isValid()) { QString blastStatus = model->data(statusIndex).toString(); if (blastStatus == "起 爆 完 成") { // 为按钮添加图标,这里假设图标文件名为 icon.png,你需要根据实际情况修改 QIcon icon(":/icons/icons/svg/blast.svg"); button->setIcon(icon); button->setIconSize(QSize(32, 32)); // 设置图标大小 button->setStyleSheet("QPushButton {" " padding: 0px;" " border: none;" " background-color: transparent;" "}" ); }else{ button->setText("开启起爆流程"); } } QHBoxLayout* layout = new QHBoxLayout(widget); layout->addWidget(button); layout->setAlignment(Qt::AlignCenter); layout->setContentsMargins(0, 0, 0, 0); widget->setLayout(layout); QModelIndex index = model->index(row, col); if (index.isValid()) { ui->tableView->setIndexWidget(index, widget); connect(button, &QPushButton::clicked, [this, row,button]() { handleButtonClick(row,button); }); } } } // 切换页数 void BlastOpePage::PageChanged(int page) { currentPage = page; loadDataFromSource(currentPage,pageSize); } void BlastOpePage::onComboBoxIndexChanged(int index) { QVariant variant = pageWidget->getComboBox()->itemData(index); int value = variant.toInt(); pageSize = value; currentPage = 1; loadDataFromSource(currentPage,pageSize); } void BlastOpePage::updateProgressBar(int value, int row) { if (!progressBars.isEmpty()) { QProgressBar *progressBar1 = progressBars[row].bar1; QProgressBar *progressBar2 = progressBars[row].bar2; QProgressBar *progressBar3 = progressBars[row].bar3; switch (value) { case 1: //检查状态 progressBar1->setRange(0, 0); // 设置范围为0到100 progressBar1->setValue(0); break; case 2: // 检查完成 progressBar1->setRange(0, 100); // 设置范围为0到100 progressBar1->setValue(100); break; case 3: // 充电开始 progressBar2->setRange(0, 0); // 设置范围为0到100 progressBar2->setValue(0); break; case 4: //充电完成 progressBar2->setRange(0, 100); // 设置范围为0到100 progressBar2->setValue(100); break; case 5: //起爆中 progressBar3->setRange(0, 0); // 设置范围为0到100 progressBar3->setValue(0); break; case 6: //充电完成 progressBar3->setRange(0, 100); // 设置范围为0到100 progressBar3->setValue(100); break; case 0: progressBar1->setRange(0, 100); progressBar1->setValue(0); progressBar2->setRange(0, 100); progressBar2->setValue(0); progressBar3->setRange(0, 100); progressBar3->setValue(0); break; default: break; } } } void BlastOpePage::onUpdateBlastStatus(int status ,int row) { QModelIndex index = model->index(row, 6); if (index.isValid()) { QColor customColor; QFont boldFont; boldFont.setBold(true); switch (status) { case 1: model->setData(index, "组 网 中 ..."); customColor= QColor("#44035b"); model->setData(index, customColor, Qt::ForegroundRole); model->setData(index, boldFont, Qt::FontRole); break; case 2: model->setData(index, "组 网 完 成"); customColor = QColor("#404185"); model->setData(index, customColor, Qt::ForegroundRole); break; case 3: model->setData(index, "充 电 中 ..."); customColor = QColor("#31688e"); model->setData(index, customColor, Qt::ForegroundRole); break; case 4: model->setData(index, "充 电 完 成"); customColor = QColor("#1f918d"); model->setData(index, customColor, Qt::ForegroundRole); break; case 5: model->setData(index, "起 爆 中 ..."); customColor = QColor("#38b775"); model->setData(index, customColor, Qt::ForegroundRole); break; case 6: model->setData(index, "起 爆 完 成"); customColor = QColor("#90d543"); model->setData(index, customColor, Qt::ForegroundRole); break; case 0: model->setData(index, "已 注 册"); customColor = QColor("#8e620"); model->setData(index, customColor, Qt::ForegroundRole); break; case 10: model->setData(index, "按 下 双 建 起 爆 ..."); customColor = QColor("#8e620"); model->setData(index, customColor, Qt::ForegroundRole); break; default: break; } } } void BlastOpePage::handleButtonClick(int row,QPushButton *button){ QStandardItem *uuidItem = model->item(row, 10); QString uuid; if (uuidItem) { QVariant uuidVariant = uuidItem->data(Qt::UserRole); if (uuidVariant.isValid()) { uuid = uuidVariant.toString(); } } if (button->text() == "开启起爆流程") { button->setText("取消起爆流程"); firingWidget *widget = new firingWidget(row,false,uuid); connect(widget, &firingWidget::progressChanged, this, &BlastOpePage::updateProgressBar); connect(widget, &firingWidget::updateBlastStatus, this, &BlastOpePage::onUpdateBlastStatus); connect(widget,&firingWidget::updateButton,this,&BlastOpePage::changeButByMqtt); connect(widget,&firingWidget::countdown,this,&BlastOpePage::showDownWidget); connect(widget,&firingWidget::updateProjectStatus,this,&BlastOpePage::updateProject); connect(widget,&firingWidget::closeFiring,this,&BlastOpePage::destroyFiringWidget); widget->show(); widget->setAttribute(Qt::WA_DeleteOnClose); uuidWidgetMap.insert(uuid, widget); } else if (button->text() == "取消起爆流程") { firingWidget *widget = uuidWidgetMap.value(uuid); if (widget) { widget->cancelBlasting(); } } } void BlastOpePage::changeButByMqtt(int status ,int row){ qDebug() << "statusButton:"<index(row, 8); if (index.isValid()) { QWidget *widget = ui->tableView->indexWidget(index); if (widget) { QPushButton *button = widget->findChild(); if (button) { // 使用样式表设置图标居中 button->setStyleSheet("QPushButton {" " padding: 0px;" " border: none;" " background-color: transparent;" "}" ); // 添加图标,假设图标文件名为 blast.svg,并且该文件存在于项目资源中 QIcon icon(":/icons/icons/svg/blast.svg"); button->setText(""); button->setIcon(icon); button->setIconSize(QSize(32, 32)); } } } } void BlastOpePage::updateProject(QString uuid){ dao.updateBlastStatusByUuid(uuid,"3"); } void BlastOpePage::destroyFiringWidget(const QString& uuid) { firingWidget *widget = uuidWidgetMap.value(uuid); if (widget) { widget->close(); // 关闭窗口 widget->deleteLater(); // 释放内存 uuidWidgetMap.remove(uuid); // 从映射中移除 } } // 槽函数,当 item 状态改变时触发 void BlastOpePage::onItemChanged(QStandardItem *item) { if (item->column() == 0) { // 仅处理第一列的勾选状态改变 if (item->checkState() == Qt::Checked) { QStandardItem *uuidItem = model->item(item->row(), 10); if (uuidItem) { QVariant uuidVariant = uuidItem->data(Qt::UserRole); if (uuidVariant.isValid()) { QString uuid = uuidVariant.toString(); uuidMap[item->row()] = uuid; } } } else if (item->checkState() == Qt::Unchecked) { QStandardItem *uuidItem = model->item(item->row(), 10); if (uuidItem) { // 从 item 中获取 uuid 数据 QVariant uuidVariant = uuidItem->data(Qt::UserRole); if (uuidVariant.isValid()) { QString uuid = uuidVariant.toString(); // 从数组中移除该 uuid uuidMap.remove(item->row()); } } } } } void BlastOpePage::on_btnSelect_clicked() { // 禁用表格第一列的选项 for (int row = 0; row < model->rowCount(); ++row) { QStandardItem *item = model->item(row, 0); if (item) { Qt::ItemFlags flags = item->flags(); flags &= ~Qt::ItemIsEnabled; item->setFlags(flags); } } for (auto it = uuidMap.begin(); it != uuidMap.end(); ++it) { int row = it.key(); QString uuid = it.value(); firingWidget *widget = new firingWidget(row,true,uuid); QModelIndex index = model->index(row, 9); if (index.isValid()) { QWidget *widgetButton = ui->tableView->indexWidget(index); if (widgetButton) { QPushButton *button = widgetButton->findChild(); button->setText("取消起爆流程"); } } // 信号连接 connect(widget, &firingWidget::progressChanged, this, &BlastOpePage::updateProgressBar); connect(widget, &firingWidget::updateBlastStatus, this, &BlastOpePage::onUpdateBlastStatus); widget->show(); widget->setAttribute(Qt::WA_DeleteOnClose); } }