#pragma execution_character_set("utf-8") #include "qhistoryorderdialog.h" #include "qbigordermanager.h" #include #include #include #include #include #include QHistoryOrderDialog::QHistoryOrderDialog(QWidget *parent) : QDialog(parent), m_dateSelector(new QDateEdit(this)), m_orderTypeFilter(new QComboBox(this)), m_stockCodeFilter(new QLineEdit(this)), m_tableView(new QTableView(this)), m_exportButton(new QPushButton("导出数据", this)), m_statsLabel(new QLabel(this)), m_model(new QStandardItemModel(this)), m_proxyModel(new QSortFilterProxyModel(this)), m_typeDelegate(new OrderTypeDelegate(this)), m_numberDelegate(new NumberFormatDelegate(this)) { setWindowTitle("历史订单查询"); setMinimumSize(800, 600); m_historyPath = QCoreApplication::applicationDirPath() + QString("/history"); initUI(); onDateChanged(QDate::currentDate()); } void QHistoryOrderDialog::initUI() { QVBoxLayout *mainLayout = new QVBoxLayout(this); // 顶部控制区域 QHBoxLayout *topLayout = new QHBoxLayout(); // 日期选择器 m_dateSelector->setDate(QDate::currentDate()); m_dateSelector->setCalendarPopup(true); topLayout->addWidget(new QLabel("选择日期:")); topLayout->addWidget(m_dateSelector); // 股票代码过滤 m_stockCodeFilter->setPlaceholderText("股票代码过滤"); topLayout->addWidget(new QLabel("股票代码:")); topLayout->addWidget(m_stockCodeFilter); // 订单类型过滤 m_orderTypeFilter->addItem("全部", ""); m_orderTypeFilter->addItem("买入", "BID"); m_orderTypeFilter->addItem("卖出", "ASK"); topLayout->addWidget(new QLabel("订单类型:")); topLayout->addWidget(m_orderTypeFilter); // 导出按钮 topLayout->addStretch(); topLayout->addWidget(m_exportButton); mainLayout->addLayout(topLayout); // 统计信息 QHBoxLayout *statsLayout = new QHBoxLayout(); statsLayout->addWidget(m_statsLabel); statsLayout->addStretch(); mainLayout->addLayout(statsLayout); // 表格视图 m_proxyModel->setSourceModel(m_model); m_tableView->setItemDelegateForColumn(2, m_typeDelegate); m_tableView->setItemDelegateForColumn(3, m_numberDelegate); m_tableView->setModel(m_proxyModel); m_tableView->setSortingEnabled(true); m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); m_tableView->setSelectionBehavior(QAbstractItemView::SelectRows); // 设置表头 m_model->setHorizontalHeaderLabels( QStringList() << "股票代码" << "股票名称" << "订单类型" << "股票数量" << "股票价格" << "订单档位" << "时间" ); mainLayout->addWidget(m_tableView); const int timeColumnIndex = 6; m_proxyModel->sort(timeColumnIndex, Qt::AscendingOrder); // 连接信号 connect(m_dateSelector, &QDateEdit::dateChanged, this, &QHistoryOrderDialog::onDateChanged); connect(m_stockCodeFilter, &QLineEdit::textChanged, this, &QHistoryOrderDialog::onFilterChanged); connect(m_orderTypeFilter, QOverload::of(&QComboBox::currentIndexChanged), this, &QHistoryOrderDialog::onFilterChanged); connect(m_exportButton, &QPushButton::clicked, this, &QHistoryOrderDialog::onExportClicked); } void QHistoryOrderDialog::onDateChanged(const QDate &date) { loadOrdersForDate(date); } void QHistoryOrderDialog::loadOrdersForDate(const QDate &date) { auto orders = getHistoryOrders(date); m_model->removeRows(0, m_model->rowCount()); for (const auto& order : orders) { QList rowItems; rowItems << new QStandardItem(order->code); rowItems << new QStandardItem(order->name); rowItems << new QStandardItem(order->nBigOrderType == 0 ? "卖出" : "买入"); rowItems << new QStandardItem(QString::number(std::fabs(order->volume / 1000)) + "K"); rowItems << new QStandardItem(QString::number(order->price, 'f', 2)); rowItems << new QStandardItem(QString::number(order->level)); QString str = order->svrRecvTime.mid(11); if (str == nullptr) { QDateTime dateTime = QDateTime::currentDateTime(); str = dateTime.toString("hh:mm:ss"); } rowItems << new QStandardItem(str); m_model->appendRow(rowItems); } updateStatistics(orders); } void QHistoryOrderDialog::updateStatistics(const QList>& orders) { int buyCount = 0, sellCount = 0; double totalBuyAmount = 0, totalSellAmount = 0; for (const auto& order : orders) { double value = order->price * order->volume; if (order->nBigOrderType) { buyCount++; totalBuyAmount += value; } else { sellCount++; totalSellAmount += value; } } QString stats = QString("总订单: %1 笔 | 买入: %2 笔 (%3 万) | 卖出: %4 笔 (%5 万)") .arg(orders.size()) .arg(buyCount) .arg(totalBuyAmount / 10000, 0, 'f', 1) .arg(sellCount) .arg(totalSellAmount / 10000, 0, 'f', 1); m_statsLabel->setText(stats); } void QHistoryOrderDialog::onFilterChanged() { QString stockCode = m_stockCodeFilter->text().trimmed(); QString orderType = m_orderTypeFilter->currentData().toString(); // 设置股票代码过滤 m_proxyModel->setFilterKeyColumn(0); m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive); m_proxyModel->setFilterFixedString(stockCode); // 设置订单类型过滤 if (!orderType.isEmpty()) { m_proxyModel->setFilterKeyColumn(2); m_proxyModel->setFilterFixedString(orderType == "ASK" ? "卖出" : "买入"); } } void QHistoryOrderDialog::onExportClicked() { QString fileName = QFileDialog::getSaveFileName(this, "导出历史数据", "", "CSV文件 (*.csv)"); if (fileName.isEmpty()) return; QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; QTextStream out(&file); out.setCodec("GBK"); // 写入表头 for (int col = 0; col < m_model->columnCount(); ++col) { out << m_model->headerData(col, Qt::Horizontal).toString(); if (col < m_model->columnCount() - 1) out << ","; } out << "\n"; // 写入数据 for (int row = 0; row < m_proxyModel->rowCount(); ++row) { for (int col = 0; col < m_proxyModel->columnCount(); ++col) { out << m_proxyModel->index(row, col).data().toString(); if (col < m_proxyModel->columnCount() - 1) out << ","; } out << "\n"; } file.close(); m_statsLabel->setText(QString("数据已导出到: %1").arg(fileName)); } QList> QHistoryOrderDialog::getHistoryOrders(const QDate& date) const { QMutexLocker locker(&m_cacheMutex); // 检查缓存 if (m_historyCache.contains(date)) { return m_historyCache[date]; } QString filePath = QString("%1/bigorders_%2.json") .arg(m_historyPath) .arg(date.toString("yyyyMMdd")); if (!QFile::exists(filePath)) { return QList>(); } QFile file(filePath); if (!file.open(QIODevice::ReadOnly)) { qWarning() << "Failed to open history file:" << filePath; return QList>(); } QList> orders; QTextStream in(&file); in.setCodec("UTF-8"); while (!in.atEnd()) { QJsonParseError error; QJsonDocument doc = QJsonDocument::fromJson(in.readLine().toUtf8(), &error); if (error.error == QJsonParseError::NoError && doc.isObject()) { BigOrderInfo order = BigOrderInfo::fromJson(doc.object()); orders.append(QSharedPointer::create(order)); //if (order.isValid()) { //} } } file.close(); // 缓存结果 m_historyCache.insert(date, orders); return orders; } QList QHistoryOrderDialog::getAvailableDates() const { QList dates; QDir historyDir(m_historyPath); QStringList files = historyDir.entryList(QStringList() << "bigorders_*.json", QDir::Files); for (const QString& file : files) { QString dateStr = file.mid(10, 8); // bigorders_20230101.json QDate date = QDate::fromString(dateStr, "yyyyMMdd"); if (date.isValid()) { dates.append(date); } } std::sort(dates.begin(), dates.end()); return dates; }