wumu
2025-10-30 5f8a4c8d12855caa8d06cfcc5caa5a0601563710
251030
1个文件已添加
3个文件已修改
386 ■■■■■ 已修改文件
positionmanagement.cpp 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
positionmanagement.h 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
positionmanagement.ui 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
stock_plan_251030_position_pool_add.sql 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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,"卖出失败","无持仓,不能卖出");
    }
}
positionmanagement.h
@@ -3,6 +3,15 @@
#include <QMainWindow>
#include <QStandardItemModel>
#include <QDialog>
#include <QLineEdit>
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QMenu>
#include <QAction>
#include <QTableView>
namespace Ui {
class PositionManagement;
@@ -16,12 +25,34 @@
    explicit PositionManagement(QWidget *parent = 0);
    ~PositionManagement();
    void initMySQL();
private slots:
    void on_pushButton_add_clicked();
    void on_pushButton_refresh_clicked();
    void showMenu(QPoint p);
    void searchPriceAction(); // 查询价格的动作槽
    void buyStockAction(); // 买入股票的动作槽--只买当前选中的这支
    void saleStockAction(); // 卖出当前选中的这支股票槽
private:
    Ui::PositionManagement *ui;
    QStandardItemModel *m_modelAll;
    QStandardItemModel *m_modelShort;
    QStandardItemModel *m_modelMid;
    QStandardItemModel *m_modelLong;
    QDialog *m_addDlg; // 添加股票的对话框
    QVector<QLineEdit*> m_lineEdits;
    QSqlDatabase db;
    QMenu *m_menu; // 右击菜单
    QPoint m_curPoint; // 当前坐标
    QTableView * m_curView; // 当前视图
};
#endif // POSITIONMANAGEMENT_H
positionmanagement.ui
@@ -6,8 +6,8 @@
   <rect>
    <x>0</x>
    <y>0</y>
    <width>840</width>
    <height>625</height>
    <width>754</width>
    <height>494</height>
   </rect>
  </property>
  <property name="windowTitle">
@@ -63,12 +63,30 @@
      </layout>
     </widget>
    </item>
    <item row="2" column="0">
     <widget class="QPushButton" name="pushButton_add">
      <property name="text">
       <string>添加股票</string>
      </property>
     </widget>
    <item row="2" column="0" colspan="2">
     <layout class="QHBoxLayout" name="horizontalLayout_5">
      <item>
       <widget class="QPushButton" name="pushButton_add">
        <property name="text">
         <string>添加股票</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QPushButton" name="pushButton_refresh">
        <property name="text">
         <string>刷新股票</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QLabel" name="label">
        <property name="text">
         <string>短线: 0%  中线: 0%  长线: 0%</string>
        </property>
       </widget>
      </item>
     </layout>
    </item>
   </layout>
  </widget>
@@ -77,7 +95,7 @@
    <rect>
     <x>0</x>
     <y>0</y>
     <width>840</width>
     <width>754</width>
     <height>26</height>
    </rect>
   </property>
stock_plan_251030_position_pool_add.sql
New file
@@ -0,0 +1,52 @@
-- --------------------------------------------------------
-- 主机:                           127.0.0.1
-- 服务器版本:                        5.6.35-log - MySQL Community Server (GPL)
-- 服务器操作系统:                      Win64
-- HeidiSQL 版本:                  9.5.0.5196
-- --------------------------------------------------------
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!50503 SET NAMES utf8mb4 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-- 导出 stock_plan 的数据库结构
CREATE DATABASE IF NOT EXISTS `stock_plan` /*!40100 DEFAULT CHARACTER SET utf8 */;
USE `stock_plan`;
-- 导出  表 stock_plan.position_pool 结构
CREATE TABLE IF NOT EXISTS `position_pool` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) DEFAULT NULL COMMENT '股票名字',
  `code` varchar(50) DEFAULT NULL COMMENT '股票代号',
  `time_in` varchar(50) DEFAULT NULL COMMENT '入池时间',
  `price_in` double DEFAULT NULL COMMENT '入池价格',
  `time_buy` varchar(50) DEFAULT '0' COMMENT '购买时间',
  `price_buy` double DEFAULT '0' COMMENT '购买价格',
  `time_sale` varchar(50) DEFAULT '0' COMMENT '卖出时间',
  `price_sale` double DEFAULT '0' COMMENT '卖出价格',
  `rate_in` double DEFAULT '0' COMMENT '入池收益',
  `rate_buy` double DEFAULT '0' COMMENT '买入收益',
  `rate_sale` double DEFAULT '0' COMMENT '卖出收益',
  `type` varchar(50) DEFAULT NULL COMMENT '1=短线,2=中线,3=长线',
  `state` int(11) DEFAULT '1' COMMENT '1=观察,2=持有,3=卖出',
  `cur_price` double DEFAULT '0' COMMENT '当前价格',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8 COMMENT='股票持仓池';
-- 正在导出表  stock_plan.position_pool 的数据:~0 rows (大约)
/*!40000 ALTER TABLE `position_pool` DISABLE KEYS */;
INSERT INTO `position_pool` (`id`, `name`, `code`, `time_in`, `price_in`, `time_buy`, `price_buy`, `time_sale`, `price_sale`, `rate_in`, `rate_buy`, `rate_sale`, `type`, `state`, `cur_price`) VALUES
    (1, '宁德时代', 'SZ300750', '2025-10-29 21:22:49', 400, '2025-10-29 23:39:32', 400, '0', 0, 0, 0, 0, '中线', 1, 500),
    (2, '阳光电源', 'SZ300274', '2025-10-29 21:25:30', 191.49, '0', 0, '0', 0, 0, 0, 0, '长线', 1, 191.49),
    (3, '先导智能', 'SZ300450', '2025-10-29 21:26:58', 62.75, '0', 0, '0', 0, 0, 0, 0, '短线', 1, 162.75),
    (4, '胜宏科技', 'SZ300476', '2025-10-29 23:43:40', 339, '0', 0, '0', 0, 0, 0, 0, '短线', 1, 339),
    (5, '立讯精密', 'SZ002475', '2025-10-29 23:46:50', 67.28, '2025-10-29 23:50:44', 67.28, '2025-10-30 00:08:37', 167.28, 0, 0, 148.633, '中线', 3, 167.28),
    (6, '特变电工', 'SH600089', '2025-10-29 23:47:14', 20.9, '2025-10-29 23:48:41', 20.9, '2025-10-30 00:07:53', 120.9, 0, 0, 478.469, '长线', 3, 120.9);
/*!40000 ALTER TABLE `position_pool` ENABLE KEYS */;
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;