wumu
2025-10-30 5f8a4c8d12855caa8d06cfcc5caa5a0601563710
positionmanagement.cpp
@@ -1,5 +1,13 @@
#include "positionmanagement.h"
#include "ui_positionmanagement.h"
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QComboBox>
#include <QDebug>
#include <QMessageBox>
#include <QDateTime>
#include <QMessageBox>
PositionManagement::PositionManagement(QWidget *parent):
    QMainWindow(parent),
@@ -12,8 +20,9 @@
    m_modelMid = new QStandardItemModel(this);
    m_modelLong = new QStandardItemModel(this);
    QStringList labels;
    labels<<"id"<<"股票"<<"code"<<"入池时间"<<"入池价格"<<"购买时间"<<"购买价格"<<"入池收益"<<"购买收益"<<"类型";
    QStringList labels; // 14列
    labels<<"id"<<"股票"<<"code"<<"入池时间"<<"入池价格"<<"购买时间"<<"购买价格"
         <<"卖出时间"<<"卖出价格"<<"入池收益"<<"买入收益"<<"卖出收益"<<"类型"<<"状态"<<"当前价格";
    m_modelAll->setHorizontalHeaderLabels(labels);
    m_modelShort->setHorizontalHeaderLabels(labels);
@@ -24,9 +33,263 @@
    ui->tableView_short->setModel(m_modelShort);
    ui->tableView_mid->setModel(m_modelMid);
    ui->tableView_long->setModel(m_modelLong);
    // 初始化数据库
    initMySQL();
    // 添加股票信息相关
    m_addDlg = new QDialog(this);
    m_addDlg->setWindowTitle("添加股票到仓位池");
    QVBoxLayout *vb = new QVBoxLayout(m_addDlg);
    QStringList placetext;
    placetext<<"输入股票名字"<<"输入股票代号"<<"输入价格";
    for(int i=0;i<3;++i){
        QLineEdit *lt = new QLineEdit(this);
        lt->setPlaceholderText(placetext.at(i));
        vb->addWidget(lt);
        m_lineEdits.append(lt);
    }
    QComboBox *comBox = new QComboBox(this);
    comBox->addItem("短线");
    comBox->addItem("中线");
    comBox->addItem("长线");
    vb->addWidget(comBox);
    QPushButton *addBtn = new QPushButton("添加",this);
    vb->addWidget(addBtn);
    // 使用匿名函数来实现槽
    connect(addBtn,&QPushButton::clicked,this,[=]{
        QString name = m_lineEdits.at(0)->text();
        QString code = m_lineEdits.at(1)->text();
        QString price = m_lineEdits.at(2)->text();
        QString type = comBox->currentText();
        qDebug()<<name<<code<<price<<type;
        QString cur_time = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
        QString sql = QString("insert into position_pool (name,code,time_in,price_in,type,cur_price) values ('%1','%2','%3',%4,'%5',%6)")
                .arg(name).arg(code).arg(cur_time).arg(price).arg(type).arg(price);
        qDebug()<<"添加股票的sql:"<<sql;
        QSqlQuery que(db);
        if(que.exec(sql)){
            qDebug()<<"insert ok";
            QMessageBox::information(m_addDlg,"添加成功",name+" "+price);
        }else{
            qDebug()<<"insert fail"<<que.lastError().text();
            QMessageBox::information(m_addDlg,"添加失败",name+" "+que.lastError().text());
        }
    });
    // 右击菜单: 准备好菜单--给目标对象设置菜单策略为自定义上下文菜单--连接信号槽
    m_menu = new QMenu(this);
    m_menu->addAction("查询最新价格");
    m_menu->addAction("买入当前股票");
    m_menu->addAction("卖出当前股票");
    // 连接菜单动作和槽
    connect(m_menu->actions().at(0),SIGNAL(triggered(bool)),this,SLOT(searchPriceAction()));
    connect(m_menu->actions().at(1),SIGNAL(triggered(bool)),this,SLOT(buyStockAction()));
    connect(m_menu->actions().at(2),SIGNAL(triggered(bool)),this,SLOT(saleStockAction()));
    this->setContextMenuPolicy(Qt::CustomContextMenu); // 设定菜单策略
    ui->tableView_all->setContextMenuPolicy(Qt::CustomContextMenu);
    ui->tableView_short->setContextMenuPolicy(Qt::CustomContextMenu);
    ui->tableView_mid->setContextMenuPolicy(Qt::CustomContextMenu);
    ui->tableView_long->setContextMenuPolicy(Qt::CustomContextMenu);
    // 和窗口连接,在整个窗口中都可以右击显示菜单
//    connect(this,&PositionManagement::customContextMenuRequested,this,[=](QPoint p){
//        //m_menu->exec(QCursor::pos()); // 方式1
//        //m_menu->exec(this->mapToGlobal(p)); // 方式2,如果是子部件,容易坐标偏移
//        m_menu->popup(QCursor::pos()); // 换一个方式3 也可以
//    });
    // 和每个视图连接,只在视图中显示菜单
    connect(ui->tableView_all,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(showMenu(QPoint)));
    connect(ui->tableView_short,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(showMenu(QPoint)));
    connect(ui->tableView_mid,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(showMenu(QPoint)));
    connect(ui->tableView_long,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(showMenu(QPoint)));
}
PositionManagement::~PositionManagement()
{
    delete ui;
}
void PositionManagement::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 PositionManagement::on_pushButton_add_clicked()
{
    m_addDlg->show();
}
void PositionManagement::on_pushButton_refresh_clicked()
{
    m_modelAll->setRowCount(0);
    m_modelShort->setRowCount(0);
    m_modelMid->setRowCount(0);
    m_modelLong->setRowCount(0);
    QString sql = "select * from position_pool";
    QSqlQuery que(db);
    if(que.exec(sql)){
        qDebug()<<"查询成功";
        qDebug()<<"size:"<<que.size();
        while (que.next()) {
            QList<QStandardItem*> items;
            QList<QStandardItem*> items_short;
            QList<QStandardItem*> items_mid;
            QList<QStandardItem*> items_long;
            for(int i=0;i<15;++i){
                qDebug()<<i<<que.value(i).toString();
                items.append(new QStandardItem(que.value(i).toString()));
                items_short.append(new QStandardItem(que.value(i).toString()));
                items_mid.append(new QStandardItem(que.value(i).toString()));
                items_long.append(new QStandardItem(que.value(i).toString()));
            }
            m_modelAll->appendRow(items);
            if(items.at(12)->text() == "短线"){
                m_modelShort->appendRow(items_short);
            }else if(items.at(12)->text() == "中线"){
                m_modelMid->appendRow(items_mid);
            }else{
                m_modelLong->appendRow(items_long);
            }
        }
    }else{
        qDebug()<<"查询失败";
    }
}
void PositionManagement::showMenu(QPoint p)
{
    m_curPoint = p;  // 记录当前坐标--子部件内的坐标,刚好可用,不用再转换了
    m_curView = (QTableView*)sender(); // 记录被点击的视图,用来取索引--模型--数据
//    qDebug()<<sender()<<p;
//    qDebug()<<"显示右击菜单";
//    m_menu->exec(this->mapFromGlobal(p)); // 方式1,容易坐标跑偏,特别是子部件显示菜单时
    m_menu->exec(QCursor::pos());
}
void PositionManagement::searchPriceAction()
{
    qDebug()<<"查询最新价格"<<sender();
}
void PositionManagement::buyStockAction()
{
    qDebug()<<"买入当前股票";
    // 判断当前位置是否为选中的有效内容行,然后按当前价格买入即可,应该拿到最新价买卖
    // 一定要先判断状态是否为观察:观察的话--当前行买入,修改记录即可;如果是已经买入或卖出的状态,再添加一条新的买入记录
    QModelIndex index = m_curView->indexAt(m_curPoint);
    if(index.row() == -1) return; // 防止异常
    QStandardItemModel * curModel = (QStandardItemModel*)index.model();
    int row = index.row();
    QString id = curModel->item(row,0)->text();
    QString name = curModel->item(row,1)->text();
    QString code = curModel->item(row,2)->text();
    QString price = curModel->item(row,14)->text();
    QString state = curModel->item(row,13)->text();
    qDebug()<<id<<name<<code<<price<<"state:"<<state;
    if(state.toInt() == 1){
        // 更新当前即可,通过id来对比处理即可更新
        QString buy_time = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
        QString sql = QString("update position_pool set time_buy='%1',price_buy=%2,state=%4 where id=%3")
                .arg(buy_time).arg(price).arg(id).arg("2");
        qDebug()<<"buy sql:"<<sql;
        QSqlQuery que(db);
        if(que.exec(sql)){
            qDebug()<<"buy 成功:"<<name<<price;
            on_pushButton_refresh_clicked(); // 刷新股票池
        }else{
            qDebug()<<"buy 失败:"<<name<<price;
        }
    }else{
        // 创建新的记录,把当前价格和时间设置为入池、买入相应的价格和时间
    }
}
void PositionManagement::saleStockAction()
{
    qDebug()<<"卖出当前股票";
    // 判断当前位置是否为选中的有效内容行,然后按当前价格卖出即可,应该拿到最新价买卖
    // 一定要先判断出目前是买入持仓的状态,否则卖出失败
    QModelIndex index = m_curView->indexAt(m_curPoint);
    if(index.row() == -1) return; // 防止异常
    QStandardItemModel * curModel = (QStandardItemModel*)index.model();
    int row = index.row();
    QString id = curModel->item(row,0)->text();
    QString name = curModel->item(row,1)->text();
    QString code = curModel->item(row,2)->text();
    QString price = curModel->item(row,14)->text();
    QString state = curModel->item(row,13)->text();
    QString buy_price = curModel->item(row,6)->text();
    qDebug()<<id<<name<<code<<price<<"state:"<<state;
    if(state.toInt() == 2){
        // 更新当前即可,通过id来对比处理即可更新
        QString sell_time = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
        double rate = (price.toDouble() / buy_price.toDouble() - 1.0)*100; // 计算卖出盈利比
        QString sql = QString("update position_pool set time_sale='%1',price_sale=%2,state=%4,rate_sale=%7 where id=%3")
                .arg(sell_time).arg(price).arg(id).arg("3").arg(QString::number(rate));
        qDebug()<<"sell sql:"<<sql;
        QSqlQuery que(db);
        if(que.exec(sql)){
            qDebug()<<"sell 成功:"<<name<<price;
            on_pushButton_refresh_clicked(); // 刷新股票池
            QMessageBox::information(this,"卖出成功",name+" 盈利百分比:"+QString::number(rate));
        }else{
            qDebug()<<"sell 失败:"<<name<<price;
        }
    }else{
        qDebug()<<"不适合卖出,没有持仓";
        QMessageBox::information(this,"卖出失败","无持仓,不能卖出");
    }
}