#include "filterform.h" #include "recordedit.h" #include "ui_filterform.h" #include #include #include #include #include #include #include #include FilterForm::FilterForm(QWidget* parent, std::unique_ptr& sqlOpr, std::unique_ptr& comSqlOpr, std::unique_ptr& repaySqlOpr) : QDialog(parent), ui(new Ui::FilterForm), sqlOpr_(sqlOpr), comSqlOpr_(comSqlOpr), repaySqlOpr_(repaySqlOpr) { ui->setupUi(this); statistic_ = std::make_shared(repaySqlOpr_); Init(); setWindowTitle("结果"); } FilterForm::~FilterForm() { delete ui; } int FilterForm::exec() { ShowResult(); if (!over_) { return QDialog::Rejected; } return QDialog::exec(); } void FilterForm::Init() { auto* lay = new QVBoxLayout(this); tw_ = new QTableWidget(this); QStringList headers; headers << "ID" << "类型" << "分类" << "金额" << "日期" << "内容" << "备注"; tw_->setColumnCount(headers.size()); tw_->setHorizontalHeaderLabels(headers); tw_->setSelectionBehavior(QAbstractItemView::SelectRows); tw_->setColumnWidth(0, 50); tw_->setColumnWidth(1, 100); tw_->setColumnWidth(2, 100); tw_->setColumnWidth(3, 100); tw_->setColumnWidth(4, 150); tw_->setColumnWidth(5, 300); tw_->setColumnWidth(6, 100); lay->addWidget(tw_); ui->widget->setLayout(lay); ui->edCashIn->setReadOnly(true); ui->edCashOut->setReadOnly(true); ui->edCreditIn->setReadOnly(true); ui->edCreditOut->setReadOnly(true); ui->edCreditCash->setReadOnly(true); tw_->setContextMenuPolicy(Qt::CustomContextMenu); connect(tw_, &QTableWidget::customContextMenuRequested, this, &FilterForm::ShowContextMenu); } void FilterForm::ShowResult() { over_ = false; AccountRecordList list; if (!sqlOpr_->GetAccountList(list)) { QMessageBox::warning(this, "错误", QString::fromStdString(sqlOpr_->GetLastErr())); return; } result_.clear(); if (!Filter(list, result_)) { QMessageBox::warning(this, "错误", "筛选失败"); return; } if (result_.empty()) { QMessageBox::warning(this, "提示", "没有符合条件的记录"); return; } for (const auto& item : result_) { tw_->insertRow(tw_->rowCount()); int row = tw_->rowCount() - 1; auto* i1 = new QTableWidgetItem(QString::number(item.id)); i1->setFlags(i1->flags() & ~Qt::ItemIsEditable); auto* i2 = new QTableWidgetItem(QString::fromStdString(item.payType)); i2->setFlags(i2->flags() & ~Qt::ItemIsEditable); auto* i3 = new QTableWidgetItem(QString::fromStdString(item.classify)); i3->setFlags(i3->flags() & ~Qt::ItemIsEditable); auto* i4 = new QTableWidgetItem(QString::number(item.money / 100.0)); i4->setFlags(i4->flags() & ~Qt::ItemIsEditable); auto* i5 = new QTableWidgetItem(QString::fromStdString(item.dt)); i5->setFlags(i5->flags() & ~Qt::ItemIsEditable); auto* i6 = new QTableWidgetItem(QString::fromStdString(item.thing)); i6->setFlags(i6->flags() & ~Qt::ItemIsEditable); auto* i7 = new QTableWidgetItem(QString::fromStdString(item.remark)); i7->setFlags(i7->flags() & ~Qt::ItemIsEditable); tw_->setItem(row, 0, i1); tw_->setItem(row, 1, i2); tw_->setItem(row, 2, i3); tw_->setItem(row, 3, i4); tw_->setItem(row, 4, i5); tw_->setItem(row, 5, i6); tw_->setItem(row, 6, i7); } CalcShow(); over_ = true; } void FilterForm::CalcShow() { statistic_->Calculate(result_); auto* d = SharedData::instance(); ui->edCashIn->setText(QString::number(d->ttCashIn_ / 100.0)); ui->edCashOut->setText(QString::number(d->ttCashOut_ / 100.0)); ui->edCreditIn->setText(QString::number(d->ttCreditIn_ / 100.0)); ui->edCreditOut->setText(QString::number(d->ttCreditOut_ / 100.0)); ui->edCreditCash->setText(QString::number(d->ttCreditCash_ / 100.0)); ui->edCreditPay->setText(QString::number(d->ttCashPay_ / 100.0)); auto ret1 = GetClassifyCash(result_, true); auto ret2 = GetClassifyCash(result_, false); ui->lwCashCl->clear(); for (const auto& item : ret1) { ui->lwCashCl->addItem(QString("%1 => %2/%3") .arg(QString::fromStdString(item.first)) .arg(QString::number(item.second.first / 100.0)) .arg(QString::number(item.second.second / 100.0))); } ui->lwCreditCl->clear(); for (const auto& item : ret2) { ui->lwCreditCl->addItem(QString("%1 => %2/%3") .arg(QString::fromStdString(item.first)) .arg(QString::number(item.second.first / 100.0)) .arg(QString::number(item.second.second / 100.0))); } } int32_t FilterForm::rePayValue(int accID) { RepayRecordList reuslt; if (!repaySqlOpr_->GetRepayResult(reuslt, accID)) { return 0; } int32_t sum = 0; for (const auto& item : reuslt) { sum += item.money; } return sum; } bool FilterForm::Filter(const AccountRecordList& list, AccountRecordList& result) { auto* d = SharedData::instance(); result.clear(); for (const auto& item : list) { if (d->flType) { if (item.payType != d->type.toStdString()) { continue; } } if (d->flKeys) { auto qkeys = d->key.toUpper(); auto skeys = QString::fromStdString(item.thing).toUpper(); if (!skeys.contains(qkeys)) { continue; } } switch (d->filter) { case CashFilter::FIL_BETWEEN: { if (item.money < d->lowMoney || item.money > d->highMoney) { continue; } break; } case CashFilter::FIL_HIGHER: { if (item.money <= d->highMoney) { continue; } break; } case CashFilter::FIL_LOWER: { if (item.money >= d->lowMoney) { continue; } break; } default: break; } if (d->flClassify) { auto qkeys = d->classify.toUpper(); auto skeys = QString::fromStdString(item.classify).toUpper(); if (!skeys.contains(qkeys)) { continue; } } if (d->flDays) { auto days = d->days; QDateTime datetime = QDateTime::fromString(QString::fromStdString(item.dt), "yyyy-MM-dd hh:mm:ss"); QDateTime now = QDateTime::currentDateTime(); if (datetime.daysTo(now) > days) { continue; } } result.push_back(item); } return true; } std::vector>> FilterForm::GetClassifyCash(const AccountRecordList& list, bool isCash) { std::vector>> ret; std::unordered_map> classifyMap; for (const auto& item : list) { if (isCash) { if (item.payType == "现金支出") { if (!classifyMap.count(item.classify)) { classifyMap[item.classify] = {0, 0}; } classifyMap[item.classify].first += item.money; } else if (item.payType == "现金收入") { if (!classifyMap.count(item.classify)) { classifyMap[item.classify] = {0, 0}; } classifyMap[item.classify].second += item.money; } } else { if (item.payType == "信用支出") { if (!classifyMap.count(item.classify)) { classifyMap[item.classify] = {0, 0}; } classifyMap[item.classify].first += item.money; } else if (item.payType == "信用收入") { if (!classifyMap.count(item.classify)) { classifyMap[item.classify] = {0, 0}; } classifyMap[item.classify].second += item.money; } else if (item.payType == "信用借款") { // 信用借款 if (!classifyMap.count(item.classify)) { classifyMap[item.classify] = {0, 0}; } classifyMap[item.classify].first += item.money; } } } for (const auto& item : classifyMap) { ret.emplace_back(item.first, item.second); } std::sort(ret.begin(), ret.end(), [](const std::pair>& a, const std::pair>& b) { auto at = a.second.first + a.second.second; auto bt = b.second.first + b.second.second; return at > bt; }); return ret; } void FilterForm::ShowContextMenu(const QPoint& pos) { QList selectedItems = tw_->selectedItems(); if (selectedItems.isEmpty()) { return; } QMenu menu(this); if (selectedItems.size() != 7) { return; } QAction* acFile = menu.addAction("查看附件"); int id = selectedItems[0]->text().toInt(); QString fileName; for (const auto& item : result_) { if (item.id == id) { fileName = QString::fromStdString(item.additionFile); break; } } TransMenu(id, menu, selectedItems[1]); connect(acFile, &QAction::triggered, [this, selectedItems, id, fileName]() { if (fileName.isEmpty()) { QMessageBox::warning(this, "警告", "附件文件名为空"); return; } QString mediaDir = QString::fromStdString(Util::GetMediaDir()); QString filePath = QDir(mediaDir).filePath(fileName); if (!QFile::exists(filePath)) { QMessageBox::critical(this, "错误", QString("文件不存在: %1").arg(filePath)); return; } if (!QDesktopServices::openUrl(QUrl::fromLocalFile(filePath))) { QMessageBox::critical(nullptr, "错误", "无法打开图片文件"); } }); QAction* acEdit = menu.addAction("编辑"); connect(acEdit, &QAction::triggered, [this, id, selectedItems]() { RecordEdit* re = new RecordEdit(this, comSqlOpr_, repaySqlOpr_); AccountRecord* recPtr = nullptr; for (auto& item : result_) { if (item.id == id) { re->record_ = item; recPtr = &item; break; } } re->exec(); // headers << "ID" << "类型" << "分类" << "金额" << "日期" << "内容" << "备注"; if (!re->modify_) { return; } if (!sqlOpr_->UpdateAccount(re->record_)) { QMessageBox::warning(this, "错误", QString::fromStdString(sqlOpr_->GetLastErr())); return; } selectedItems[1]->setText(QString::fromStdString(re->record_.payType)); selectedItems[2]->setText(QString::fromStdString(re->record_.classify)); selectedItems[3]->setText(QString::number(re->record_.money / 100.0)); selectedItems[4]->setText(QString::fromStdString(re->record_.dt)); selectedItems[5]->setText(QString::fromStdString(re->record_.thing)); selectedItems[6]->setText(QString::fromStdString(re->record_.remark)); *recPtr = re->record_; CalcShow(); }); QAction* acDelete = menu.addAction("删除"); connect(acDelete, &QAction::triggered, [this, id, selectedItems]() { if (QMessageBox::question(this, "确认删除", "确定删除记录吗?") != QMessageBox::Yes) { return; } if (!sqlOpr_->DeleteAccount(id)) { QMessageBox::warning(this, "错误", QString::fromStdString(sqlOpr_->GetLastErr())); return; } // 从结果列表中移除记录 for (auto it = result_.begin(); it != result_.end(); ++it) { if (it->id == id) { result_.erase(it); break; } } // 从表格中移除行 tw_->removeRow(selectedItems[0]->row()); CalcShow(); }); menu.exec(tw_->viewport()->mapToGlobal(pos)); } void FilterForm::TransMenu(int id, QMenu& menu, QTableWidgetItem* item) { QString payType; for (const auto& item : result_) { if (item.id == id) { payType = QString::fromStdString(item.payType); break; } } if (payType.isEmpty()) { QMessageBox::warning(this, "警告", QString("未找到ID为%1的支付类型。").arg(id)); return; } // 根据支付类型执行不同操作 QAction* acFile = nullptr; QString pur; if (payType == "现金支出") { acFile = menu.addAction("转为信用支出"); pur = "信用支出"; } else if (payType == "现金收入") { acFile = menu.addAction("转为信用收入"); pur = "信用收入"; } else if (payType == "信用支出") { acFile = menu.addAction("转为现金支出"); pur = "现金支出"; } else if (payType == "信用收入") { acFile = menu.addAction("转为现金收入"); pur = "现金收入"; } if (acFile == nullptr) { return; } connect(acFile, &QAction::triggered, [this, id, pur, item]() { // 执行支付类型转换逻辑 if (QMessageBox::question(this, "确认转换", QString("确定将ID为%1的记录转为%2吗?").arg(id).arg(pur), QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) { // 1. 更新数据库中的支付类型 bool done = false; for (auto& item : result_) { if (item.id != id) { continue; } item.payType = pur.toStdString(); if (!sqlOpr_->UpdateAccount(item)) { QMessageBox::critical(this, "错误", "更新数据库失败"); return; } done = true; break; } if (done) { item->setText(pur); CalcShow(); QMessageBox::information(this, "成功", QString("ID为%1的记录已成功转为%2。").arg(id).arg(pur)); } } }); }