640 lines
27 KiB
C++
640 lines
27 KiB
C++
#include "mainwindow.h"
|
||
|
||
#include <QComboBox>
|
||
#include <QDialog>
|
||
#include <QFormLayout>
|
||
#include <QGroupBox>
|
||
#include <QHeaderView>
|
||
#include <QHBoxLayout>
|
||
#include <QInputDialog>
|
||
#include <QLabel>
|
||
#include <QLineEdit>
|
||
#include <QMessageBox>
|
||
#include <QPushButton>
|
||
#include <QSpinBox>
|
||
#include <QTableWidget>
|
||
#include <QTableWidgetItem>
|
||
#include <QTreeWidget>
|
||
#include <QTreeWidgetItem>
|
||
#include <QVBoxLayout>
|
||
|
||
#include <ctime>
|
||
|
||
#include "core/his_core.h"
|
||
#include "models/ward.h"
|
||
#include "utils/logger.h"
|
||
|
||
void MainWindow::setupWardsTab() {
|
||
wardsTab_ = new QWidget(this);
|
||
auto* layout = new QVBoxLayout(wardsTab_);
|
||
|
||
auto* toolBar = new QHBoxLayout();
|
||
wardSearchBox_ = new QLineEdit(wardsTab_);
|
||
wardSearchBox_->setPlaceholderText(tr("搜索病房..."));
|
||
connect(wardSearchBox_, &QLineEdit::textChanged, this, &MainWindow::onWardSearch);
|
||
|
||
wardAddButton_ = new QPushButton(tr("添加病房"), wardsTab_);
|
||
wardEditButton_ = new QPushButton(tr("编辑病房"), wardsTab_);
|
||
wardDeleteButton_ = new QPushButton(tr("删除病房"), wardsTab_);
|
||
wardAddBedButton_ = new QPushButton(tr("添加床位"), wardsTab_);
|
||
wardDeleteBedButton_ = new QPushButton(tr("删除床位"), wardsTab_);
|
||
wardOccupancyButton_ = new QPushButton(tr("病房使用情况"), wardsTab_);
|
||
|
||
toolBar->addWidget(wardSearchBox_);
|
||
toolBar->addWidget(wardAddButton_);
|
||
toolBar->addWidget(wardEditButton_);
|
||
toolBar->addWidget(wardDeleteButton_);
|
||
toolBar->addWidget(wardAddBedButton_);
|
||
toolBar->addWidget(wardDeleteBedButton_);
|
||
toolBar->addWidget(wardOccupancyButton_);
|
||
toolBar->addStretch(1);
|
||
layout->addLayout(toolBar);
|
||
|
||
wardTreeView_ = new QTreeWidget(wardsTab_);
|
||
wardTreeView_->setColumnCount(6);
|
||
wardTreeView_->setHeaderLabels({tr("WardID"), tr("Department"), tr("Type"), tr("MaxBeds"), tr("FreeBeds"), tr("Occupancy")});
|
||
wardTreeView_->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||
wardTreeView_->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||
wardTreeView_->header()->setSectionResizeMode(QHeaderView::Stretch);
|
||
layout->addWidget(wardTreeView_);
|
||
|
||
connect(wardAddButton_, &QPushButton::clicked, this, &MainWindow::handleAddWard);
|
||
connect(wardEditButton_, &QPushButton::clicked, this, &MainWindow::handleEditWard);
|
||
connect(wardDeleteButton_, &QPushButton::clicked, this, &MainWindow::handleDeleteWard);
|
||
connect(wardAddBedButton_, &QPushButton::clicked, this, &MainWindow::handleAddBed);
|
||
connect(wardDeleteBedButton_, &QPushButton::clicked, this, &MainWindow::handleDeleteBed);
|
||
connect(wardOccupancyButton_, &QPushButton::clicked, this, &MainWindow::handleWardOccupancy);
|
||
connect(wardTreeView_, &QTreeWidget::itemDoubleClicked, this, &MainWindow::onWardItemDoubleClicked);
|
||
}
|
||
|
||
void MainWindow::refreshWardTable() {
|
||
wardTreeView_->clear();
|
||
wardTreeView_->setColumnCount(6);
|
||
wardTreeView_->setHeaderLabels({tr("病房ID"), tr("归属科室"), tr("类型"), tr("最大床位数"), tr("空闲床位"), tr("占用率")});
|
||
|
||
core_.wardService.for_eachWard([this](const std::string&, const Ward& ward) {
|
||
auto* wardItem = new QTreeWidgetItem(wardTreeView_);
|
||
wardItem->setText(0, QString::fromStdString(ward.WardID));
|
||
wardItem->setText(1, QString::fromStdString(ward.DepartmentID));
|
||
wardItem->setText(2, wardTypeToText(ward.Type));
|
||
wardItem->setText(3, QString::number(ward.MaxBeds));
|
||
wardItem->setText(4, QString::number(ward.freeBedCount()));
|
||
wardItem->setText(5, QString("%1%%").arg(int(ward.occupancyRate() * 100)));
|
||
|
||
for (const auto& bed : ward.Beds) {
|
||
auto* bedItem = new QTreeWidgetItem(wardItem);
|
||
bedItem->setText(0, QString::fromStdString("Bed: " + bed.BedID));
|
||
bedItem->setText(1, QString::fromStdString(bed.Status == BedStatus::Occupied ? "Occupied" : "Free"));
|
||
bedItem->setText(2, QString::fromStdString(bed.PatientID.empty() ? "-" : bed.PatientID));
|
||
bedItem->setText(3, "");
|
||
bedItem->setText(4, "-");
|
||
bedItem->setText(5, "-");
|
||
}
|
||
});
|
||
}
|
||
|
||
void MainWindow::handleAddWard() {
|
||
QDialog* dialog = new QDialog(this);
|
||
dialog->setWindowTitle(tr("添加病房"));
|
||
dialog->setModal(true);
|
||
dialog->resize(450, 250);
|
||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||
|
||
QFormLayout* form = new QFormLayout(dialog);
|
||
form->setSpacing(10);
|
||
form->setContentsMargins(20, 20, 20, 20);
|
||
|
||
QString newWardId = QString::fromStdString(Ward::generateUniqueId());
|
||
QLabel* wardIdDisplay = new QLabel(newWardId, dialog);
|
||
wardIdDisplay->setEnabled(false);
|
||
|
||
QComboBox* deptCombo = new QComboBox(dialog);
|
||
deptCombo->addItem(tr("-- 请选择科室 --"));
|
||
core_.departmentService.for_eachDepartment([deptCombo](const std::string&, const Department& d) {
|
||
deptCombo->addItem(QString::fromStdString(d.Name), QString::fromStdString(d.DepartmentID));
|
||
});
|
||
|
||
QComboBox* typeCombo = new QComboBox(dialog);
|
||
typeCombo->addItems({tr("普通病房"), tr("特需病房"), tr("ICU")});
|
||
|
||
QSpinBox* maxBedsSpin = new QSpinBox(dialog);
|
||
maxBedsSpin->setRange(0, 1000);
|
||
maxBedsSpin->setValue(0);
|
||
|
||
QLabel* infoLabel = new QLabel(tr("病房ID将自动生成"), dialog);
|
||
infoLabel->setStyleSheet("color: gray; font-size: 11px;");
|
||
|
||
form->addRow(tr("病房ID (自动生成):"), wardIdDisplay);
|
||
form->addRow(tr("科室:"), deptCombo);
|
||
form->addRow(tr("类型:"), typeCombo);
|
||
form->addRow(tr("最大床位数:"), maxBedsSpin);
|
||
form->addRow(infoLabel);
|
||
|
||
auto* buttonLayout = new QHBoxLayout();
|
||
auto* okButton = new QPushButton(tr("保存"), dialog);
|
||
auto* cancelButton = new QPushButton(tr("取消"), dialog);
|
||
buttonLayout->addWidget(okButton);
|
||
buttonLayout->addWidget(cancelButton);
|
||
buttonLayout->addStretch();
|
||
form->addRow(buttonLayout);
|
||
|
||
connect(okButton, &QPushButton::clicked, [this, dialog, deptCombo, typeCombo, maxBedsSpin, newWardId]() {
|
||
if (deptCombo->currentIndex() == 0) {
|
||
QMessageBox::warning(this, tr("错误"), tr("请选择科室"));
|
||
return;
|
||
}
|
||
|
||
Ward ward(newWardId.toStdString(), deptCombo->currentData().toString().toStdString(), parseWardType(typeCombo->currentText()), maxBedsSpin->value());
|
||
if (!core_.wardService.addWard(ward)) {
|
||
QMessageBox::warning(this, tr("添加失败"), tr("病房 ID 已存在"));
|
||
return;
|
||
}
|
||
|
||
std::string wardDetails =
|
||
"病房ID: " + newWardId.toStdString() +
|
||
" | 科室: " + deptCombo->currentText().toStdString() +
|
||
" | 科室ID: " + (deptCombo->count() > deptCombo->currentIndex() ?
|
||
deptCombo->currentData().toString().toStdString() : "未知") +
|
||
" | 类型: " + typeCombo->currentText().toStdString() +
|
||
" | 最大床位数: " + std::to_string(maxBedsSpin->value());
|
||
logOperation(LogEntryType::WARD_OPERATION, "ADD_WARD", wardDetails, newWardId.toStdString());
|
||
|
||
QMessageBox::information(this, tr("成功"), tr("已添加病房: %1").arg(newWardId));
|
||
refreshWardTable();
|
||
refreshDashboard();
|
||
dialog->accept();
|
||
});
|
||
|
||
connect(cancelButton, &QPushButton::clicked, dialog, &QDialog::reject);
|
||
dialog->exec();
|
||
}
|
||
|
||
void MainWindow::handleAddBed() {
|
||
QDialog* dialog = new QDialog(this);
|
||
dialog->setWindowTitle(tr("添加床位"));
|
||
dialog->setModal(true);
|
||
dialog->resize(450, 200);
|
||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||
|
||
QFormLayout* form = new QFormLayout(dialog);
|
||
form->setSpacing(10);
|
||
form->setContentsMargins(20, 20, 20, 20);
|
||
|
||
QComboBox* wardCombo = new QComboBox(dialog);
|
||
wardCombo->addItem(tr("-- 选择病房 --"));
|
||
core_.wardService.for_eachWard([this, &wardCombo](const std::string&, const Ward& ward) {
|
||
QString deptName = QString::fromStdString(ward.DepartmentID);
|
||
auto* dept = core_.departmentService.findDepartment(ward.DepartmentID);
|
||
if (dept) {
|
||
deptName = QString::fromStdString(dept->Name);
|
||
}
|
||
QString display = QString("%1 (%2) - 空床: %3/%4")
|
||
.arg(QString::fromStdString(ward.WardID))
|
||
.arg(deptName)
|
||
.arg(ward.freeBedCount())
|
||
.arg(ward.MaxBeds);
|
||
wardCombo->addItem(display, QString::fromStdString(ward.WardID));
|
||
});
|
||
|
||
QLabel* bedIdDisplay = new QLabel(tr("请先选择病房"), dialog);
|
||
bedIdDisplay->setEnabled(false);
|
||
|
||
form->addRow(tr("选择病房:"), wardCombo);
|
||
form->addRow(tr("床位ID (自动生成):"), bedIdDisplay);
|
||
|
||
auto* buttonLayout = new QHBoxLayout();
|
||
auto* okButton = new QPushButton(tr("添加"), dialog);
|
||
auto* cancelButton = new QPushButton(tr("取消"), dialog);
|
||
buttonLayout->addWidget(okButton);
|
||
buttonLayout->addWidget(cancelButton);
|
||
buttonLayout->addStretch();
|
||
form->addRow(buttonLayout);
|
||
|
||
connect(wardCombo, QOverload<int>::of(&QComboBox::currentIndexChanged), [this, wardCombo, bedIdDisplay](int index) {
|
||
if (index == 0) {
|
||
bedIdDisplay->setText(tr("请先选择病房"));
|
||
return;
|
||
}
|
||
QString wardId = wardCombo->currentData().toString();
|
||
auto* ward = core_.wardService.findWard(wardId.toStdString());
|
||
if (!ward) return;
|
||
|
||
QString newBedId = QString::fromStdString(Bed::generateUniqueId());
|
||
bedIdDisplay->setText(newBedId);
|
||
});
|
||
|
||
connect(okButton, &QPushButton::clicked, [this, wardCombo, bedIdDisplay, dialog]() {
|
||
if (wardCombo->currentIndex() == 0) {
|
||
QMessageBox::warning(this, tr("错误"), tr("请选择病房"));
|
||
return;
|
||
}
|
||
QString wardId = wardCombo->currentData().toString();
|
||
QString bedId = bedIdDisplay->text();
|
||
|
||
if (!core_.wardService.addBed(wardId.toStdString(), bedId.toStdString())) {
|
||
QMessageBox::warning(this, tr("添加失败"), tr("床位已存在"));
|
||
return;
|
||
}
|
||
|
||
auto* ward = core_.wardService.findWard(wardId.toStdString());
|
||
|
||
std::string bedDetails =
|
||
"病房ID: " + wardId.toStdString() +
|
||
" | 床位ID: " + bedId.toStdString() +
|
||
" | 病房类型: " + (ward ? wardTypeToText(ward->Type).toStdString() : "未知") +
|
||
" | 科室: " + (ward ? ward->DepartmentID : "未知") +
|
||
" | 操作: 新增床位";
|
||
logOperation(LogEntryType::WARD_OPERATION, "ADD_BED", bedDetails, wardId.toStdString());
|
||
|
||
QMessageBox::information(this, tr("成功"), tr("已添加床位: %1 到病房: %2").arg(bedId).arg(wardId));
|
||
refreshWardTable();
|
||
dialog->accept();
|
||
});
|
||
|
||
connect(cancelButton, &QPushButton::clicked, dialog, &QDialog::reject);
|
||
dialog->exec();
|
||
}
|
||
|
||
void MainWindow::handleDeleteBed() {
|
||
QTreeWidgetItem* item = wardTreeView_->currentItem();
|
||
if (!item || item->parent() == nullptr) {
|
||
QMessageBox::warning(this, tr("删除床位"), tr("请先选择一个床位"));
|
||
return;
|
||
}
|
||
|
||
QString bedText = item->text(0);
|
||
if (!bedText.startsWith("Bed: ")) {
|
||
QMessageBox::warning(this, tr("删除床位"), tr("请选择一个床位"));
|
||
return;
|
||
}
|
||
QString bedId = bedText.mid(5);
|
||
QString wardId = item->parent()->text(0);
|
||
QString patientId = item->text(2);
|
||
|
||
if (!patientId.isEmpty() && patientId != "-") {
|
||
QMessageBox::warning(this, tr("删除失败"),
|
||
tr("床位 %1 上还有患者 %2,无法删除。\n请先让患者出院后再删除床位。").arg(bedId).arg(patientId));
|
||
return;
|
||
}
|
||
|
||
if (!core_.wardService.removeBed(wardId.toStdString(), bedId.toStdString())) {
|
||
QMessageBox::warning(this, tr("删除失败"), tr("无法删除床位"));
|
||
return;
|
||
}
|
||
|
||
std::string bedDetails =
|
||
"病房ID: " + wardId.toStdString() +
|
||
" | 床位ID: " + bedId.toStdString() +
|
||
" | 状态: 空床 | 操作: 删除了空床位";
|
||
logOperation(LogEntryType::WARD_OPERATION, "REMOVE_BED", bedDetails, wardId.toStdString());
|
||
|
||
QMessageBox::information(this, tr("成功"), tr("已删除床位: %1").arg(bedId));
|
||
|
||
refreshWardTable();
|
||
refreshPatientTable();
|
||
refreshDashboard();
|
||
}
|
||
|
||
void MainWindow::handleEditWard() {
|
||
QTreeWidgetItem* item = wardTreeView_->currentItem();
|
||
if (!item || item->parent() != nullptr) {
|
||
QMessageBox::warning(this, tr("编辑病房"), tr("请选择一个病房"));
|
||
return;
|
||
}
|
||
|
||
QString wardId = item->text(0);
|
||
auto* ward = core_.wardService.findWard(wardId.toStdString());
|
||
if (!ward) return;
|
||
|
||
QDialog* dialog = new QDialog(this);
|
||
dialog->setWindowTitle(tr("编辑病房 - %1").arg(wardId));
|
||
dialog->setModal(true);
|
||
dialog->resize(450, 300);
|
||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||
|
||
QFormLayout* form = new QFormLayout(dialog);
|
||
|
||
QLabel* wardIdLabel = new QLabel(wardId, dialog);
|
||
wardIdLabel->setEnabled(false);
|
||
|
||
QComboBox* deptCombo = new QComboBox(dialog);
|
||
deptCombo->addItem(tr("-- 请选择科室 --"));
|
||
core_.departmentService.for_eachDepartment([deptCombo](const std::string&, const Department& d) {
|
||
deptCombo->addItem(QString::fromStdString(d.Name), QString::fromStdString(d.DepartmentID));
|
||
});
|
||
for (int i = 1; i < deptCombo->count(); ++i) {
|
||
if (deptCombo->itemData(i).toString().toStdString() == ward->DepartmentID) {
|
||
deptCombo->setCurrentIndex(i);
|
||
break;
|
||
}
|
||
}
|
||
|
||
QComboBox* typeCombo = new QComboBox(dialog);
|
||
typeCombo->addItems({tr("普通病房"), tr("特需病房"), tr("ICU")});
|
||
int typeIdx = (ward->Type == WardType::Special) ? 1 : (ward->Type == WardType::ICU ? 2 : 0);
|
||
typeCombo->setCurrentIndex(typeIdx);
|
||
|
||
QSpinBox* maxBedsSpin = new QSpinBox(dialog);
|
||
maxBedsSpin->setRange(1, 1000);
|
||
maxBedsSpin->setValue(ward->MaxBeds);
|
||
|
||
form->addRow(tr("病房ID:"), wardIdLabel);
|
||
form->addRow(tr("科室:"), deptCombo);
|
||
form->addRow(tr("类型:"), typeCombo);
|
||
form->addRow(tr("最大床位数:"), maxBedsSpin);
|
||
|
||
auto* buttonLayout = new QHBoxLayout();
|
||
auto* okButton = new QPushButton(tr("保存"), dialog);
|
||
auto* cancelButton = new QPushButton(tr("取消"), dialog);
|
||
buttonLayout->addWidget(okButton);
|
||
buttonLayout->addWidget(cancelButton);
|
||
buttonLayout->addStretch();
|
||
form->addRow(buttonLayout);
|
||
|
||
connect(okButton, &QPushButton::clicked, [this, dialog, wardId, deptCombo, typeCombo, maxBedsSpin]() {
|
||
if (deptCombo->currentIndex() == 0) {
|
||
QMessageBox::warning(this, tr("错误"), tr("请选择科室"));
|
||
return;
|
||
}
|
||
|
||
auto* ward = core_.wardService.findWard(wardId.toStdString());
|
||
if (ward) {
|
||
std::string oldDetails =
|
||
"修改前 - 科室: " + ward->DepartmentID +
|
||
" | 类型: " + std::to_string(static_cast<int>(ward->Type)) +
|
||
" | 最大床位数: " + std::to_string(ward->MaxBeds);
|
||
|
||
ward->DepartmentID = deptCombo->currentData().toString().toStdString();
|
||
ward->Type = parseWardType(typeCombo->currentText());
|
||
ward->MaxBeds = maxBedsSpin->value();
|
||
|
||
std::string newDetails =
|
||
"修改后 - 科室: " + ward->DepartmentID +
|
||
" | 类型: " + std::to_string(static_cast<int>(ward->Type)) +
|
||
" | 最大床位数: " + std::to_string(ward->MaxBeds);
|
||
|
||
std::string fullDetails = "病房ID: " + wardId.toStdString() + " | " + oldDetails + "\n" + newDetails;
|
||
logOperation(LogEntryType::WARD_OPERATION, "MODIFY_WARD", fullDetails, wardId.toStdString());
|
||
|
||
QMessageBox::information(this, tr("成功"), tr("已更新病房: %1").arg(wardId));
|
||
refreshWardTable();
|
||
dialog->accept();
|
||
}
|
||
});
|
||
|
||
connect(cancelButton, &QPushButton::clicked, dialog, &QDialog::reject);
|
||
dialog->exec();
|
||
}
|
||
|
||
void MainWindow::handleDeleteWard() {
|
||
QTreeWidgetItem* item = wardTreeView_->currentItem();
|
||
if (!item || item->parent() != nullptr) {
|
||
QMessageBox::warning(this, tr("删除病房"), tr("请选择一个病房"));
|
||
return;
|
||
}
|
||
|
||
QString wardId = item->text(0);
|
||
auto* ward = core_.wardService.findWard(wardId.toStdString());
|
||
if (!ward) return;
|
||
|
||
if (ward->occupiedBedCount() > 0) {
|
||
QMessageBox::warning(this, tr("删除失败"),
|
||
tr("病房 %1 还有患者正在住院,无法删除。\n请先让所有患者出院后再删除病房。").arg(wardId));
|
||
return;
|
||
}
|
||
|
||
QMessageBox::StandardButton reply = QMessageBox::question(
|
||
this, tr("确认删除"),
|
||
tr("确定要删除病房 %1 吗?\n此操作无法撤销,将同时删除该病房下的所有床位。").arg(wardId),
|
||
QMessageBox::Yes | QMessageBox::No);
|
||
if (reply != QMessageBox::Yes) return;
|
||
|
||
QString deptName = QString::fromStdString(ward->DepartmentID);
|
||
auto* dept = core_.departmentService.findDepartment(ward->DepartmentID);
|
||
if (dept) {
|
||
deptName = QString::fromStdString(dept->Name);
|
||
}
|
||
|
||
std::string wardDetails =
|
||
"病房ID: " + wardId.toStdString() +
|
||
" | 科室: " + deptName.toStdString() +
|
||
" | 类型: " + wardTypeToText(ward->Type).toStdString() +
|
||
" | 最大床位数: " + std::to_string(ward->MaxBeds) +
|
||
" | 操作: 删除病房";
|
||
logOperation(LogEntryType::WARD_OPERATION, "REMOVE_WARD", wardDetails, wardId.toStdString());
|
||
|
||
if (!core_.wardService.removeWard(wardId.toStdString())) {
|
||
QMessageBox::warning(this, tr("删除失败"), tr("无法删除病房"));
|
||
return;
|
||
}
|
||
|
||
QMessageBox::information(this, tr("成功"), tr("已删除病房: %1").arg(wardId));
|
||
refreshWardTable();
|
||
refreshDashboard();
|
||
}
|
||
|
||
void MainWindow::handleWardOccupancy() {
|
||
QDialog* dialog = new QDialog(this);
|
||
dialog->setWindowTitle(tr("病房使用情况"));
|
||
dialog->setModal(true);
|
||
dialog->resize(800, 550);
|
||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||
|
||
QVBoxLayout* mainLayout = new QVBoxLayout(dialog);
|
||
|
||
QGroupBox* filterGroup = new QGroupBox(tr("筛选条件"), dialog);
|
||
QFormLayout* filterLayout = new QFormLayout(filterGroup);
|
||
|
||
QComboBox* wardTypeFilter = new QComboBox(filterGroup);
|
||
wardTypeFilter->addItems({tr("全部"), tr("普通病房"), tr("特需病房"), tr("ICU")});
|
||
|
||
QComboBox* wardGradeFilter = new QComboBox(filterGroup);
|
||
wardGradeFilter->addItems({tr("全部"), tr("高占用率 (>=80%)"), tr("中占用率 (40-80%)"), tr("低占用率 (<40%)")});
|
||
|
||
QPushButton* applyFilterBtn = new QPushButton(tr("应用筛选"), filterGroup);
|
||
|
||
filterLayout->addRow(tr("病房类型:"), wardTypeFilter);
|
||
filterLayout->addRow(tr("占用率筛选:"), wardGradeFilter);
|
||
filterLayout->addWidget(applyFilterBtn);
|
||
mainLayout->addWidget(filterGroup);
|
||
|
||
QTableWidget* summaryTable = new QTableWidget(dialog);
|
||
summaryTable->setColumnCount(7);
|
||
summaryTable->setHorizontalHeaderLabels({tr("病房ID"), tr("科室"), tr("类型"), tr("总床位"), tr("已占用"), tr("空闲"), tr("占用率")});
|
||
summaryTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||
summaryTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||
summaryTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||
mainLayout->addWidget(summaryTable);
|
||
|
||
QGroupBox* detailGroup = new QGroupBox(tr("床位详情"), dialog);
|
||
QVBoxLayout* detailLayout = new QVBoxLayout(detailGroup);
|
||
|
||
QTableWidget* bedDetailTable = new QTableWidget(detailGroup);
|
||
bedDetailTable->setColumnCount(4);
|
||
bedDetailTable->setHorizontalHeaderLabels({tr("床位ID"), tr("状态"), tr("患者"), tr("备注")});
|
||
bedDetailTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||
bedDetailTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||
bedDetailTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||
detailLayout->addWidget(bedDetailTable);
|
||
mainLayout->addWidget(detailGroup);
|
||
|
||
struct WardSummaryData {
|
||
QString wardId;
|
||
QString department;
|
||
QString type;
|
||
int totalBeds;
|
||
int occupied;
|
||
int free;
|
||
double rate;
|
||
};
|
||
QList<WardSummaryData> wardSummaries;
|
||
|
||
auto refreshData = [this, &wardSummaries, summaryTable, wardTypeFilter, wardGradeFilter]() {
|
||
wardSummaries.clear();
|
||
QString typeFilter = wardTypeFilter->currentText();
|
||
QString gradeFilter = wardGradeFilter->currentText();
|
||
|
||
core_.wardService.for_eachWard([this, typeFilter, gradeFilter, &wardSummaries](const std::string&, const Ward& ward) {
|
||
QString wardType = wardTypeToText(ward.Type);
|
||
double rate = ward.occupancyRate();
|
||
|
||
bool matches = true;
|
||
if (typeFilter != "全部") {
|
||
matches = false;
|
||
if (typeFilter == "普通病房" && ward.Type == WardType::Normal) matches = true;
|
||
else if (typeFilter == "特需病房" && ward.Type == WardType::Special) matches = true;
|
||
else if (typeFilter == "ICU" && ward.Type == WardType::ICU) matches = true;
|
||
}
|
||
if (!matches) return;
|
||
if (gradeFilter == "高占用率 (>=80%)" && rate < 0.8) return;
|
||
else if (gradeFilter == "中占用率 (40-80%)" && (rate < 0.4 || rate > 0.8)) return;
|
||
else if (gradeFilter == "低占用率 (<40%)" && rate >= 0.4) return;
|
||
|
||
WardSummaryData ws;
|
||
ws.wardId = QString::fromStdString(ward.WardID);
|
||
ws.department = QString::fromStdString(ward.DepartmentID);
|
||
auto* dept = core_.departmentService.findDepartment(ward.DepartmentID);
|
||
if (dept) {
|
||
ws.department = QString::fromStdString(dept->Name);
|
||
}
|
||
ws.type = wardType;
|
||
ws.totalBeds = ward.MaxBeds;
|
||
ws.occupied = ward.occupiedBedCount();
|
||
ws.free = ward.freeBedCount();
|
||
ws.rate = rate;
|
||
wardSummaries.append(ws);
|
||
});
|
||
|
||
summaryTable->setRowCount(wardSummaries.size());
|
||
for (int i = 0; i < wardSummaries.size(); ++i) {
|
||
const auto& ws = wardSummaries[i];
|
||
summaryTable->setItem(i, 0, new QTableWidgetItem(ws.wardId));
|
||
summaryTable->setItem(i, 1, new QTableWidgetItem(ws.department));
|
||
summaryTable->setItem(i, 2, new QTableWidgetItem(ws.type));
|
||
summaryTable->setItem(i, 3, new QTableWidgetItem(QString::number(ws.totalBeds)));
|
||
summaryTable->setItem(i, 4, new QTableWidgetItem(QString::number(ws.occupied)));
|
||
summaryTable->setItem(i, 5, new QTableWidgetItem(QString::number(ws.free)));
|
||
summaryTable->setItem(i, 6, new QTableWidgetItem(QString("%1%").arg(int(ws.rate * 100))));
|
||
}
|
||
};
|
||
|
||
refreshData();
|
||
|
||
connect(summaryTable, &QTableWidget::itemSelectionChanged, [this, summaryTable, bedDetailTable]() {
|
||
int row = summaryTable->currentRow();
|
||
if (row < 0) return;
|
||
QString wardId = summaryTable->item(row, 0)->text();
|
||
|
||
auto* ward = core_.wardService.findWard(wardId.toStdString());
|
||
if (!ward) return;
|
||
|
||
bedDetailTable->setRowCount(ward->Beds.size());
|
||
for (size_t i = 0; i < ward->Beds.size(); ++i) {
|
||
const auto& bed = ward->Beds[i];
|
||
bedDetailTable->setItem(static_cast<int>(i), 0, new QTableWidgetItem(QString::fromStdString(bed.BedID)));
|
||
bedDetailTable->setItem(static_cast<int>(i), 1, new QTableWidgetItem(bed.Status == BedStatus::Occupied ? tr("已占用") : tr("空闲")));
|
||
bedDetailTable->setItem(static_cast<int>(i), 2, new QTableWidgetItem(bed.PatientID.empty() ? "-" : QString::fromStdString(bed.PatientID)));
|
||
bedDetailTable->setItem(static_cast<int>(i), 3, new QTableWidgetItem(""));
|
||
}
|
||
});
|
||
|
||
connect(applyFilterBtn, &QPushButton::clicked, refreshData);
|
||
dialog->exec();
|
||
}
|
||
|
||
void MainWindow::onWardSearch(const QString& text) {
|
||
for (int i = 0; i < wardTreeView_->topLevelItemCount(); ++i) {
|
||
auto* item = wardTreeView_->topLevelItem(i);
|
||
bool match = item->text(0).contains(text, Qt::CaseInsensitive) ||
|
||
item->text(1).contains(text, Qt::CaseInsensitive);
|
||
item->setHidden(!match);
|
||
}
|
||
}
|
||
|
||
void MainWindow::onWardItemDoubleClicked(QTreeWidgetItem* item, int column) {
|
||
if (!item) return;
|
||
|
||
QString itemText = item->text(0);
|
||
if (item->parent() && itemText.startsWith("Bed: ")) {
|
||
QString bedId = itemText.mid(5);
|
||
QString wardId = item->parent()->text(0);
|
||
|
||
QDialog* dialog = new QDialog(this);
|
||
dialog->setWindowTitle(tr("编辑床位 - %1").arg(bedId));
|
||
dialog->setModal(true);
|
||
dialog->resize(400, 200);
|
||
dialog->setAttribute(Qt::WA_DeleteOnClose);
|
||
|
||
QFormLayout* form = new QFormLayout(dialog);
|
||
|
||
QLabel* bedIdLabel = new QLabel(bedId, dialog);
|
||
bedIdLabel->setEnabled(false);
|
||
|
||
QString patientId = item->text(2);
|
||
QString status = item->text(1);
|
||
|
||
QComboBox* statusCombo = new QComboBox(dialog);
|
||
statusCombo->addItems({tr("Free"), tr("Occupied")});
|
||
statusCombo->setCurrentIndex(status.contains("Occupied") ? 1 : 0);
|
||
|
||
QLineEdit* patientEdit = new QLineEdit(patientId == "-" ? "" : patientId, dialog);
|
||
|
||
form->addRow(tr("床位ID:"), bedIdLabel);
|
||
form->addRow(tr("状态:"), statusCombo);
|
||
form->addRow(tr("患者ID:"), patientEdit);
|
||
|
||
auto* buttonLayout = new QHBoxLayout();
|
||
auto* okButton = new QPushButton(tr("保存"), dialog);
|
||
auto* cancelButton = new QPushButton(tr("取消"), dialog);
|
||
buttonLayout->addWidget(okButton);
|
||
buttonLayout->addWidget(cancelButton);
|
||
buttonLayout->addStretch();
|
||
form->addRow(buttonLayout);
|
||
|
||
connect(okButton, &QPushButton::clicked, [this, dialog, wardId, bedId, statusCombo, patientEdit]() {
|
||
BedStatus newStatus = (statusCombo->currentIndex() == 0) ? BedStatus::Free : BedStatus::Occupied;
|
||
|
||
auto* ward = core_.wardService.findWard(wardId.toStdString());
|
||
if (ward) {
|
||
for (auto& bed : ward->Beds) {
|
||
if (bed.BedID == bedId.toStdString()) {
|
||
bed.Status = newStatus;
|
||
if (newStatus == BedStatus::Occupied) {
|
||
bed.PatientID = patientEdit->text().toStdString();
|
||
} else {
|
||
bed.PatientID = "";
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
QMessageBox::information(this, tr("成功"), tr("床位信息已更新"));
|
||
refreshWardTable();
|
||
dialog->accept();
|
||
}
|
||
});
|
||
|
||
connect(cancelButton, &QPushButton::clicked, dialog, &QDialog::reject);
|
||
dialog->exec();
|
||
}
|
||
}
|