wumu
2025-11-06 fcc4de01b336e73df6788fa6129ec15162ac6701
etfstockinfo.cpp
@@ -8,6 +8,8 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QMessageBox>
#include <QDateTime>
ETFStockInfo::ETFStockInfo(QWidget *parent) :
    QMainWindow(parent),
@@ -65,11 +67,34 @@
    m_manager.get(m_request);
    qDebug()<<"请求中...";
    ui->dateTimeEdit->setDateTime(QDateTime::currentDateTime());
    ui->dateTimeEdit_3->setDateTime(QDateTime::currentDateTime());
}
ETFStockInfo::~ETFStockInfo()
{
    delete ui;
}
void ETFStockInfo::initMySQL()
{
    //添加一个数据库
      db=QSqlDatabase::addDatabase("QMYSQL");    //括号内要写出数据库的类型
      //设置数据库
      db.setHostName("127.0.0.1"); //设置数据库的主机ip
      //设置数据库的用户名
      db.setUserName("root");
      //设置数据库的密码
      db.setPassword("root");    //这个就是安装MySQL时设置的密码
      //设置数据库的名字
      db.setDatabaseName("stock_plan");
      //打开数据库(已经安装过mysql驱动了)
      if(db.open()==false){
          QMessageBox::warning(this,"waring",db.lastError().text());
      }else{
          qDebug()<<"mysql conn ok";
      }
}
void ETFStockInfo::getEtfInfo(QByteArray &buffer)
@@ -151,6 +176,9 @@
            // 添加一行数据项到模型中
            //m_model->appendRow(rowItems);
            m_model_market->appendRow(rowItems);
            // 保存etf基金的代号和名字
            m_codeNamesEtf[symbol] = name;
        }
    }
@@ -210,6 +238,64 @@
    }
}
void ETFStockInfo::getStockOne(QByteArray &buffer)
{
    QJsonDocument jd = QJsonDocument::fromJson(buffer);
    if(jd.isObject()){
        QJsonObject jObject = jd.object();
        QJsonArray jArr = jObject.value("data").toObject().value("item").toArray(); // 通过键值对取值
        int cnt = jArr.count();
        qDebug()<<"数组size:"<<cnt;
        QString symbol = jObject.value("data").toObject().value("symbol").toString();
        QString code = symbol; // 股票代号
        QString name = m_codeNamesEtf[code];
        qDebug()<<"历史:"<<code<<symbol;
        // 以批量写入的方式来获取多年数据
        QString sql = "insert into etf_day_info (code,name,amount,chg,percent,volume,close,time_trade) values ";
        //qDebug()<<"sql 1:"<<sql;
        for(int i=0;i<cnt;++i){
            qint64 timestamp = jArr.at(i).toArray().at(0).toVariant().toLongLong();
//            double open = jArr.at(i).toArray().at(2).toVariant().toDouble();
//            double high = jArr.at(i).toArray().at(3).toVariant().toDouble();
//            double low = jArr.at(i).toArray().at(4).toVariant().toDouble();
            double close = jArr.at(i).toArray().at(5).toVariant().toDouble();
            double percent = jArr.at(i).toArray().at(7).toVariant().toDouble();
//            double turnoverrate = jArr.at(i).toArray().at(8).toVariant().toDouble();
            double amount = jArr.at(i).toArray().at(9).toVariant().toDouble();
//            double pe_ttm = jArr.at(i).toArray().at(16).toVariant().toDouble();
//            double market_capital = jArr.at(i).toArray().at(17).toVariant().toDouble();
            long long volume = jArr.at(i).toArray().at(1).toVariant().toLongLong()/100;
            double chg = jArr.at(i).toArray().at(6).toVariant().toDouble();
            //long long amount = jArr.at(i).toArray().at(9).toVariant().toLongLong()/100000000; // 亿
            QString curDateTime = QDateTime::fromMSecsSinceEpoch(timestamp).toString("yyyy-MM-dd");
//            qDebug()<<timestamp<<curDateTime<<close<<volume<<amount;
            // 处理数据保存到模型中
            QString vals = QString("('%1','%2',%3,%4,%5,%6,%7,'%8')").arg(code).arg(name).arg(QString::number(amount))
                    .arg(QString::number(chg)).arg(QString::number(percent)).arg(QString::number(volume)).arg(QString::number(close))
                    .arg(curDateTime);
            if(i != cnt - 1){
                vals.append(",");
            }
            sql.append(vals);
            //qDebug()<<"sql 3:"<<sql;
        }
        qDebug()<<"over:"<<sql.size();
//        qDebug()<<"sql 2:"<<sql; // 太大了 显示不出来
        QSqlQuery que(db);
        if(que.exec(sql)){
            qDebug()<<"insert ok";
        }else{
            qDebug()<<"insert fail"<<que.lastError().text();
        }
    }
}
void ETFStockInfo::showAplyData(QNetworkReply *reply)
{
    qDebug()<<"收到响应etf";
@@ -224,7 +310,7 @@
    }else if(reply->url().toString().indexOf("https://stock.xueqiu.com/v5/stock/chart/kline.json") != -1){
        qDebug()<<"查看个股情况:";
//        getStockOne(buffer);
        getStockOne(buffer);
    }else if(reply->url().toString().indexOf("https://stock.xueqiu.com/v5/stock/screener/quote/list.json?page=1&size=100&order=desc&order_by=percent&market=CN&ind_code") != -1){
        qDebug()<<"根据行业获取股票信息"<<reply->url();
@@ -290,3 +376,105 @@
    }
}
void ETFStockInfo::on_pushButton_search_date_clicked()
{
    // 按日期查询数据库,了解趋势
    QString cur_date = ui->dateTimeEdit->date().toString("yyyy-MM-dd");
    QString sql = QString("select *  from etf_day_info where time_trade = '%1' order by percent desc").arg(cur_date);
    QSqlQuery que(db);
    if(que.exec(sql)){
        qDebug()<<"select ok";
        m_model_market->setRowCount(0); // 重置模型行数
        int rows = 0;
        while (que.next()) {
            QString code = que.value(1).toString();
            QString name = que.value(2).toString();
            QString amount = QString::number(que.value(3).toDouble()/100000000);
            QString chg = QString::number(que.value(4).toDouble());
            QString percent = que.value(5).toString();
            QString volume = que.value(6).toString();
            QString close = que.value(7).toString();
            QString time_trade = que.value(8).toString();
//            QString turnover_rate = que.value(7).toString();
//            QString pe_ttm = que.value(8).toString();
//            QString amount_rank = que.value(9).toString();
//            m_modelDatas.append({name,code,market_capital,percent,close,amount,volume,turnover_rate,pe_ttm,amount_rank});
            QList<QStandardItem*> items;
            items.append(new QStandardItem(code));
            items.append(new QStandardItem(name));
            items.append(new QStandardItem(amount));
            items.append(new QStandardItem(chg));
            items.append(new QStandardItem("0"));
            items.append(new QStandardItem("0"));
            QStandardItem *percentItem =  new QStandardItem(percent);
            if(percent.toDouble() > 0){
                percentItem->setData(QColor("red"),Qt::DecorationRole); // 添加一个装饰的颜色为红色
                percentItem->setData(QColor("red"),Qt::TextColorRole);  // 将字体颜色设置为红色
                items.at(0)->setData(QColor("red"),Qt::TextColorRole);  // 将股票名字设置为红色
             }
            else if(percent.toDouble() < 0){
                percentItem->setData(QColor("green"),Qt::BackgroundColorRole);
                items.at(0)->setData(QColor("green"),Qt::TextColorRole);
            }
            items.append(percentItem);
            items.append(new QStandardItem(volume));
            items.append(new QStandardItem(close));
            items.append(new QStandardItem(time_trade));
//            items.append(new QStandardItem(pe_ttm));
//            items.append(new QStandardItem(amount_rank));
            m_model_market->appendRow(items);
            rows++;
        }
        qDebug()<<"查询到行数:"<<rows;
    }else{
        qDebug()<<"select fail"<<que.lastError().text();
    }
}
void ETFStockInfo::on_pushButton_update_clicked()
{
    // 更新到最新,默认全更
    // 也可以指定天数的数量来更新
    // 先保证获取到当前所有的etf基金的代码和名字,然后根据代码来发起更新请求
    m_days = ui->comboBox_days->currentText().toInt();
    if(m_days == 0) return;
    if(m_codeNamesEtf.size() > 0){
        qint64 cur_time = QDateTime::currentMSecsSinceEpoch();
        for(auto code:m_codeNamesEtf.keys()){
            QString url = QString("https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=%1&begin=%2&period=day&type=before&count=-%3&indicator=kline,pe,market_capital,ma")
                    .arg(code).arg(QString::number(cur_time)).arg(m_days);
            m_request.setUrl(QUrl(url));
            m_manager.get(m_request);
        }
        qDebug()<<"发起请求完成";
    }else{
        // 如果为空,则需要去刷新一下最新的情况,获取基金信息
        on_pushButton_market_clicked();
    }
}
void ETFStockInfo::on_checkBox_update_clicked()
{
    if(ui->checkBox_update->isChecked()){
        ui->pushButton_update->setEnabled(true);
    }else{
        ui->pushButton_update->setEnabled(false);
    }
}