From 69b17ff33713c33670dc9f5a6413ad654eac13c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=81=E9=91=AB=E5=93=B2?= <15872990+cin12501@user.noreply.gitee.com> Date: Sun, 27 Jul 2025 18:58:57 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E8=AE=A1=E6=97=B6=E6=A1=86=E7=9A=84?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/PomodoroWidget.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/PomodoroWidget.cpp b/src/PomodoroWidget.cpp index 21450df..b7810c4 100644 --- a/src/PomodoroWidget.cpp +++ b/src/PomodoroWidget.cpp @@ -243,13 +243,13 @@ void PomodoroWidget::paintEvent(QPaintEvent* event) } total_width += fm.horizontalAdvance(" : ") * 2; // 加上两个冒号 - // 从中心开始绘制 - int x_offset = center_x - total_width / 2; - int y_offset = center_y - fm.height() / 2; // 保持白色框在自然中心位置 + // 从中心开始绘制,向右偏移20像素 + int x_offset = center_x - total_width / 2 - 5; + int y_offset = center_y - fm.height() / 2+10; // 保持白色框在自然中心位置 for (int i = 0; i < 3; ++i) { int text_width = fm.horizontalAdvance(time_parts[i]); - QRect box_rect(x_offset - 12, y_offset - 12, text_width + 24, fm.height() + 24); + QRect box_rect(x_offset - 8, y_offset - 8, text_width + 16, fm.height() + 16); // 绘制阴影效果 painter.setPen(QPen(QColor(180, 180, 180), 1)); @@ -261,7 +261,7 @@ void PomodoroWidget::paintEvent(QPaintEvent* event) painter.setBrush(QBrush(QColor(255, 255, 255))); painter.drawRoundedRect(box_rect, 8, 8); - x_offset += text_width + fm.horizontalAdvance(" : "); + x_offset += text_width + fm.horizontalAdvance(" : ") + 5; // 增加5像素的额外间距 } } } else if (time_display_ && time_display_->isVisible()) { @@ -271,25 +271,25 @@ void PomodoroWidget::paintEvent(QPaintEvent* event) if (time_parts.size() == 3) { QFont font = time_display_->font(); QFontMetrics fm(font); - + // 计算时间显示区域的中心位置 int center_x = width() / 2; int center_y = height() / 2; - + // 计算总文本宽度 int total_width = 0; for (const QString& part : time_parts) { total_width += fm.horizontalAdvance(part); } total_width += fm.horizontalAdvance(" : ") * 2; // 加上两个冒号 - - // 从中心开始绘制 - int x_offset = center_x - total_width / 2; - int y_offset = center_y - fm.height() / 2; // 保持白色框在自然中心位置 + + // 从中心开始绘制,向右偏移20像素 + int x_offset = center_x - total_width / 2 -5; + int y_offset = center_y - fm.height() / 2+10; // 保持白色框在自然中心位置 for (int i = 0; i < 3; ++i) { int text_width = fm.horizontalAdvance(time_parts[i]); - QRect box_rect(x_offset - 12, y_offset - 12, text_width + 24, fm.height() + 24); + QRect box_rect(x_offset - 8, y_offset - 8, text_width + 16, fm.height() + 16); // 绘制阴影效果 painter.setPen(QPen(QColor(180, 180, 180), 1)); @@ -301,12 +301,13 @@ void PomodoroWidget::paintEvent(QPaintEvent* event) painter.setBrush(QColor(255, 255, 255)); painter.drawRoundedRect(box_rect, 8, 8); - x_offset += text_width + fm.horizontalAdvance(" : "); + x_offset += text_width + fm.horizontalAdvance(" : ") + 5; // 增加5像素的额外间距 } } } } + void PomodoroWidget::setupButtonStyles() { // 设置按钮悬停效果 From e4ba640b33dd9415f48958b7d039aebd6b92ddd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=81=E9=91=AB=E5=93=B2?= <15872990+cin12501@user.noreply.gitee.com> Date: Mon, 28 Jul 2025 23:33:32 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/DBLayer.cpp | 157 ++++++++++++++ src/DBLayer.h | 31 +++ src/PomodoroWidget.cpp | 42 ++-- src/ServiceLayer.cpp | 15 ++ src/ServiceLayer.h | 8 + src/ViewLayer.cpp | 454 ++++++++++++++++++++++++++++------------- src/ViewLayer.h | 25 +++ src/main/main.cpp | 2 +- 8 files changed, 577 insertions(+), 157 deletions(-) diff --git a/src/DBLayer.cpp b/src/DBLayer.cpp index 324e338..bca961b 100644 --- a/src/DBLayer.cpp +++ b/src/DBLayer.cpp @@ -115,6 +115,23 @@ DBLayer::DBLayer(std::string db_file_name) : db_file_name_(std::move(db_file_nam qDebug() << "UserSettingsTable 创建成功"; } + // 创建 PomodoroStateTable 用于存储番茄钟状态 + QString pomodoroStateSql = "CREATE TABLE IF NOT EXISTS PomodoroStateTable (" + "userId INTEGER PRIMARY KEY, " + "state INTEGER, " + "totalSeconds INTEGER, " + "remainingSeconds INTEGER, " + "remark TEXT, " + "startTime TEXT)"; + if (!query.exec(pomodoroStateSql)) + { + qDebug() << "PomodoroStateTable 创建失败:" << query.lastError().text(); + } + else + { + qDebug() << "PomodoroStateTable 创建成功"; + } + // 构造函数中初始化完后关闭数据库 closeDatabase(); } @@ -816,3 +833,143 @@ bool DBLayer::setActiveHabit(std::size_t habit_id) closeDatabase(); return true; } + +bool DBLayer::savePomodoroState(int state, int total_seconds, int remaining_seconds, const std::string& remark, const std::string& start_time) +{ + if (!openDatabase()) + { + qDebug() << "数据库打开失败,无法保存番茄钟状态"; + return false; + } + + std::size_t currentUserId = getCurrentUserID(); + if (currentUserId == 0) + { + // 如果没有登录用户,使用默认用户ID 1 + currentUserId = 1; + //qDebug() << "没有当前登录用户,使用默认用户ID:" << currentUserId; + } + + // 确保数据库连接仍然打开 + if (!db_.isOpen()) { + //qDebug() << "数据库连接已关闭,重新打开"; + if (!openDatabase()) { + //qDebug() << "重新打开数据库失败"; + return false; + } + } + + QSqlQuery query(db_); + query.prepare("INSERT OR REPLACE INTO PomodoroStateTable " + "(userId, state, totalSeconds, remainingSeconds, remark, startTime) " + "VALUES (:userId, :state, :totalSeconds, :remainingSeconds, :remark, :startTime)"); + + query.bindValue(":userId", static_cast(currentUserId)); + query.bindValue(":state", state); + query.bindValue(":totalSeconds", total_seconds); + query.bindValue(":remainingSeconds", remaining_seconds); + query.bindValue(":remark", QString::fromStdString(remark)); + query.bindValue(":startTime", QString::fromStdString(start_time)); + + if (!query.exec()) + { + qDebug() << "保存番茄钟状态失败:" << query.lastError().text(); + closeDatabase(); + return false; + } + + closeDatabase(); + return true; +} + +bool DBLayer::loadPomodoroState(int& state, int& total_seconds, int& remaining_seconds, std::string& remark, std::string& start_time) +{ + if (!openDatabase()) + { + qDebug() << "数据库打开失败,无法加载番茄钟状态"; + return false; + } + + std::size_t currentUserId = getCurrentUserID(); + if (currentUserId == 0) + { + // 如果没有登录用户,使用默认用户ID 1 + currentUserId = 1; + //qDebug() << "没有当前登录用户,使用默认用户ID:" << currentUserId; + } + + // 确保数据库连接仍然打开 + if (!db_.isOpen()) { + //qDebug() << "数据库连接已关闭,重新打开"; + if (!openDatabase()) { + //qDebug() << "重新打开数据库失败"; + return false; + } + } + + QSqlQuery query(db_); + query.prepare("SELECT state, totalSeconds, remainingSeconds, remark, startTime " + "FROM PomodoroStateTable WHERE userId = :userId"); + query.bindValue(":userId", static_cast(currentUserId)); + + if (!query.exec()) + { + qDebug() << "加载番茄钟状态失败:" << query.lastError().text(); + closeDatabase(); + return false; + } + + if (query.next()) + { + state = query.value("state").toInt(); + total_seconds = query.value("totalSeconds").toInt(); + remaining_seconds = query.value("remainingSeconds").toInt(); + remark = query.value("remark").toString().toStdString(); + start_time = query.value("startTime").toString().toStdString(); + closeDatabase(); + return true; + } + + closeDatabase(); + return false; // 没有找到状态记录 +} + +bool DBLayer::clearPomodoroState() +{ + if (!openDatabase()) + { + qDebug() << "数据库打开失败,无法清除番茄钟状态"; + return false; + } + + std::size_t currentUserId = getCurrentUserID(); + if (currentUserId == 0) + { + // 如果没有登录用户,使用默认用户ID 1 + currentUserId = 1; + //qDebug() << "没有当前登录用户,使用默认用户ID:" << currentUserId; + } + + // 确保数据库连接仍然打开 + if (!db_.isOpen()) { + //qDebug() << "数据库连接已关闭,重新打开"; + if (!openDatabase()) { + //qDebug() << "重新打开数据库失败"; + return false; + } + } + + QSqlQuery query(db_); + query.prepare("DELETE FROM PomodoroStateTable WHERE userId = :userId"); + query.bindValue(":userId", static_cast(currentUserId)); + + if (!query.exec()) + { + qDebug() << "清除番茄钟状态失败:" << query.lastError().text(); + closeDatabase(); + return false; + } + + closeDatabase(); + return true; +} diff --git a/src/DBLayer.h b/src/DBLayer.h index 8ef3906..83f6d9b 100644 --- a/src/DBLayer.h +++ b/src/DBLayer.h @@ -235,6 +235,37 @@ class DBLayer * @details 从数据库中启用指定ID的习惯 */ bool setActiveHabit(std::size_t habit_id); + + /** + * @brief 保存番茄钟状态到数据库 + * @author 遥远 + * @param state 番茄钟状态 (0=IDLE, 1=RUNNING, 2=PAUSED) + * @param total_seconds 总秒数 + * @param remaining_seconds 剩余秒数 + * @param remark 备注 + * @param start_time 开始时间戳 + * @return 保存是否成功 + */ + bool savePomodoroState(int state, int total_seconds, int remaining_seconds, const std::string& remark, const std::string& start_time); + + /** + * @brief 从数据库加载番茄钟状态 + * @author 遥远 + * @param state 输出:番茄钟状态 + * @param total_seconds 输出:总秒数 + * @param remaining_seconds 输出:剩余秒数 + * @param remark 输出:备注 + * @param start_time 输出:开始时间戳 + * @return 加载是否成功 + */ + bool loadPomodoroState(int& state, int& total_seconds, int& remaining_seconds, std::string& remark, std::string& start_time); + + /** + * @brief 清除番茄钟状态 + * @author 遥远 + * @return 清除是否成功 + */ + bool clearPomodoroState(); }; #endif // DBLAYER_H diff --git a/src/PomodoroWidget.cpp b/src/PomodoroWidget.cpp index 8e2050b..149e595 100644 --- a/src/PomodoroWidget.cpp +++ b/src/PomodoroWidget.cpp @@ -96,12 +96,12 @@ void PomodoroWidget::initCircularInterface() top_layout->setSpacing(50); image_button_ = new QPushButton("📷", top_container); - image_button_->setFixedSize(25, 25); - image_button_->setStyleSheet("QPushButton { border: none; background: transparent; font-size: 10px; }"); + image_button_->setFixedSize(35, 35); + image_button_->setStyleSheet("QPushButton { border: none; background: transparent; font-size: 30px; }"); music_button_ = new QPushButton("🎵", top_container); - music_button_->setFixedSize(25, 25); - music_button_->setStyleSheet("QPushButton { border: none; background: transparent; font-size: 10px; }"); + music_button_->setFixedSize(35, 35); + music_button_->setStyleSheet("QPushButton { border: none; background: transparent; font-size: 30px; }"); top_layout->addStretch(); top_layout->addWidget(image_button_); @@ -185,12 +185,12 @@ void PomodoroWidget::initCircularInterface() bottom_layout->setSpacing(50); control_button_ = new QPushButton("▶", bottom_container); - control_button_->setFixedSize(25, 25); - control_button_->setStyleSheet("QPushButton { border: none; background: transparent; font-size: 10px; }"); + control_button_->setFixedSize(35, 35); + control_button_->setStyleSheet("QPushButton { border: none; background: transparent; font-size: 30px; }"); reset_button_ = new QPushButton("🔄", bottom_container); - reset_button_->setFixedSize(25, 25); - reset_button_->setStyleSheet("QPushButton { border: none; background: transparent; font-size: 10px; }"); + reset_button_->setFixedSize(35, 35); + reset_button_->setStyleSheet("QPushButton { border: none; background: transparent; font-size: 30px; }"); bottom_layout->addStretch(); bottom_layout->addWidget(control_button_); @@ -500,27 +500,35 @@ QString PomodoroWidget::getTimeDisplayText() const return formatTime(remaining_seconds_); } -void PomodoroWidget::restoreState(int state, int total_seconds, int remaining_seconds, const QString& remark, const QString& /*start_time*/) +void PomodoroWidget::restoreState(int state, int total_seconds, int remaining_seconds, const QString& remark, const QString& start_time) { if (timer_) timer_->stop(); state_ = static_cast(state); total_seconds_ = total_seconds; - remaining_seconds_ = remaining_seconds; + remaining_seconds_ = remaining_seconds; // 这里已经是计算好的剩余时间 remark_ = remark; - start_time_ = QTime::currentTime(); // 仅用于兼容,不参与倒计时计算 - + if (state_ == IDLE) { control_button_->setText("▶"); time_edit_->setText("00 : 00 : 00"); time_edit_->show(); time_display_->hide(); } else { - control_button_->setText(state_ == RUNNING ? "⏸" : "▶"); - time_edit_->hide(); - time_display_->show(); - time_display_->setText(formatTime(remaining_seconds_)); - if (state_ == RUNNING) timer_->start(); + // 对于运行中或暂停的状态 + if (state_ == RUNNING) { + control_button_->setText("⏸"); + time_edit_->hide(); + time_display_->show(); + time_display_->setText(formatTime(remaining_seconds_)); + timer_->start(); + } else if (state_ == PAUSED) { + control_button_->setText("▶"); + time_edit_->hide(); + time_display_->show(); + time_display_->setText(formatTime(remaining_seconds_)); + } } + updateRemarkDisplay(); update(); emit stateChanged(); diff --git a/src/ServiceLayer.cpp b/src/ServiceLayer.cpp index 160e626..6bb377b 100644 --- a/src/ServiceLayer.cpp +++ b/src/ServiceLayer.cpp @@ -353,4 +353,19 @@ QJsonObject ServiceLayer::getThemeConfig(const QString &theme_name) const QJsonDocument doc = QJsonDocument::fromJson(data); return doc.object(); +} + +bool ServiceLayer::savePomodoroState(int state, int total_seconds, int remaining_seconds, const std::string& remark, const std::string& start_time) +{ + return db_layer.savePomodoroState(state, total_seconds, remaining_seconds, remark, start_time); +} + +bool ServiceLayer::loadPomodoroState(int& state, int& total_seconds, int& remaining_seconds, std::string& remark, std::string& start_time) +{ + return db_layer.loadPomodoroState(state, total_seconds, remaining_seconds, remark, start_time); +} + +bool ServiceLayer::clearPomodoroState() +{ + return db_layer.clearPomodoroState(); } \ No newline at end of file diff --git a/src/ServiceLayer.h b/src/ServiceLayer.h index 35582a2..f052a51 100644 --- a/src/ServiceLayer.h +++ b/src/ServiceLayer.h @@ -241,6 +241,14 @@ class ServiceLayer * @return 主题配置的JSON对象 */ static QJsonObject getThemeConfig(const QString &theme_name); + + bool savePomodoroState(int state, int total_seconds, int remaining_seconds, const std::string &remark, + const std::string &start_time); + + bool loadPomodoroState(int &state, int &total_seconds, int &remaining_seconds, std::string &remark, + std::string &start_time); + + bool clearPomodoroState(); }; inline const QString ServiceLayer::THEMES_PATH = "themes/themes.json"; // 主题列表配置文件路径 diff --git a/src/ViewLayer.cpp b/src/ViewLayer.cpp index ebfc75b..b6351af 100644 --- a/src/ViewLayer.cpp +++ b/src/ViewLayer.cpp @@ -206,14 +206,8 @@ void ViewLayer::initEventManageView() titleFont.setPointSize(18); titleFont.setBold(true); title->setFont(titleFont); - QPushButton *backButton = new QPushButton(); - backButton->setIcon(QIcon(":/assets/images/back.png")); - backButton->setIconSize(QSize(30, 30)); - backButton->setFixedSize(45, 45); - connect(backButton, &QPushButton::clicked, this, &ViewLayer::onBackToNavigation); topLayout->addWidget(title); topLayout->addStretch(); - topLayout->addWidget(backButton); layout->addLayout(topLayout, 0, 0, 1, 4); // 滚动区域和事项列表容器 @@ -549,11 +543,12 @@ void ViewLayer::initMainView() cardLayout->setAlignment(Qt::AlignVCenter); cardLayout->setSpacing(16); - // 编号框 - QLabel* indexLabel = new QLabel(QString::number(index + 1)); - indexLabel->setFixedSize(30, 50); - indexLabel->setAlignment(Qt::AlignCenter); - indexLabel->setStyleSheet("font-weight:bold;font-size:22px;border-radius:8px;background:#fff;border:1px solid #e0e0e0;"); + // 习惯名称框 + QLabel* nameLabel = new QLabel(QString::fromStdString(habit.name)); + nameLabel->setFixedSize(120, 50); + nameLabel->setAlignment(Qt::AlignCenter); + nameLabel->setStyleSheet("font-weight:bold;font-size:16px;border-radius:8px;background:#fff;border:1px solid #e0e0e0;"); + nameLabel->setWordWrap(true); // 日期 QLabel* dateLabel = new QLabel( @@ -563,26 +558,7 @@ void ViewLayer::initMainView() ); dateLabel->setStyleSheet("font-size:16px;"); - // 编辑按钮 - QPushButton* editBtn = new QPushButton(); - editBtn->setIcon(QIcon(":/assets/images/modify.png")); - editBtn->setToolTip("编辑"); - connect(editBtn, &QPushButton::clicked, [this, habit]() { habitUpdateView(habit); }); - - // 删除按钮 - QPushButton* delBtn = new QPushButton(); - delBtn->setIcon(QIcon(":/assets/images/delete.png")); - delBtn->setToolTip("删除"); - connect(delBtn, &QPushButton::clicked, [this, habit]() { - if (QMessageBox::question(this, "确认删除", "确定删除该习惯吗?") == QMessageBox::Yes) { - if (sv_Layer.deleteHabit(habit.habit_id)) { - QMessageBox::information(this, "提示", "删除成功"); - initMainView(); - } else { - QMessageBox::warning(this, "错误", "删除失败"); - } - } - }); + // 打卡次数 QLabel* checkinLabel = new QLabel( @@ -590,12 +566,69 @@ void ViewLayer::initMainView() ); checkinLabel->setStyleSheet("font-size:16px;"); + // 打卡按钮 + QPushButton* checkinBtn = new QPushButton("打卡"); + checkinBtn->setFixedSize(60, 30); + checkinBtn->setStyleSheet( + "QPushButton {" + " background-color: #52c41a;" + " color: white;" + " border: none;" + " border-radius: 6px;" + " font-size: 14px;" + " font-weight: bold;" + " padding: 2px;" + "}" + "QPushButton:hover {" + " background-color: #389e0d;" + "}" + "QPushButton:pressed {" + " background-color: #237804;" + "}" + ); + + // 连接打卡按钮信号 + connect(checkinBtn, &QPushButton::clicked, [this, habit, checkinLabel, todayCheckin]() mutable { + // 检查是否已达到目标次数 + if (todayCheckin >= habit.target_count) { + QMessageBox::information(this, "打卡完成", QString("习惯「%1」今日打卡已完成!(%2/%3)").arg(QString::fromStdString(habit.name)).arg(QString::number(todayCheckin)).arg(QString::number(habit.target_count))); + return; + } + + if (sv_Layer.checkinHabit(habit)) { + // 直接增加打卡次数 + todayCheckin++; + checkinLabel->setText(QString("打卡:%1 / %2 次").arg(QString::number(todayCheckin)).arg(QString::number(habit.target_count))); + + // 检查是否完成目标 + if (todayCheckin >= habit.target_count) { + QMessageBox::information(this, "打卡完成", QString("习惯「%1」今日打卡已完成!(%2/%3)").arg(QString::fromStdString(habit.name)).arg(QString::number(todayCheckin)).arg(QString::number(habit.target_count))); + // 可选:禁用打卡按钮 + // checkinBtn->setEnabled(false); + // checkinBtn->setStyleSheet( + // "QPushButton {" + // " background-color: #d9d9d9;" + // " color: #999;" + // " border: none;" + // " border-radius: 6px;" + // " font-size: 14px;" + // " font-weight: bold;" + // " padding: 2px;" + // "}" + // ); + } else { + QMessageBox::information(this, "打卡成功", QString("习惯「%1」打卡成功!(%2/%3)").arg(QString::fromStdString(habit.name)).arg(QString::number(todayCheckin)).arg(QString::number(habit.target_count))); + } + } else { + QMessageBox::warning(this, "打卡失败", QString("习惯「%1」打卡失败!").arg(QString::fromStdString(habit.name))); + } + }); + // 横向布局 - cardLayout->addWidget(indexLabel); + cardLayout->addWidget(nameLabel); cardLayout->addWidget(dateLabel); - cardLayout->addWidget(editBtn); - cardLayout->addWidget(delBtn); cardLayout->addWidget(checkinLabel); + cardLayout->addWidget(checkinBtn); cardLayout->addStretch(); habitCard->setLayout(cardLayout); @@ -622,38 +655,6 @@ void ViewLayer::initMainView() habitGroup->setLayout(groupLayout); gridLayout->addWidget(habitGroup, 0, 0, 2, 1); - // 刷新图片按钮 - QPushButton* refreshBtn = new QPushButton(main_widget); - refreshBtn->setIcon(QIcon(":/assets/images/update.png")); - refreshBtn->setIconSize(QSize(48, 48)); - refreshBtn->setFixedSize(60, 60); - refreshBtn->setStyleSheet(R"( - border: none; - background: transparent; - outline: none; - )"); - refreshBtn->setToolTip("刷新当前页面"); - - QLabel* refreshLabel = new QLabel("点我更新", main_widget); - refreshLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop); - refreshLabel->setStyleSheet("font-size:14px; color:#888;"); - - // 用QWidget包裹刷新按钮和文字 - QWidget* refreshWidget = new QWidget(main_widget); - QVBoxLayout* refreshLayout = new QVBoxLayout(refreshWidget); - refreshLayout->addWidget(refreshBtn, 0, Qt::AlignHCenter); - refreshLayout->addWidget(refreshLabel, 0, Qt::AlignHCenter); - refreshLayout->setContentsMargins(0, 0, 0, 0); - refreshWidget->setLayout(refreshLayout); - - // 插入到主布局 habit 区下方 - gridLayout->addWidget(refreshWidget, 2, 0, Qt::AlignLeft); - - // 点击刷新 - connect(refreshBtn, &QPushButton::clicked, [this]() { - initMainView(); // 直接重新初始化主视图 - }); - // 2. 右上:事项区 QGroupBox* eventGroup = new QGroupBox("活跃事项", main_widget); QWidget* eventListContainer = new QWidget(); @@ -674,24 +675,9 @@ void ViewLayer::initMainView() QLabel* nameLabel = new QLabel(QString::fromStdString(event.title)); QLabel* dateLabel = new QLabel(QString::fromStdString(toString(event.event_date))); QLabel* timeLabel = new QLabel(QString::fromStdString(toString(event.event_time))); - QPushButton* editBtn = new QPushButton("编辑"); - QPushButton* delBtn = new QPushButton("删除"); - connect(editBtn, &QPushButton::clicked, [this, event]() { EventUpdateView(event); }); - connect(delBtn, &QPushButton::clicked, [this, event]() { - if (QMessageBox::question(this, "确认删除", "确定删除该事项吗?") == QMessageBox::Yes) { - if (sv_Layer.deleteEvent(event.event_id)) { - QMessageBox::information(this, "提示", "删除成功"); - initMainView(); - } else { - QMessageBox::warning(this, "错误", "删除失败"); - } - } - }); cardLayout->addWidget(nameLabel); cardLayout->addWidget(dateLabel); cardLayout->addWidget(timeLabel); - cardLayout->addWidget(editBtn); - cardLayout->addWidget(delBtn); eventCard->setLayout(cardLayout); eventLayout->addWidget(eventCard); ++index; @@ -705,26 +691,27 @@ void ViewLayer::initMainView() // 3. 右下:番茄钟区 QGroupBox* pomoGroup = new QGroupBox("当前番茄钟", main_widget); - QHBoxLayout* pomoLayout = new QHBoxLayout(pomoGroup); - Date pomoToday = std::chrono::year_month_day(std::chrono::floor(std::chrono::system_clock::now())); - DateRecord pomoTodayRecord = sv_Layer.getAllRecordsByDate(pomoToday); - QLayoutItem* child; - while ((child = pomoLayout->takeAt(0)) != nullptr) { - delete child->widget(); - delete child; - } - if (!pomoTodayRecord.pomodoro_records.empty()) { - pomoLayout->addStretch(1); - for (const auto& pair : pomoTodayRecord.pomodoro_records) { - const Pomodoro& pomo = pair.second; - PomodoroWidget* pomoWidget = new PomodoroWidget(pomo, pomoGroup); - pomoLayout->addWidget(pomoWidget); - } - pomoLayout->addStretch(1); - } else { - QLabel* noPomo = new QLabel("暂无番茄钟"); - pomoLayout->addWidget(noPomo, 0, Qt::AlignCenter); - } + QVBoxLayout* pomoLayout = new QVBoxLayout(pomoGroup); + + // 创建番茄钟显示组件 + main_pomodoro_remark_label = new QLabel("", pomoGroup); + main_pomodoro_remark_label->setAlignment(Qt::AlignCenter); + main_pomodoro_remark_label->setStyleSheet("color:#333;font-size:30px;font-weight:bold;margin:5px 0;"); + main_pomodoro_remark_label->hide(); + + main_pomodoro_time_label = new QLabel("00 : 00 : 00", pomoGroup); + main_pomodoro_time_label->setAlignment(Qt::AlignCenter); + main_pomodoro_time_label->setStyleSheet("color:#1890ff;font-size:20px;font-weight:bold;margin:5px 0;"); + main_pomodoro_time_label->hide(); + + main_pomodoro_no_pomodoro_label = new QLabel("暂无番茄钟", pomoGroup); + main_pomodoro_no_pomodoro_label->setAlignment(Qt::AlignCenter); + main_pomodoro_no_pomodoro_label->setStyleSheet("color:#888;font-size:16px;margin:20px 0;"); + + pomoLayout->addWidget(main_pomodoro_remark_label); + pomoLayout->addWidget(main_pomodoro_time_label); + pomoLayout->addWidget(main_pomodoro_no_pomodoro_label); + pomoGroup->setLayout(pomoLayout); gridLayout->addWidget(pomoGroup, 1, 1); @@ -776,12 +763,27 @@ void ViewLayer::initMainView() gridLayout->setRowStretch(0, 2); gridLayout->setRowStretch(1, 2); gridLayout->setRowStretch(2, 1); - gridLayout->setColumnStretch(0, 2); - gridLayout->setColumnStretch(1, 3); + gridLayout->setColumnStretch(0, 5); // 习惯框占5份 + gridLayout->setColumnStretch(1, 2); // 右侧区域占2份 // 把内容区加到主垂直布局 mainVLayout->addLayout(gridLayout, 10); mainVLayout->addWidget(navigation_widget, 1); + + + main_widget->setLayout(mainVLayout); + dialogLabel->installEventFilter(this); + main_widget->setStyleSheet("background: #F5F6FA;"); + + // 初始化主界面番茄钟定时器 + if (!main_pomodoro_timer) { + main_pomodoro_timer = new QTimer(this); + main_pomodoro_timer->setInterval(1000); // 每秒更新 + connect(main_pomodoro_timer, &QTimer::timeout, this, &ViewLayer::updateMainPomodoroDisplay); + } + + // 检查并恢复番茄钟状态(延迟执行,确保番茄钟组件已创建) + QTimer::singleShot(200, this, &ViewLayer::checkAndRestorePomodoroState); } void ViewLayer::initTimelineView() @@ -795,18 +797,15 @@ void ViewLayer::initTimelineView() QVBoxLayout *layout = new QVBoxLayout(timeline_widget); - // 顶部标题 + 返回按钮 + // 顶部标题 QHBoxLayout *topLayout = new QHBoxLayout(); QLabel *title = new QLabel("时间线", timeline_widget); QFont titleFont; titleFont.setPointSize(18); titleFont.setBold(true); title->setFont(titleFont); - QPushButton *backButton = createButton(":/assets/images/back.png", "返回", 45, 45); - connect(backButton, &QPushButton::clicked, this, &ViewLayer::onBackToNavigation); topLayout->addWidget(title); topLayout->addStretch(); - topLayout->addWidget(backButton); layout->addLayout(topLayout); // 日期选择栏 @@ -848,6 +847,8 @@ void ViewLayer::initTimelineView() connect(dateEdit, &QDateEdit::dateChanged, this, &ViewLayer::refreshTimeline); refreshTimeline(); // 初次加载 + + } QPushButton* ViewLayer::createButton(const QString& iconPath, const QString& tooltip, int width, int height) @@ -887,7 +888,7 @@ void ViewLayer::refreshTimeline() // 向服务层请求当天记录 DateRecord raw_record = sv_Layer.getAllRecordsByDate(date); - std::vector events = sv_Layer.getEventsByDate(date); + std::vector events = sv_Layer.getEventsByDate(Utility::chronoToQDateTime(date, Time{}).date()); // 定义用于排序合并的向量(按 Time 升序) using TimelineItem = std::tuple; // time, type, content @@ -947,22 +948,74 @@ void ViewLayer::initPomodoroView() titleFont.setPointSize(18); titleFont.setBold(true); title->setFont(titleFont); - QPushButton *backButton = new QPushButton(); - backButton->setIcon(QIcon(":/assets/images/back.png")); - backButton->setIconSize(QSize(30, 30)); - backButton->setFixedSize(45, 45); - connect(backButton, &QPushButton::clicked, this, &ViewLayer::onBackToNavigation); topLayout->addWidget(title); topLayout->addStretch(); - topLayout->addWidget(backButton); layout->addLayout(topLayout); - // 主体容器内容 + // 主体容器内容 - 圆形钟居中显示 + QWidget* center_container = new QWidget(pomodoro_widget); + QVBoxLayout* center_layout = new QVBoxLayout(center_container); + center_layout->setContentsMargins(0, 0, 0, 0); + if (!pomodoro_widget_component) { pomodoro_widget_component = new PomodoroWidget(pomodoro_widget); + + // 连接番茄钟信号到主界面更新 + connect(pomodoro_widget_component, &PomodoroWidget::stateChanged, this, &ViewLayer::updateMainPomodoroDisplay); + connect(pomodoro_widget_component, &PomodoroWidget::timerUpdated, this, &ViewLayer::updateMainPomodoroDisplay); + + // 连接状态改变信号到保存状态 + connect(pomodoro_widget_component, &PomodoroWidget::stateChanged, this, [this]() { + if (pomodoro_widget_component) { + qDebug() << "番茄钟状态改变,当前状态:" << pomodoro_widget_component->getState(); + + // 如果是IDLE状态,清除数据库中的状态 + if (pomodoro_widget_component->getState() == PomodoroWidget::IDLE) { + qDebug() << "清除番茄钟状态"; + sv_Layer.clearPomodoroState(); + } else { + // 保存番茄钟状态到数据库 + qDebug() << "保存番茄钟状态到数据库"; + bool success = sv_Layer.savePomodoroState( + static_cast(pomodoro_widget_component->getState()), + pomodoro_widget_component->getTotalSeconds(), + pomodoro_widget_component->getRemainingSeconds(), + pomodoro_widget_component->getRemark().toStdString(), + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss").toStdString() + ); + qDebug() << "保存番茄钟状态结果:" << (success ? "成功" : "失败"); + } + } + }); + + // 连接定时器更新信号到保存状态(每秒保存一次) + connect(pomodoro_widget_component, &PomodoroWidget::timerUpdated, this, [this]() { + if (pomodoro_widget_component && pomodoro_widget_component->getState() == PomodoroWidget::RUNNING) { + // 每秒保存运行中的番茄钟状态 + bool success = sv_Layer.savePomodoroState( + static_cast(pomodoro_widget_component->getState()), + pomodoro_widget_component->getTotalSeconds(), + pomodoro_widget_component->getRemainingSeconds(), + pomodoro_widget_component->getRemark().toStdString(), + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss").toStdString() + ); + if (!success) { + qDebug() << "定时器更新时保存番茄钟状态失败"; + } + } + }); } - layout->addWidget(pomodoro_widget_component); + + // 添加弹性空间使圆形钟居中 + center_layout->addStretch(); + center_layout->addWidget(pomodoro_widget_component, 0, Qt::AlignCenter); + center_layout->addStretch(); + + layout->addWidget(center_container); + + // 番茄钟组件创建完成后,立即检查并恢复状态 + QTimer::singleShot(100, this, &ViewLayer::checkAndRestorePomodoroState); } void ViewLayer::initSettingsView() @@ -976,22 +1029,18 @@ void ViewLayer::initSettingsView() auto *layout = new QVBoxLayout(settings_widget); - // 顶部:标题 + 返回按钮 + // 顶部:标题 QHBoxLayout *topLayout = new QHBoxLayout(); QLabel *title = new QLabel("个人设置", settings_widget); QFont titleFont; titleFont.setPointSize(18); titleFont.setBold(true); title->setFont(titleFont); - QPushButton *backButton = new QPushButton(); - backButton->setIcon(QIcon(":/assets/images/back.png")); - backButton->setIconSize(QSize(30, 30)); - backButton->setFixedSize(45, 45); - connect(backButton, &QPushButton::clicked, this, &ViewLayer::onBackToNavigation); topLayout->addWidget(title); topLayout->addStretch(); - topLayout->addWidget(backButton); layout->addLayout(topLayout); + + } void ViewLayer::initCalendarView() @@ -1008,18 +1057,12 @@ void ViewLayer::initCalendarView() layout = new QVBoxLayout(calendar_widget); } - // 标题和返回按钮 + // 标题 auto top_layout = new QHBoxLayout(); auto title = new QLabel("日历", calendar_widget); title->setFont(QFont("Arial", 18, QFont::Bold)); - auto backButton = new QPushButton(); - backButton->setIcon(QIcon(":/assets/images/back.png")); - backButton->setIconSize(QSize(30, 30)); - backButton->setFixedSize(45, 45); - connect(backButton, &QPushButton::clicked, this, &ViewLayer::onBackToNavigation); top_layout->addWidget(title); top_layout->addStretch(); - top_layout->addWidget(backButton); layout->addLayout(top_layout); // 创建 CalendarView 并传入 ServiceLayer @@ -1029,6 +1072,7 @@ void ViewLayer::initCalendarView() }); layout->addWidget(calendar_view); + calendar_widget->setLayout(layout); } @@ -1188,21 +1232,15 @@ void ViewLayer::initHabitManageView() habit_manage_widget->setLayout(gridLayout); } - // 顶部标题 + 返回按钮 + // 顶部标题 QHBoxLayout *topLayout = new QHBoxLayout(); QLabel *title = new QLabel("习惯管理", habit_manage_widget); QFont titleFont; titleFont.setPointSize(18); titleFont.setBold(true); title->setFont(titleFont); - QPushButton *backButton = new QPushButton(); - backButton->setIcon(QIcon(":/assets/images/back.png")); - backButton->setIconSize(QSize(30, 30)); - backButton->setFixedSize(45, 45); - connect(backButton, &QPushButton::clicked, this, &ViewLayer::onBackToNavigation); topLayout->addWidget(title); topLayout->addStretch(); - topLayout->addWidget(backButton); gridLayout->addLayout(topLayout, 0, 0, 1, 4); // 占据第0行,4列 // 活跃习惯展示区(滚动区域) @@ -1463,7 +1501,7 @@ void ViewLayer::initNavigationView() { } }); - timer->start(5000); + timer->start(5000); } @@ -1544,7 +1582,7 @@ void ViewLayer::setCurrentView(ViewType view) { if (cur_view_type == view) return; - + initMainView(); this->resetCurrentView(view); } @@ -1567,3 +1605,141 @@ bool ViewLayer::eventFilter(QObject* watched, QEvent* event) } return QWidget::eventFilter(watched, event); } + +void ViewLayer::updateMainPomodoroDisplay() +{ + qDebug() << "=== 更新主界面番茄钟显示 ==="; + qDebug() << "番茄钟组件是否存在:" << (pomodoro_widget_component ? "是" : "否"); + + if (!pomodoro_widget_component) { + qDebug() << "番茄钟组件不存在,显示无番茄钟"; + showNoPomodoro(); + return; + } + + // 检查番茄钟状态 + int state = pomodoro_widget_component->getState(); + qDebug() << "当前番茄钟状态:" << state; + + if (state == PomodoroWidget::IDLE) { + qDebug() << "番茄钟状态为IDLE,显示无番茄钟"; + showNoPomodoro(); + return; + } + + // 获取番茄钟信息 + QString remark = pomodoro_widget_component->getRemark(); + QString timeText = pomodoro_widget_component->getTimeDisplayText(); + int remainingSeconds = pomodoro_widget_component->getRemainingSeconds(); + + qDebug() << "番茄钟信息:"; + qDebug() << " 备注:" << remark; + qDebug() << " 时间文本:" << timeText; + qDebug() << " 剩余秒数:" << remainingSeconds; + + // 更新显示 + if (main_pomodoro_remark_label && main_pomodoro_time_label && main_pomodoro_no_pomodoro_label) { + main_pomodoro_remark_label->setText(remark); + main_pomodoro_time_label->setText(timeText); + + main_pomodoro_remark_label->show(); + main_pomodoro_time_label->show(); + main_pomodoro_no_pomodoro_label->hide(); + + qDebug() << "主界面番茄钟显示已更新"; + } else { + qDebug() << "错误:主界面番茄钟标签不存在"; + } + + qDebug() << "=== 主界面番茄钟显示更新完成 ==="; +} + +void ViewLayer::startMainPomodoroTimer() +{ + if (main_pomodoro_timer) { + main_pomodoro_timer->start(); + } +} + +void ViewLayer::stopMainPomodoroTimer() +{ + if (main_pomodoro_timer) { + main_pomodoro_timer->stop(); + } +} + +void ViewLayer::checkAndRestorePomodoroState() +{ + qDebug() << "=== 开始检查并恢复番茄钟状态 ==="; + qDebug() << "番茄钟组件是否存在:" << (pomodoro_widget_component ? "是" : "否"); + + // 检查番茄钟组件是否存在 + if (!pomodoro_widget_component) { + qDebug() << "错误:番茄钟组件不存在,无法恢复状态"; + return; + } + + // 检查是否有正在运行的番茄钟 + if (pomodoro_widget_component->getState() != PomodoroWidget::IDLE) { + qDebug() << "发现正在运行的番茄钟,状态:" << pomodoro_widget_component->getState(); + qDebug() << "启动主界面定时器"; + startMainPomodoroTimer(); + updateMainPomodoroDisplay(); + return; + } + + // 尝试从数据库恢复番茄钟状态 + int state, total_seconds, remaining_seconds; + std::string remark, start_time; + + qDebug() << "尝试从数据库加载番茄钟状态..."; + if (sv_Layer.loadPomodoroState(state, total_seconds, remaining_seconds, remark, start_time)) { + qDebug() << "成功加载番茄钟状态:"; + qDebug() << " 状态:" << state; + qDebug() << " 总时长:" << total_seconds; + qDebug() << " 剩余时长:" << remaining_seconds; + qDebug() << " 备注:" << QString::fromStdString(remark); + qDebug() << " 开始时间:" << QString::fromStdString(start_time); + + // 如果有保存的状态,恢复番茄钟 + if (state != 0) { // 0 = IDLE + qDebug() << "开始恢复番茄钟状态..."; + pomodoro_widget_component->restoreState(state, total_seconds, remaining_seconds, + QString::fromStdString(remark), + QString::fromStdString(start_time)); + + qDebug() << "恢复后的状态:" << pomodoro_widget_component->getState(); + qDebug() << "恢复后的剩余时间:" << pomodoro_widget_component->getRemainingSeconds(); + + // 检查恢复后的状态 + if (pomodoro_widget_component->getState() != PomodoroWidget::IDLE) { + qDebug() << "番茄钟状态恢复成功,启动定时器"; + startMainPomodoroTimer(); + updateMainPomodoroDisplay(); + } else { + // 如果恢复后状态变为IDLE(时间已用完),清除数据库状态 + qDebug() << "番茄钟时间已用完,清除数据库状态"; + sv_Layer.clearPomodoroState(); + showNoPomodoro(); + } + } else { + qDebug() << "状态为IDLE,显示无番茄钟"; + showNoPomodoro(); + } + } else { + qDebug() << "没有找到保存的番茄钟状态,显示无番茄钟"; + showNoPomodoro(); + } + + qDebug() << "=== 番茄钟状态检查完成 ==="; +} + +void ViewLayer::showNoPomodoro() +{ + if (main_pomodoro_remark_label && main_pomodoro_time_label && main_pomodoro_no_pomodoro_label) { + main_pomodoro_remark_label->hide(); + main_pomodoro_time_label->hide(); + main_pomodoro_no_pomodoro_label->show(); + } + stopMainPomodoroTimer(); +} diff --git a/src/ViewLayer.h b/src/ViewLayer.h index 66d60e9..8f61b52 100644 --- a/src/ViewLayer.h +++ b/src/ViewLayer.h @@ -12,6 +12,10 @@ #include #include #include +#include +#include +#include +#include #include "CalendarDialog.h" #include "Times.h" @@ -77,6 +81,21 @@ class ViewLayer final : public QWidget bool eventFilter(QObject *watched, QEvent *event) override; + // 更新主界面番茄钟显示(主界面右下角) + void updateMainPomodoroDisplay(); + + // 启动主界面番茄钟定时器 + void startMainPomodoroTimer(); + + // 停止主界面番茄钟定时器 + void stopMainPomodoroTimer(); + + // 检查并恢复番茄钟状态(从数据库恢复) + void checkAndRestorePomodoroState(); + + // 显示“无番茄钟”状态 + void showNoPomodoro(); + signals: /** * @brief 习惯添加信号 @@ -166,6 +185,12 @@ private slots: // 当前对话框的 QLabel 指针 QLabel* dialogLabel = nullptr; + // 主界面番茄钟显示相关 + QLabel* main_pomodoro_remark_label = nullptr; // 显示番茄钟备注 + QLabel* main_pomodoro_time_label = nullptr; // 显示番茄钟剩余时间 + QLabel* main_pomodoro_no_pomodoro_label = nullptr; // 显示“暂无番茄钟”提示 + QTimer* main_pomodoro_timer = nullptr; // 主界面番茄钟定时器,用于定时刷新显示 + // ================= 各视图初始化 ================= /** * @brief 初始化导航视图 diff --git a/src/main/main.cpp b/src/main/main.cpp index 1d78ed2..0955b0a 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -9,7 +9,7 @@ int testHabbitModule(int argc, char* argv[], const ViewLayer::ViewType type) QApplication app(argc, argv); ViewLayer view; - view.setFixedSize(1000, 800); + view.setFixedSize(1100, 800); view.setWindowTitle("Habbit 效率管理软件"); view.setCurrentView(type); view.show(); From e329c7faffd36d43585c3cad49319993472b3944 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=81=E9=91=AB=E5=93=B2?= <15872990+cin12501@user.noreply.gitee.com> Date: Mon, 28 Jul 2025 23:37:33 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Habbit1 | 1 + 1 file changed, 1 insertion(+) create mode 160000 Habbit1 diff --git a/Habbit1 b/Habbit1 new file mode 160000 index 0000000..f605a8c --- /dev/null +++ b/Habbit1 @@ -0,0 +1 @@ +Subproject commit f605a8c944ca265c3e98e1e92d71d6f2d21acc9b From d0588e879df90be0d346f57228125ca089aea66e Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Tue, 29 Jul 2025 00:27:59 +0800 Subject: [PATCH 4/5] fix: Fix missing function --- src/ViewLayer.cpp | 260 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 260 insertions(+) diff --git a/src/ViewLayer.cpp b/src/ViewLayer.cpp index bff1802..457bd7a 100644 --- a/src/ViewLayer.cpp +++ b/src/ViewLayer.cpp @@ -713,6 +713,266 @@ void ViewLayer::initMainView() QTimer::singleShot(200, this, &ViewLayer::checkAndRestorePomodoroState); } +void ViewLayer::refreshMainView() +{ + if (!main_content_grid_layout) return; + + // 清空 main_content_grid_layout + QLayoutItem* item; + while ((item = main_content_grid_layout->takeAt(0)) != nullptr) { + if (item->widget()) { + item->widget()->deleteLater(); + } + delete item; + } + + // ========= 左侧:待打卡习惯 ========= + QGroupBox* habitGroup = new QGroupBox("待打卡习惯", main_widget); + QScrollArea* habitScroll = new QScrollArea(habitGroup); + habitScroll->setWidgetResizable(true); + habitScroll->setFixedHeight(500); + habitScroll->setStyleSheet(R"( + QScrollBar:horizontal { + height: 8px; background: #f0f0f0; margin: 0px 20px 0 20px; border-radius: 4px; + } + QScrollBar::handle:horizontal { + background: #bfbfbf; min-width: 24px; border-radius: 4px; + } + QScrollBar:vertical { + width: 8px; background: #f0f0f0; margin: 20px 0 20px 0; border-radius: 4px; + } + QScrollBar::handle:vertical { + background: #bfbfbf; min-height: 24px; border-radius: 4px; + } + QScrollBar::add-line, QScrollBar::sub-line { + background: none; border: none; + })"); + + QWidget* habitListContainer = new QWidget(); + QVBoxLayout* habitLayout = new QVBoxLayout(habitListContainer); + + Date today = std::chrono::year_month_day(std::chrono::floor(std::chrono::system_clock::now())); + DateRecord todayRecord = sv_Layer.getAllRecordsByDate(today); + std::vector habits = sv_Layer.getActiveHabits(); + + if (habits.empty()) { + QLabel* noHabit = new QLabel("暂无习惯"); + noHabit->setAlignment(Qt::AlignCenter); + noHabit->setStyleSheet("color:#888;font-size:18px;margin:20px 0;"); + habitLayout->addWidget(noHabit); + } else { + int index = 0; + for (const auto& habit : habits) { + if (index >= 5) break; + int todayCheckin = std::count_if( + todayRecord.habit_records.begin(), todayRecord.habit_records.end(), + [&habit](const auto& rec) { return rec.second.habit_id == habit.habit_id; }); + + QWidget* habitCard = new QWidget(); + habitCard->setFixedHeight(80); + habitCard->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + habitCard->setStyleSheet(R"( + background:#fff; + border:1px solid #e0e0e0; + border-radius:12px; + padding:8px; + margin-bottom:12px;)"); + + QHBoxLayout* cardLayout = new QHBoxLayout(habitCard); + cardLayout->setAlignment(Qt::AlignVCenter); + cardLayout->setSpacing(16); + + QLabel* nameLabel = new QLabel(QString::fromStdString(habit.name)); + nameLabel->setFixedHeight(50); + nameLabel->setAlignment(Qt::AlignCenter); + nameLabel->setStyleSheet("font-weight:bold;font-size:22px;border-radius:8px;background:#fff;border:1px solid #e0e0e0;"); + + QLabel* dateLabel = new QLabel( + QString("%1 ~ %2") + .arg(QString::fromStdString(toString(habit.start_date))) + .arg(QString::fromStdString(toString(habit.end_date))) + ); + dateLabel->setStyleSheet("font-size:16px;"); + + QPushButton* editBtn = new QPushButton(); + editBtn->setIcon(QIcon(":/assets/images/modify.png")); + editBtn->setToolTip("编辑"); + connect(editBtn, &QPushButton::clicked, [this, habit]() { + habitUpdateView(habit); + refreshMainView(); + }); + + QPushButton* delBtn = new QPushButton(); + delBtn->setIcon(QIcon(":/assets/images/delete.png")); + delBtn->setToolTip("删除"); + connect(delBtn, &QPushButton::clicked, [this, habit]() { + if (QMessageBox::question(this, "确认删除", "确定删除该习惯吗?") == QMessageBox::Yes) { + if (sv_Layer.deleteHabit(habit.habit_id)) { + QMessageBox::information(this, "提示", "删除成功"); + refreshMainView(); // 刷新 + } else { + QMessageBox::warning(this, "错误", "删除失败"); + } + } + }); + + QLabel* checkinLabel = new QLabel( + QString("打卡:%1 / %2 次").arg(QString::number(todayCheckin)).arg(QString::number(habit.target_count))); + checkinLabel->setStyleSheet("font-size:16px;"); + + cardLayout->addWidget(nameLabel); + cardLayout->addWidget(dateLabel); + cardLayout->addWidget(editBtn); + cardLayout->addWidget(delBtn); + cardLayout->addWidget(checkinLabel); + cardLayout->addStretch(); + + habitCard->setLayout(cardLayout); + habitLayout->addWidget(habitCard); + ++index; + } + } + + habitListContainer->setLayout(habitLayout); + habitScroll->setWidget(habitListContainer); + QVBoxLayout* groupLayout = new QVBoxLayout(habitGroup); + groupLayout->addWidget(habitScroll); + habitGroup->setLayout(groupLayout); + main_content_grid_layout->addWidget(habitGroup, 0, 0, 2, 1); + + // ========= 右上:事项 ========= + QGroupBox* eventGroup = new QGroupBox("活跃事项", main_widget); + QWidget* eventListContainer = new QWidget(); + QVBoxLayout* eventLayout = new QVBoxLayout(eventListContainer); + std::vector events = sv_Layer.getActiveEvents(); + + if (events.empty()) { + QLabel* noEvent = new QLabel("暂无事项"); + noEvent->setAlignment(Qt::AlignCenter); + noEvent->setStyleSheet("color:#888;font-size:18px;margin:20px 0;"); + eventLayout->addWidget(noEvent); + } else { + int index = 0; + for (const auto& event : events) { + if (index >= 4) break; + QWidget* eventCard = new QWidget(); + QHBoxLayout* cardLayout = new QHBoxLayout(eventCard); + QLabel* nameLabel = new QLabel(QString::fromStdString(event.title)); + QLabel* dateLabel = new QLabel(QString::fromStdString(toString(event.event_date))); + QLabel* timeLabel = new QLabel(QString::fromStdString(toString(event.event_time))); + QPushButton* editBtn = new QPushButton("编辑"); + QPushButton* delBtn = new QPushButton("删除"); + connect(editBtn, &QPushButton::clicked, [this, event]() { + EventUpdateView(event); + refreshMainView(); + }); + connect(delBtn, &QPushButton::clicked, [this, event]() { + if (QMessageBox::question(this, "确认删除", "确定删除该事项吗?") == QMessageBox::Yes) { + if (sv_Layer.deleteEvent(event.event_id)) { + QMessageBox::information(this, "提示", "删除成功"); + refreshMainView(); // 刷新 + } else { + QMessageBox::warning(this, "错误", "删除失败"); + } + } + }); + cardLayout->addWidget(nameLabel); + cardLayout->addWidget(dateLabel); + cardLayout->addWidget(timeLabel); + cardLayout->addWidget(editBtn); + cardLayout->addWidget(delBtn); + eventCard->setLayout(cardLayout); + eventLayout->addWidget(eventCard); + ++index; + } + } + + eventListContainer->setLayout(eventLayout); + QVBoxLayout* eventGroupLayout = new QVBoxLayout(eventGroup); + eventGroupLayout->addWidget(eventListContainer); + eventGroup->setLayout(eventGroupLayout); + main_content_grid_layout->addWidget(eventGroup, 0, 1); + + // ========= 右下:番茄钟 ========= + QGroupBox* pomoGroup = new QGroupBox("当前番茄钟", main_widget); + QVBoxLayout* pomoLayout = new QVBoxLayout(pomoGroup); + pomoLayout->setAlignment(Qt::AlignCenter); + + if (pomodoro_widget_component && pomodoro_widget_component->getState() == PomodoroWidget::RUNNING) { + QLabel* timeLabel = new QLabel(pomodoro_widget_component->getTimeDisplayText()); + timeLabel->setStyleSheet("font-size: 24px; font-weight: bold;"); + timeLabel->setAlignment(Qt::AlignCenter); + + QLabel* remarkLabel = new QLabel(pomodoro_widget_component->getRemark()); + remarkLabel->setStyleSheet("font-size: 18px; color: #555;"); + remarkLabel->setWordWrap(true); + remarkLabel->setAlignment(Qt::AlignCenter); + + pomoLayout->addWidget(timeLabel); + pomoLayout->addWidget(remarkLabel); + } else { + QLabel* noPomo = new QLabel("暂无活跃番茄钟"); + noPomo->setStyleSheet("font-size: 20px; color: #999;"); + noPomo->setAlignment(Qt::AlignCenter); + pomoLayout->addWidget(noPomo); + } + + main_content_grid_layout->addWidget(pomoGroup, 1, 1); + + pomoGroup->setLayout(pomoLayout); + main_content_grid_layout->addWidget(pomoGroup, 1, 1); + + // ========= 右下角:吉祥物+对话框 ========= + QWidget* dialogMascotWidget = new QWidget(main_widget); + QHBoxLayout* dialogMascotLayout = new QHBoxLayout(dialogMascotWidget); + QGroupBox* dialogGroup = new QGroupBox(dialogMascotWidget); + QVBoxLayout* dialogLayout = new QVBoxLayout(dialogGroup); + + if (!dialogLabel) dialogLabel = new QLabel(dialogGroup); + dialogLabel->setText(dialogTexts[0]); + dialogLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); + dialogLabel->setWordWrap(true); + + dialogGroup->setStyleSheet(R"( + QGroupBox { + background: #fffbe6; + border: 2px solid #ffd666; + border-radius: 16px; + margin-top: 8px; + margin-bottom: 8px; + padding: 16px; + min-width: 220px; + max-width: 320px; + })"); + dialogLabel->setStyleSheet(R"( + QLabel { + color: #ad6800; + font-size: 18px; + font-weight: bold; + padding: 4px 8px; + background: transparent; + })"); + + dialogLayout->addWidget(dialogLabel); + dialogGroup->setLayout(dialogLayout); + dialogMascotLayout->addWidget(dialogGroup, 2); + + QLabel* mascotLabel = new QLabel(dialogMascotWidget); + QPixmap mascotPixmap(":/assets/images/logo.png"); + mascotLabel->setPixmap(mascotPixmap.scaled(120, 120, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + dialogMascotLayout->addWidget(mascotLabel, 1, Qt::AlignRight | Qt::AlignBottom); + dialogMascotWidget->setLayout(dialogMascotLayout); + + main_content_grid_layout->addWidget(dialogMascotWidget, 2, 1); + + // ========= 拉伸策略 ========= + main_content_grid_layout->setRowStretch(0, 2); + main_content_grid_layout->setRowStretch(1, 2); + main_content_grid_layout->setRowStretch(2, 1); + main_content_grid_layout->setColumnStretch(0, 2); + main_content_grid_layout->setColumnStretch(1, 3); +} + void ViewLayer::initTimelineView() { auto* layout = new QVBoxLayout(timeline_widget); From 9f970398b6e927072d06e314dc13d1b60226b37c Mon Sep 17 00:00:00 2001 From: FrozenLemonTee <1115306170@qq.com> Date: Tue, 29 Jul 2025 00:28:42 +0800 Subject: [PATCH 5/5] fix: Fix missing function --- src/SimpleAuthSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SimpleAuthSystem.cpp b/src/SimpleAuthSystem.cpp index f2c98e7..c05e3a3 100644 --- a/src/SimpleAuthSystem.cpp +++ b/src/SimpleAuthSystem.cpp @@ -84,7 +84,7 @@ void SimpleAuthSystem::sendHttpRequest(const QString &endpoint, const QString &d statusLabel->setText("正在发送请求..."); - connect(process, &QProcess::finished, this, [=](int exitCode, QProcess::ExitStatus exitStatus) + connect(process, &QProcess::finished, this, [=, this](int exitCode, QProcess::ExitStatus exitStatus) { QString response = QString::fromUtf8(process->readAllStandardOutput()); QString error = QString::fromUtf8(process->readAllStandardError());