zhuizhu 7 ヶ月 前
コミット
ed92aee0c2

+ 8 - 38
MainPanel.cpp

@@ -127,11 +127,10 @@ QIcon createChatIcon()
 } // namespace IconUtils
 
 MainPanel::MainPanel(QWidget *parent)
-    : QWidget(parent)
+    : TWidget(parent)
     , chatView(nullptr)
 {
     setAttribute(Qt::WA_StyledBackground, true);
-    setStyleSheet("background: #f7f7f7;");
 
     m_debounceTimer = new QTimer(this);
     m_debounceTimer->setInterval(500);
@@ -172,11 +171,9 @@ MainPanel::MainPanel(QWidget *parent)
     splitter->addWidget(m_rightWidget);
     splitter->setStretchFactor(0, 60);
     splitter->setStretchFactor(1, 30);
-    QVBoxLayout *mainLayout = new QVBoxLayout(this);
-    mainLayout->addWidget(splitter, 1);
-    mainLayout->setContentsMargins(0, 0, 0, 0);
-    mainLayout->setSpacing(0);
-    setLayout(mainLayout);
+    this->mainLayout()->addWidget(splitter, 1);
+    this->mainLayout()->setContentsMargins(0, 0, 0, 0);
+    this->mainLayout()->setSpacing(0);
 
     // 为playerContainer设置初始布局
     QVBoxLayout *playerLayout = new QVBoxLayout(playerContainer);
@@ -185,10 +182,10 @@ MainPanel::MainPanel(QWidget *parent)
     buttonGroup = new PopoverButtonGroup(Qt::Horizontal, playerContainer);
 
     // 添加功能按钮
-    FunctionButton *settingsBtn = new FunctionButton(IconUtils::createSettingsIcon(), "设置", this);
-    // 移除 Popover 箭头,改为直接打开设置窗口
-    buttonGroup->addButton(settingsBtn, nullptr);
-    connect(settingsBtn, &QPushButton::clicked, this, &MainPanel::onSettingsButtonClicked);
+    // FunctionButton *settingsBtn = new FunctionButton(IconUtils::createSettingsIcon(), "设置", this);
+    // // 移除 Popover 箭头,改为直接打开设置窗口
+    // buttonGroup->addButton(settingsBtn, nullptr);
+    // connect(settingsBtn, &QPushButton::clicked, this, &MainPanel::onSettingsButtonClicked);
 
     // 移除:搜索按钮(暂不使用)
     // FunctionButton *searchBtn = new FunctionButton(IconUtils::createSearchIcon(), "搜索", this);
@@ -678,33 +675,6 @@ void MainPanel::onStreamButtonClicked()
     }
 }
 
-void MainPanel::onSettingsButtonClicked()
-{
-    // 使用 TMainWindow 包裹设置页面,保持无边框一致风格
-    if (m_settingsFrame) {
-        if (m_settingsFrame->isVisible()) {
-            m_settingsFrame->raise();
-            m_settingsFrame->activateWindow();
-        } else {
-            m_settingsFrame->show();
-            m_settingsFrame->raise();
-            m_settingsFrame->activateWindow();
-        }
-        return;
-    }
-
-    m_settingsFrame = new TMainWindow();
-    m_settingsFrame->setAttribute(Qt::WA_DeleteOnClose);
-    m_settingsFrame->setWindowTitle(tr("设置"));
-    // 当设置窗口关闭时,清空指针
-    connect(m_settingsFrame, &QObject::destroyed, this, [this]() { m_settingsFrame = nullptr; });
-
-    auto *settingsWidget = new ThemeSettingsWidget(m_settingsFrame);
-    m_settingsFrame->setCentralWidget(settingsWidget);
-    m_settingsFrame->resize(560, 460);
-    m_settingsFrame->show();
-}
-
 void MainPanel::onChatWindowCloseRequested()
 {
     // 如果处在推流状态,认为是“隐藏聊天”而不是关闭程序

+ 2 - 2
MainPanel.h

@@ -11,6 +11,7 @@
 #include <QPushButton>
 #include <QCheckBox>
 #include "libs/Recorder/export.h"
+#include "widgets/framelessbase.h"  // Use TWidget as base
 
 class QSplitter;
 
@@ -34,7 +35,7 @@ namespace ADS {
     class DockWidget;
 }
 
-class MainPanel : public QWidget
+class MainPanel : public TWidget
 {
     Q_OBJECT
 public:
@@ -141,7 +142,6 @@ private slots:
     // 新增:录制控制按钮的槽函数
     void onRecordButtonClicked();
     void onStreamButtonClicked();
-    void onSettingsButtonClicked();
     void onChatButtonClicked();                 // 聊天弹出/嵌入/显示/隐藏按钮槽
     
     // 聊天窗口关闭处理

+ 2 - 2
mainwindow.cpp

@@ -248,7 +248,7 @@ void MainWindow::onJoinMeetingRequested()
             }
             
             // 显示对话框
-            if (joinDialog->exec() == QDialog::Accepted) {
+            if (joinDialog->exec() == JoinMeetingDialog::Accepted) {
                 QString meetingId = joinDialog->getSelectedMeetingId();
                 
                 // 独立窗口加入会议(观看者模式)
@@ -273,7 +273,7 @@ void MainWindow::onJoinMeetingRequested()
                                BubbleTip::Type::Error);
             
             // 即使获取失败也显示对话框,允许手动输入
-            if (joinDialog->exec() == QDialog::Accepted) {
+            if (joinDialog->exec() == JoinMeetingDialog::Accepted) {
                 QString meetingId = joinDialog->getSelectedMeetingId();
                 
                 // 独立窗口加入会议(观看者模式)

+ 216 - 210
widgets/createmeetingdialog.cpp

@@ -1,4 +1,6 @@
 #include "createmeetingdialog.h"
+#include <QCloseEvent>
+#include <QEventLoop>
 #include <QMessageBox>
 #include <QRandomGenerator>
 #include <QRegularExpression>
@@ -6,7 +8,7 @@
 #include <QScrollArea>
 
 CreateMeetingDialog::CreateMeetingDialog(QWidget *parent)
-    : QDialog(parent)
+    : TDialog(parent)
     , m_mainLayout(nullptr)
     , m_formLayout(nullptr)
     , m_basicGroup(nullptr)
@@ -32,303 +34,306 @@ CreateMeetingDialog::CreateMeetingDialog(QWidget *parent)
     , m_cancelButton(nullptr)
 {
     setWindowTitle("创建会议");
-    setModal(true);
     resize(500, 600);
-    
+
     setupUI();
     applyStyles();
     setDefaultValues();
-    
+
     // 初始状态下禁用创建按钮
     m_createButton->setEnabled(false);
 }
 
-CreateMeetingDialog::~CreateMeetingDialog()
-{
-}
+CreateMeetingDialog::~CreateMeetingDialog() {}
 
 void CreateMeetingDialog::setupUI()
 {
     // 创建滚动区域
-    QScrollArea *scrollArea = new QScrollArea(this);
+    QScrollArea *scrollArea = new QScrollArea();
     scrollArea->setWidgetResizable(true);
     scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-    
+
     QWidget *scrollWidget = new QWidget();
     scrollArea->setWidget(scrollWidget);
-    
+
     m_mainLayout = new QVBoxLayout(scrollWidget);
     m_mainLayout->setContentsMargins(20, 20, 20, 20);
     m_mainLayout->setSpacing(20);
-    
+
     // 基本信息组
     m_basicGroup = new QGroupBox("基本信息", scrollWidget);
     m_basicLayout = new QFormLayout(m_basicGroup);
     m_basicLayout->setContentsMargins(15, 15, 15, 15);
     m_basicLayout->setSpacing(10);
-    
+
     // 会议名称
     m_meetingNameEdit = new QLineEdit();
     m_meetingNameEdit->setPlaceholderText("请输入会议名称");
-    connect(m_meetingNameEdit, &QLineEdit::textChanged, this, &CreateMeetingDialog::onMeetingNameChanged);
+    connect(m_meetingNameEdit,
+            &QLineEdit::textChanged,
+            this,
+            &CreateMeetingDialog::onMeetingNameChanged);
     m_basicLayout->addRow("会议名称 *:", m_meetingNameEdit);
-    
+
     // 会议描述
     m_descriptionEdit = new QTextEdit();
     m_descriptionEdit->setPlaceholderText("请输入会议描述(可选)");
     m_descriptionEdit->setMaximumHeight(80);
     m_basicLayout->addRow("会议描述:", m_descriptionEdit);
-    
+
     // 开始时间
     m_startTimeEdit = new QDateTimeEdit();
     m_startTimeEdit->setCalendarPopup(true);
     m_startTimeEdit->setDisplayFormat("yyyy-MM-dd hh:mm");
     m_basicLayout->addRow("开始时间 *:", m_startTimeEdit);
-    
+
     // 会议时长
     m_durationSpinBox = new QSpinBox();
     m_durationSpinBox->setRange(15, 480); // 15分钟到8小时
     m_durationSpinBox->setSuffix(" 分钟");
     m_durationSpinBox->setSingleStep(15);
     m_basicLayout->addRow("会议时长 *:", m_durationSpinBox);
-    
+
     // 最大参与人数
     m_maxParticipantsSpinBox = new QSpinBox();
     m_maxParticipantsSpinBox->setRange(2, 100);
     m_maxParticipantsSpinBox->setSuffix(" 人");
     m_basicLayout->addRow("最大参与人数:", m_maxParticipantsSpinBox);
-    
+
     // 会议类型
     m_meetingTypeCombo = new QComboBox();
     m_meetingTypeCombo->addItems({"视频会议", "音频会议", "屏幕共享", "网络研讨会"});
     m_basicLayout->addRow("会议类型:", m_meetingTypeCombo);
-    
+
     m_mainLayout->addWidget(m_basicGroup);
-    
+
     // 安全设置组
     m_securityGroup = new QGroupBox("安全设置", scrollWidget);
     m_securityLayout = new QVBoxLayout(m_securityGroup);
     m_securityLayout->setContentsMargins(15, 15, 15, 15);
     m_securityLayout->setSpacing(10);
-    
+
     // 密码设置
     m_passwordCheckBox = new QCheckBox("启用会议密码");
-    connect(m_passwordCheckBox, &QCheckBox::toggled, this, &CreateMeetingDialog::onPasswordCheckChanged);
+    connect(m_passwordCheckBox,
+            &QCheckBox::toggled,
+            this,
+            &CreateMeetingDialog::onPasswordCheckChanged);
     m_securityLayout->addWidget(m_passwordCheckBox);
-    
+
     m_passwordLayout = new QHBoxLayout();
     m_passwordEdit = new QLineEdit();
     m_passwordEdit->setPlaceholderText("请输入6-12位密码");
     m_passwordEdit->setMaxLength(12);
     m_passwordEdit->setEnabled(false);
-    
+
     // 设置密码验证器
     QRegularExpression passwordRegex("[A-Za-z0-9]{6,12}");
-    QRegularExpressionValidator *passwordValidator = new QRegularExpressionValidator(passwordRegex, this);
+    QRegularExpressionValidator *passwordValidator = new QRegularExpressionValidator(passwordRegex,
+                                                                                     this);
     m_passwordEdit->setValidator(passwordValidator);
-    
+
     m_generatePasswordButton = new QPushButton("生成密码");
     m_generatePasswordButton->setEnabled(false);
-    connect(m_generatePasswordButton, &QPushButton::clicked, this, &CreateMeetingDialog::generateRandomPassword);
-    
+    connect(m_generatePasswordButton,
+            &QPushButton::clicked,
+            this,
+            &CreateMeetingDialog::generateRandomPassword);
+
     m_passwordLayout->addWidget(m_passwordEdit);
     m_passwordLayout->addWidget(m_generatePasswordButton);
     m_securityLayout->addLayout(m_passwordLayout);
-    
+
     // 录制设置
     m_recordCheckBox = new QCheckBox("自动录制会议");
     m_securityLayout->addWidget(m_recordCheckBox);
-    
+
     m_mainLayout->addWidget(m_securityGroup);
-    
+
     // 角色选择组
     m_roleGroup = new QGroupBox("加入方式", scrollWidget);
     m_roleLayout = new QVBoxLayout(m_roleGroup);
     m_roleLayout->setContentsMargins(15, 15, 15, 15);
     m_roleLayout->setSpacing(10);
-    
+
     m_joinAsAdminCheckBox = new QCheckBox("以管理员身份加入会议(可以录制和管理)");
     m_joinAsAdminCheckBox->setChecked(true); // 默认选中管理员模式
     m_roleLayout->addWidget(m_joinAsAdminCheckBox);
-    
+
     QLabel *roleHint = new QLabel("提示:取消勾选将以观看者身份加入会议");
     roleHint->setStyleSheet("color: #666; font-size: 12px;");
     m_roleLayout->addWidget(roleHint);
-    
+
     m_mainLayout->addWidget(m_roleGroup);
-    
+
     // 按钮布局
     m_buttonLayout = new QHBoxLayout();
     m_buttonLayout->addStretch();
-    
+
     m_cancelButton = new QPushButton("取消");
     m_createButton = new QPushButton("创建会议");
-    
+
     connect(m_cancelButton, &QPushButton::clicked, this, &CreateMeetingDialog::reject);
     connect(m_createButton, &QPushButton::clicked, this, &CreateMeetingDialog::accept);
-    
+
     m_buttonLayout->addWidget(m_cancelButton);
     m_buttonLayout->addWidget(m_createButton);
-    
+
     m_mainLayout->addLayout(m_buttonLayout);
-    
-    // 设置主布局
-    QVBoxLayout *dialogLayout = new QVBoxLayout(this);
-    dialogLayout->setContentsMargins(0, 0, 0, 0);
-    dialogLayout->addWidget(scrollArea);
+
+    // 设置主布局 - 使用TWidget的mainLayout()
+    mainLayout()->addWidget(scrollArea);
 }
 
 void CreateMeetingDialog::applyStyles()
 {
-    setStyleSheet(
-        "CreateMeetingDialog {"
-        "    background-color: #f8f9fa;"
-        "}"
-        
-        "QScrollArea {"
-        "    border: none;"
-        "    background-color: #f8f9fa;"
-        "}"
-        
-        "QGroupBox {"
-        "    font-size: 14px;"
-        "    font-weight: bold;"
-        "    color: #495057;"
-        "    border: 2px solid #e9ecef;"
-        "    border-radius: 8px;"
-        "    margin-top: 10px;"
-        "    background-color: white;"
-        "}"
-        
-        "QGroupBox::title {"
-        "    subcontrol-origin: margin;"
-        "    left: 10px;"
-        "    padding: 0 8px 0 8px;"
-        "    background-color: white;"
-        "}"
-        
-        "QLabel {"
-        "    font-size: 13px;"
-        "    color: #495057;"
-        "    font-weight: 500;"
-        "}"
-        
-        "QLineEdit {"
-        "    border: 2px solid #e9ecef;"
-        "    border-radius: 6px;"
-        "    padding: 8px 12px;"
-        "    font-size: 13px;"
-        "    background-color: white;"
-        "}"
-        
-        "QLineEdit:focus {"
-        "    border-color: #007bff;"
-        "    outline: none;"
-        "}"
-        
-        "QLineEdit:disabled {"
-        "    background-color: #f8f9fa;"
-        "    color: #6c757d;"
-        "}"
-        
-        "QTextEdit {"
-        "    border: 2px solid #e9ecef;"
-        "    border-radius: 6px;"
-        "    padding: 8px 12px;"
-        "    font-size: 13px;"
-        "    background-color: white;"
-        "}"
-        
-        "QTextEdit:focus {"
-        "    border-color: #007bff;"
-        "    outline: none;"
-        "}"
-        
-        "QDateTimeEdit, QSpinBox, QComboBox {"
-        "    border: 2px solid #e9ecef;"
-        "    border-radius: 6px;"
-        "    padding: 8px 12px;"
-        "    font-size: 13px;"
-        "    background-color: white;"
-        "}"
-        
-        "QDateTimeEdit:focus, QSpinBox:focus, QComboBox:focus {"
-        "    border-color: #007bff;"
-        "    outline: none;"
-        "}"
-        
-        "QCheckBox {"
-        "    font-size: 13px;"
-        "    color: #495057;"
-        "    spacing: 8px;"
-        "}"
-        
-        "QCheckBox::indicator {"
-        "    width: 16px;"
-        "    height: 16px;"
-        "    border: 2px solid #e9ecef;"
-        "    border-radius: 3px;"
-        "    background-color: white;"
-        "}"
-        
-        "QCheckBox::indicator:checked {"
-        "    background-color: #007bff;"
-        "    border-color: #007bff;"
-        "    image: url(:/icons/check.png);"
-        "}"
-        
-        "QPushButton {"
-        "    border: none;"
-        "    border-radius: 6px;"
-        "    padding: 10px 20px;"
-        "    font-size: 13px;"
-        "    font-weight: 500;"
-        "    min-width: 80px;"
-        "}"
-        
-        "#createButton {"
-        "    background-color: #28a745;"
-        "    color: white;"
-        "}"
-        
-        "#createButton:hover {"
-        "    background-color: #218838;"
-        "}"
-        
-        "#createButton:pressed {"
-        "    background-color: #1e7e34;"
-        "}"
-        
-        "#createButton:disabled {"
-        "    background-color: #6c757d;"
-        "    color: #adb5bd;"
-        "}"
-        
-        "#cancelButton {"
-        "    background-color: #6c757d;"
-        "    color: white;"
-        "}"
-        
-        "#cancelButton:hover {"
-        "    background-color: #545b62;"
-        "}"
-        
-        "#generatePasswordButton {"
-        "    background-color: #17a2b8;"
-        "    color: white;"
-        "    min-width: 60px;"
-        "}"
-        
-        "#generatePasswordButton:hover {"
-        "    background-color: #138496;"
-        "}"
-        
-        "#generatePasswordButton:disabled {"
-        "    background-color: #6c757d;"
-        "    color: #adb5bd;"
-        "}"
-    );
-    
+    setStyleSheet("CreateMeetingDialog {"
+                  "    background-color: #f8f9fa;"
+                  "}"
+
+                  "QScrollArea {"
+                  "    border: none;"
+                  "    background-color: #f8f9fa;"
+                  "}"
+
+                  "QGroupBox {"
+                  "    font-size: 14px;"
+                  "    font-weight: bold;"
+                  "    color: #495057;"
+                  "    border: 2px solid #e9ecef;"
+                  "    border-radius: 8px;"
+                  "    margin-top: 10px;"
+                  "    background-color: white;"
+                  "}"
+
+                  "QGroupBox::title {"
+                  "    subcontrol-origin: margin;"
+                  "    left: 10px;"
+                  "    padding: 0 8px 0 8px;"
+                  "    background-color: white;"
+                  "}"
+
+                  "QLabel {"
+                  "    font-size: 13px;"
+                  "    color: #495057;"
+                  "    font-weight: 500;"
+                  "}"
+
+                  "QLineEdit {"
+                  "    border: 2px solid #e9ecef;"
+                  "    border-radius: 6px;"
+                  "    padding: 8px 12px;"
+                  "    font-size: 13px;"
+                  "    background-color: white;"
+                  "}"
+
+                  "QLineEdit:focus {"
+                  "    border-color: #007bff;"
+                  "    outline: none;"
+                  "}"
+
+                  "QLineEdit:disabled {"
+                  "    background-color: #f8f9fa;"
+                  "    color: #6c757d;"
+                  "}"
+
+                  "QTextEdit {"
+                  "    border: 2px solid #e9ecef;"
+                  "    border-radius: 6px;"
+                  "    padding: 8px 12px;"
+                  "    font-size: 13px;"
+                  "    background-color: white;"
+                  "}"
+
+                  "QTextEdit:focus {"
+                  "    border-color: #007bff;"
+                  "    outline: none;"
+                  "}"
+
+                  "QDateTimeEdit, QSpinBox, QComboBox {"
+                  "    border: 2px solid #e9ecef;"
+                  "    border-radius: 6px;"
+                  "    padding: 8px 12px;"
+                  "    font-size: 13px;"
+                  "    background-color: white;"
+                  "}"
+
+                  "QDateTimeEdit:focus, QSpinBox:focus, QComboBox:focus {"
+                  "    border-color: #007bff;"
+                  "    outline: none;"
+                  "}"
+
+                  "QCheckBox {"
+                  "    font-size: 13px;"
+                  "    color: #495057;"
+                  "    spacing: 8px;"
+                  "}"
+
+                  "QCheckBox::indicator {"
+                  "    width: 16px;"
+                  "    height: 16px;"
+                  "    border: 2px solid #e9ecef;"
+                  "    border-radius: 3px;"
+                  "    background-color: white;"
+                  "}"
+
+                  "QCheckBox::indicator:checked {"
+                  "    background-color: #007bff;"
+                  "    border-color: #007bff;"
+                  "    image: url(:/icons/check.png);"
+                  "}"
+
+                  "QPushButton {"
+                  "    border: none;"
+                  "    border-radius: 6px;"
+                  "    padding: 10px 20px;"
+                  "    font-size: 13px;"
+                  "    font-weight: 500;"
+                  "    min-width: 80px;"
+                  "}"
+
+                  "#createButton {"
+                  "    background-color: #28a745;"
+                  "    color: white;"
+                  "}"
+
+                  "#createButton:hover {"
+                  "    background-color: #218838;"
+                  "}"
+
+                  "#createButton:pressed {"
+                  "    background-color: #1e7e34;"
+                  "}"
+
+                  "#createButton:disabled {"
+                  "    background-color: #6c757d;"
+                  "    color: #adb5bd;"
+                  "}"
+
+                  "#cancelButton {"
+                  "    background-color: #6c757d;"
+                  "    color: white;"
+                  "}"
+
+                  "#cancelButton:hover {"
+                  "    background-color: #545b62;"
+                  "}"
+
+                  "#generatePasswordButton {"
+                  "    background-color: #17a2b8;"
+                  "    color: white;"
+                  "    min-width: 60px;"
+                  "}"
+
+                  "#generatePasswordButton:hover {"
+                  "    background-color: #138496;"
+                  "}"
+
+                  "#generatePasswordButton:disabled {"
+                  "    background-color: #6c757d;"
+                  "    color: #adb5bd;"
+                  "}");
+
     m_createButton->setObjectName("createButton");
     m_cancelButton->setObjectName("cancelButton");
     m_generatePasswordButton->setObjectName("generatePasswordButton");
@@ -340,13 +345,13 @@ void CreateMeetingDialog::setDefaultValues()
     QDateTime defaultTime = QDateTime::currentDateTime().addSecs(3600);
     m_startTimeEdit->setDateTime(defaultTime);
     m_startTimeEdit->setMinimumDateTime(QDateTime::currentDateTime());
-    
+
     // 设置默认时长为60分钟
     m_durationSpinBox->setValue(60);
-    
+
     // 设置默认最大参与人数为10人
     m_maxParticipantsSpinBox->setValue(10);
-    
+
     // 默认选择视频会议
     m_meetingTypeCombo->setCurrentIndex(0);
 }
@@ -355,11 +360,11 @@ void CreateMeetingDialog::onPasswordCheckChanged(bool checked)
 {
     m_passwordEdit->setEnabled(checked);
     m_generatePasswordButton->setEnabled(checked);
-    
+
     if (!checked) {
         m_passwordEdit->clear();
     }
-    
+
     validateInput();
 }
 
@@ -378,12 +383,12 @@ void CreateMeetingDialog::generateRandomPassword()
 {
     const QString chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
     QString password;
-    
+
     for (int i = 0; i < 8; ++i) {
         int index = QRandomGenerator::global()->bounded(chars.length());
         password.append(chars.at(index));
     }
-    
+
     m_passwordEdit->setText(password);
 }
 
@@ -393,12 +398,12 @@ bool CreateMeetingDialog::isValidInput() const
     if (m_meetingNameEdit->text().trimmed().isEmpty()) {
         return false;
     }
-    
+
     // 检查开始时间
     if (m_startTimeEdit->dateTime() <= QDateTime::currentDateTime()) {
         return false;
     }
-    
+
     // 如果启用了密码,检查密码有效性
     if (m_passwordCheckBox->isChecked()) {
         QString password = m_passwordEdit->text().trimmed();
@@ -406,7 +411,7 @@ bool CreateMeetingDialog::isValidInput() const
             return false;
         }
     }
-    
+
     return true;
 }
 
@@ -423,7 +428,7 @@ MeetingInfo CreateMeetingDialog::getMeetingInfo() const
     info.recordMeeting = m_recordCheckBox->isChecked();
     info.meetingType = m_meetingTypeCombo->currentText();
     info.joinAsAdmin = m_joinAsAdminCheckBox->isChecked();
-    
+
     return info;
 }
 
@@ -436,7 +441,7 @@ void CreateMeetingDialog::accept()
 {
     if (!isValidInput()) {
         QString errorMsg;
-        
+
         if (m_meetingNameEdit->text().trimmed().isEmpty()) {
             errorMsg = "请输入会议名称。";
         } else if (m_startTimeEdit->dateTime() <= QDateTime::currentDateTime()) {
@@ -447,16 +452,17 @@ void CreateMeetingDialog::accept()
                 errorMsg = "密码长度必须在6-12位之间。";
             }
         }
-        
+
         QMessageBox::warning(this, "输入错误", errorMsg);
         return;
     }
-    
+
     m_meetingInfo = getMeetingInfo();
-    QDialog::accept();
+
+    TDialog::accept();
 }
 
 void CreateMeetingDialog::reject()
 {
-    QDialog::reject();
-}
+    TDialog::reject();
+}

+ 7 - 2
widgets/createmeetingdialog.h

@@ -1,7 +1,7 @@
 #ifndef CREATEMEETINGDIALOG_H
 #define CREATEMEETINGDIALOG_H
 
-#include <QDialog>
+#include "framelessbase.h"
 #include <QVBoxLayout>
 #include <QHBoxLayout>
 #include <QFormLayout>
@@ -16,6 +16,9 @@
 #include <QGroupBox>
 #include <QDateTime>
 
+class QEventLoop;
+class QCloseEvent;
+
 struct MeetingInfo {
     QString meetingName;
     QString description;
@@ -29,11 +32,13 @@ struct MeetingInfo {
     bool joinAsAdmin; // 是否以管理员身份加入
 };
 
-class CreateMeetingDialog : public QDialog
+class CreateMeetingDialog : public TDialog
 {
     Q_OBJECT
 
 public:
+    enum DialogCode { Rejected = TDialog::Rejected, Accepted = TDialog::Accepted };
+
     explicit CreateMeetingDialog(QWidget *parent = nullptr);
     ~CreateMeetingDialog();
 

+ 258 - 0
widgets/framelessbase.cpp

@@ -13,6 +13,13 @@
 #include <QtWidgets/QApplication>
 #include <QtWidgets/QPushButton>
 #include <QtWidgets/QStyle>
+#include <QtWidgets/QMenuBar>
+#include <QtCore/QPointer>
+#include <QHBoxLayout>
+#include <QIcon>
+#include <QEventLoop>
+#include <QCloseEvent>
+#include "themesettingswidget.h"
 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
 #include <QtGui/QActionGroup>
 #else
@@ -147,9 +154,38 @@ void TMainWindow::installWindowAgent()
     windowBar->setTitleLabel(titleLabel);
     windowBar->setHostWidget(this);
 
+#ifndef Q_OS_MAC
+    // 创建一个“设置”按钮,放在标题文本区域的最右侧,使其位于置顶按钮的左侧
+    auto settingsButton = new QWK::WindowButton(windowBar);
+    settingsButton->setObjectName(QStringLiteral("settings-button"));
+    settingsButton->setProperty("system-button", true);
+    settingsButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+    settingsButton->setIconNormal(QIcon(QStringLiteral(":/window-bar/more-line.svg")));
+    QObject::connect(settingsButton, &QAbstractButton::clicked, this, [this]() {
+        static QPointer<ThemeSettingsWidget> s_settings;
+        if (!s_settings) {
+            s_settings = new ThemeSettingsWidget();
+            s_settings->setAttribute(Qt::WA_DeleteOnClose);
+            s_settings->setWindowTitle(tr("设置"));
+            s_settings->resize(520, 480);
+        }
+        s_settings->show();
+        s_settings->raise();
+        s_settings->activateWindow();
+    });
+    // 将按钮加入到 titleLabel 内部的水平布局(右对齐)
+    {
+        auto labelLayout = new QHBoxLayout(titleLabel);
+        labelLayout->setContentsMargins(0, 0, 0, 0);
+        labelLayout->addStretch();
+        labelLayout->addWidget(settingsButton);
+    }
+#endif
+
     windowAgent->setTitleBar(windowBar);
 #ifndef Q_OS_MAC
     windowAgent->setHitTestVisible(pinButton, true);
+    windowAgent->setHitTestVisible(settingsButton, true);
     windowAgent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
     windowAgent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
     windowAgent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
@@ -305,9 +341,38 @@ void TWidget::installWindowAgent()
     windowBar->setTitleLabel(titleLabel);
     windowBar->setHostWidget(this);
 
+#ifndef Q_OS_MAC
+    // 创建一个“设置”按钮,放在标题文本区域的最右侧,使其位于置顶按钮的左侧
+    auto settingsButton = new QWK::WindowButton(windowBar);
+    settingsButton->setObjectName(QStringLiteral("settings-button"));
+    settingsButton->setProperty("system-button", true);
+    settingsButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+    settingsButton->setIconNormal(QIcon(QStringLiteral(":/window-bar/more-line.svg")));
+    QObject::connect(settingsButton, &QAbstractButton::clicked, this, [this]() {
+        static QPointer<ThemeSettingsWidget> s_settings;
+        if (!s_settings) {
+            s_settings = new ThemeSettingsWidget();
+            s_settings->setAttribute(Qt::WA_DeleteOnClose);
+            s_settings->setWindowTitle(tr("设置"));
+            s_settings->resize(520, 480);
+        }
+        s_settings->show();
+        s_settings->raise();
+        s_settings->activateWindow();
+    });
+    // 将按钮加入到 titleLabel 内部的水平布局(右对齐)
+    {
+        auto labelLayout = new QHBoxLayout(titleLabel);
+        labelLayout->setContentsMargins(0, 0, 0, 0);
+        labelLayout->addStretch();
+        labelLayout->addWidget(settingsButton);
+    }
+#endif
+
     windowAgent->setTitleBar(windowBar);
 #ifndef Q_OS_MAC
     windowAgent->setHitTestVisible(pinButton, true);
+    windowAgent->setHitTestVisible(settingsButton, true);
     windowAgent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
     windowAgent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
     windowAgent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
@@ -348,3 +413,196 @@ void TWidget::installWindowAgent()
     connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);
 #endif
 }
+
+// ---------------- TDialog (QDialog-based) ----------------
+TDialog::TDialog(QWidget *parent)
+    : QDialog(parent)
+    , m_menuWidget(nullptr)
+    , m_mainLayout(nullptr)
+{
+    // QDialog 默认是 Qt::Dialog 窗口类型
+    setAttribute(Qt::WA_DontCreateNativeAncestors);
+
+    m_mainLayout = new QVBoxLayout(this);
+    m_mainLayout->setContentsMargins(0, 0, 0, 0);
+    m_mainLayout->setSpacing(0);
+    setLayout(m_mainLayout);
+
+    // 启用与 TWidget 一致的自定义无边框标题栏/按钮
+    installWindowAgent();
+}
+
+QWidget *TDialog::menuWidget() const
+{
+    return m_menuWidget;
+}
+
+void TDialog::setMenuWidget(QWidget *widget)
+{
+    if (m_menuWidget) {
+        m_mainLayout->removeWidget(m_menuWidget);
+        delete m_menuWidget;
+    }
+
+    m_menuWidget = widget;
+    if (m_menuWidget) {
+        m_mainLayout->insertWidget(0, m_menuWidget);
+    }
+}
+
+bool TDialog::event(QEvent *event)
+{
+    switch (event->type()) {
+    case QEvent::WindowActivate: {
+        auto menu = menuWidget();
+        if (menu) {
+            menu->setProperty("bar-active", true);
+            style()->polish(menu);
+        }
+        break;
+    }
+    case QEvent::WindowDeactivate: {
+        auto menu = menuWidget();
+        if (menu) {
+            menu->setProperty("bar-active", false);
+            style()->polish(menu);
+        }
+        break;
+    }
+    default:
+        break;
+    }
+    return QDialog::event(event);
+}
+
+void TDialog::installWindowAgent()
+{
+    // 1. Setup window agent
+    windowAgent = new QWK::WidgetWindowAgent(this);
+    windowAgent->setup(this);
+
+    auto titleLabel = new QLabel(windowTitle());
+    titleLabel->setAlignment(Qt::AlignCenter);
+    titleLabel->setObjectName(QStringLiteral("win-title-label"));
+
+#ifndef Q_OS_MAC
+    auto iconButton = new QWK::WindowButton();
+    iconButton->setObjectName(QStringLiteral("icon-button"));
+    iconButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+    auto pinButton = new QWK::WindowButton();
+    pinButton->setCheckable(true);
+    pinButton->setObjectName(QStringLiteral("pin-button"));
+    pinButton->setProperty("system-button", true);
+    pinButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+    auto minButton = new QWK::WindowButton();
+    minButton->setObjectName(QStringLiteral("min-button"));
+    minButton->setProperty("system-button", true);
+    minButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+    auto maxButton = new QWK::WindowButton();
+    maxButton->setCheckable(true);
+    maxButton->setObjectName(QStringLiteral("max-button"));
+    maxButton->setProperty("system-button", true);
+    maxButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+    auto closeButton = new QWK::WindowButton();
+    closeButton->setObjectName(QStringLiteral("close-button"));
+    closeButton->setProperty("system-button", true);
+    closeButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+#endif
+
+    auto windowBar = new QWK::WindowBar();
+#ifndef Q_OS_MAC
+    windowBar->setIconButton(iconButton);
+    windowBar->setPinButton(pinButton);
+    windowBar->setMinButton(minButton);
+    windowBar->setMaxButton(maxButton);
+    windowBar->setCloseButton(closeButton);
+#endif
+    windowBar->setTitleLabel(titleLabel);
+    windowBar->setHostWidget(this);
+
+#ifndef Q_OS_MAC
+    // 创建一个“设置”按钮,放在标题文本区域的最右侧,使其位于置顶按钮的左侧
+    auto settingsButton = new QWK::WindowButton(windowBar);
+    settingsButton->setObjectName(QStringLiteral("settings-button"));
+    settingsButton->setProperty("system-button", true);
+    settingsButton->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+    settingsButton->setIconNormal(QIcon(QStringLiteral(":/window-bar/more-line.svg")));
+    QObject::connect(settingsButton, &QAbstractButton::clicked, this, [this]() {
+        static QPointer<ThemeSettingsWidget> s_settings;
+        if (!s_settings) {
+            s_settings = new ThemeSettingsWidget();
+            s_settings->setAttribute(Qt::WA_DeleteOnClose);
+            s_settings->setWindowTitle(tr("设置"));
+            s_settings->resize(520, 480);
+        }
+        s_settings->show();
+        s_settings->raise();
+        s_settings->activateWindow();
+    });
+    // 将按钮加入到 titleLabel 内部的水平布局(右对齐)
+    {
+        auto labelLayout = new QHBoxLayout(titleLabel);
+        labelLayout->setContentsMargins(0, 0, 0, 0);
+        labelLayout->addStretch();
+        labelLayout->addWidget(settingsButton);
+    }
+#endif
+
+    windowAgent->setTitleBar(windowBar);
+#ifndef Q_OS_MAC
+    windowAgent->setHitTestVisible(pinButton, true);
+    windowAgent->setHitTestVisible(settingsButton, true);
+    windowAgent->setSystemButton(QWK::WindowAgentBase::WindowIcon, iconButton);
+    windowAgent->setSystemButton(QWK::WindowAgentBase::Minimize, minButton);
+    windowAgent->setSystemButton(QWK::WindowAgentBase::Maximize, maxButton);
+    windowAgent->setSystemButton(QWK::WindowAgentBase::Close, closeButton);
+#endif
+
+#ifdef Q_OS_MAC
+    windowAgent->setSystemButtonAreaCallback([](const QSize &size) {
+        static constexpr const int width = 75;
+        return QRect(QPoint(size.width() - width, 0), QSize(width, size.height())); //
+    });
+#endif
+
+    setMenuWidget(windowBar);
+
+#ifndef Q_OS_MAC
+    connect(this, &QDialog::windowTitleChanged, this, [titleLabel](const QString &title) {
+        titleLabel->setText(title);
+    });
+
+    connect(windowBar, &QWK::WindowBar::pinRequested, this, [this, pinButton](bool pin) {
+        if (isHidden() || isMinimized() || isMaximized() || isFullScreen()) {
+            return;
+        }
+        setWindowFlag(Qt::WindowStaysOnTopHint, pin);
+        show();
+        pinButton->setChecked(pin);
+    });
+    connect(windowBar, &QWK::WindowBar::minimizeRequested, this, &QWidget::showMinimized);
+    connect(windowBar, &QWK::WindowBar::maximizeRequested, this, [this, maxButton](bool max) {
+        if (max) {
+            showMaximized();
+        } else {
+            showNormal();
+        }
+        emulateLeaveEvent(maxButton);
+    });
+    connect(windowBar, &QWK::WindowBar::closeRequested, this, &QWidget::close);
+#endif
+}
+
+void TDialog::accept()
+{
+    QDialog::accept();
+}
+
+void TDialog::reject()
+{
+    QDialog::reject();
+}

+ 36 - 8
widgets/framelessbase.h

@@ -6,8 +6,11 @@
 #include <QMainWindow>
 #include <QMenuBar>
 #include <QMessageBox>
+#include <QDialog>
 
 class QVBoxLayout;
+class QEventLoop;
+class QCloseEvent;
 
 namespace QWK {
 class WidgetWindowAgent;
@@ -34,21 +37,46 @@ class TWidget : public QWidget
     Q_OBJECT
 public:
     explicit TWidget(QWidget *parent = nullptr);
-    ~TWidget() override {}
-
+    QWidget *menuWidget() const;
+    void setMenuWidget(QWidget *widget);
     QVBoxLayout *mainLayout() const { return m_mainLayout; }
 
-    QWidget *menuWidget() const;         // 获取当前标题栏
-    void setMenuWidget(QWidget *widget); // 设置新的标题栏
 protected:
     bool event(QEvent *event) override;
+    void installWindowAgent();
 
-private:
+protected:
+    QWK::WidgetWindowAgent *windowAgent = nullptr;
+    QWidget *m_menuWidget = nullptr;
+    QVBoxLayout *m_mainLayout = nullptr;
+};
+
+// 轻量对话框基类:继承 QDialog,并复用与 TWidget 一致的无边框窗口代理/标题栏能力
+class TDialog : public QDialog
+{
+    Q_OBJECT
+public:
+    enum DialogCode { Rejected = QDialog::Rejected, Accepted = QDialog::Accepted };
+
+    explicit TDialog(QWidget *parent = nullptr);
+    ~TDialog() override = default;
+
+    QWidget *menuWidget() const;
+    void setMenuWidget(QWidget *widget);
+    QVBoxLayout *mainLayout() const { return m_mainLayout; }
+
+public slots:
+    void accept() override;  // 包装到 QDialog::accept()
+    void reject() override;  // 包装到 QDialog::reject()
+
+protected:
+    bool event(QEvent *event) override;
     void installWindowAgent();
-    QWK::WidgetWindowAgent *windowAgent;
 
-    QWidget *m_menuWidget = nullptr;     // 存储当前标题栏
-    QVBoxLayout *m_mainLayout = nullptr; // 主布局
+private:
+    QWK::WidgetWindowAgent *windowAgent = nullptr;
+    QWidget *m_menuWidget = nullptr;
+    QVBoxLayout *m_mainLayout = nullptr;
 };
 
 #endif // FRAMELESSBASE_H

+ 48 - 158
widgets/joinmeetingdialog.cpp

@@ -2,9 +2,10 @@
 #include <QMessageBox>
 #include <QRegularExpression>
 #include <QRegularExpressionValidator>
+// 移除:#include <QEventLoop> 与 #include <QCloseEvent>
 
 JoinMeetingDialog::JoinMeetingDialog(QWidget *parent)
-    : QDialog(parent)
+    : TDialog(parent)
     , m_mainLayout(nullptr)
     , m_tabWidget(nullptr)
     , m_manualTab(nullptr)
@@ -20,221 +21,108 @@ JoinMeetingDialog::JoinMeetingDialog(QWidget *parent)
     , m_cancelButton(nullptr)
 {
     setWindowTitle("加入会议");
-    setModal(true);
     resize(400, 300);
-    
+
     setupUI();
-    applyStyles();
-    
+
     // 默认选择手动输入标签页
     m_tabWidget->setCurrentIndex(0);
-    
+
     // 初始状态下禁用加入按钮
     m_joinButton->setEnabled(false);
 }
 
-JoinMeetingDialog::~JoinMeetingDialog()
-{
-}
+JoinMeetingDialog::~JoinMeetingDialog() {}
 
 void JoinMeetingDialog::setupUI()
 {
-    m_mainLayout = new QVBoxLayout(this);
+    QWidget *content = new QWidget(this);
+    m_mainLayout = new QVBoxLayout(content);
     m_mainLayout->setContentsMargins(20, 20, 20, 20);
     m_mainLayout->setSpacing(15);
-    
+
     // 创建标签页控件
-    m_tabWidget = new QTabWidget(this);
-    
+    m_tabWidget = new QTabWidget(content);
+
     // 手动输入标签页
     m_manualTab = new QWidget();
     m_manualLayout = new QVBoxLayout(m_manualTab);
     m_manualLayout->setContentsMargins(15, 15, 15, 15);
     m_manualLayout->setSpacing(10);
-    
+
     m_manualLabel = new QLabel("请输入会议ID:", m_manualTab);
     m_meetingIdEdit = new QLineEdit(m_manualTab);
     m_meetingIdEdit->setPlaceholderText("例如:123456789");
-    
+
     // 设置输入验证器(只允许数字和字母)
     QRegularExpression regex("[A-Za-z0-9]{1,20}");
     QRegularExpressionValidator *validator = new QRegularExpressionValidator(regex, this);
     m_meetingIdEdit->setValidator(validator);
-    
+
     connect(m_meetingIdEdit, &QLineEdit::textChanged, this, &JoinMeetingDialog::onMeetingIdChanged);
-    
+
     m_manualLayout->addWidget(m_manualLabel);
     m_manualLayout->addWidget(m_meetingIdEdit);
     m_manualLayout->addStretch();
-    
+
     m_tabWidget->addTab(m_manualTab, "手动输入");
-    
+
     // 选择会议标签页
     m_selectTab = new QWidget();
     m_selectLayout = new QVBoxLayout(m_selectTab);
     m_selectLayout->setContentsMargins(15, 15, 15, 15);
     m_selectLayout->setSpacing(10);
-    
+
     m_selectLabel = new QLabel("选择可用的会议:", m_selectTab);
     m_meetingListWidget = new QListWidget(m_selectTab);
-    
-    connect(m_meetingListWidget, &QListWidget::itemClicked, this, &JoinMeetingDialog::onMeetingItemClicked);
+
+    connect(m_meetingListWidget,
+            &QListWidget::itemClicked,
+            this,
+            &JoinMeetingDialog::onMeetingItemClicked);
     connect(m_meetingListWidget, &QListWidget::itemDoubleClicked, this, &JoinMeetingDialog::accept);
-    
+
     m_selectLayout->addWidget(m_selectLabel);
     m_selectLayout->addWidget(m_meetingListWidget);
-    
+
     m_tabWidget->addTab(m_selectTab, "选择会议");
-    
+
     // 按钮布局
     m_buttonLayout = new QHBoxLayout();
     m_buttonLayout->addStretch();
-    
-    m_cancelButton = new QPushButton("取消", this);
-    m_joinButton = new QPushButton("加入会议", this);
-    
+
+    m_cancelButton = new QPushButton("取消", content);
+    m_joinButton = new QPushButton("加入会议", content);
+
     connect(m_cancelButton, &QPushButton::clicked, this, &JoinMeetingDialog::reject);
     connect(m_joinButton, &QPushButton::clicked, this, &JoinMeetingDialog::accept);
-    
+
     m_buttonLayout->addWidget(m_cancelButton);
     m_buttonLayout->addWidget(m_joinButton);
-    
+
     // 添加到主布局
     m_mainLayout->addWidget(m_tabWidget);
     m_mainLayout->addLayout(m_buttonLayout);
-}
 
-void JoinMeetingDialog::applyStyles()
-{
-    setStyleSheet(
-        "JoinMeetingDialog {"
-        "    background-color: #f8f9fa;"
-        "}"
-        
-        "QTabWidget::pane {"
-        "    border: 1px solid #dee2e6;"
-        "    border-radius: 5px;"
-        "    background-color: white;"
-        "}"
-        
-        "QTabWidget::tab-bar {"
-        "    alignment: center;"
-        "}"
-        
-        "QTabBar::tab {"
-        "    background-color: #e9ecef;"
-        "    border: 1px solid #dee2e6;"
-        "    border-bottom: none;"
-        "    border-top-left-radius: 5px;"
-        "    border-top-right-radius: 5px;"
-        "    padding: 8px 16px;"
-        "    margin-right: 2px;"
-        "}"
-        
-        "QTabBar::tab:selected {"
-        "    background-color: white;"
-        "    border-bottom: 1px solid white;"
-        "}"
-        
-        "QTabBar::tab:hover {"
-        "    background-color: #f8f9fa;"
-        "}"
-        
-        "QLabel {"
-        "    font-size: 14px;"
-        "    color: #495057;"
-        "    font-weight: 500;"
-        "}"
-        
-        "QLineEdit {"
-        "    border: 2px solid #e9ecef;"
-        "    border-radius: 6px;"
-        "    padding: 8px 12px;"
-        "    font-size: 14px;"
-        "    background-color: white;"
-        "}"
-        
-        "QLineEdit:focus {"
-        "    border-color: #007bff;"
-        "    outline: none;"
-        "}"
-        
-        "QListWidget {"
-        "    border: 2px solid #e9ecef;"
-        "    border-radius: 6px;"
-        "    background-color: white;"
-        "    selection-background-color: #007bff;"
-        "    selection-color: white;"
-        "}"
-        
-        "QListWidget::item {"
-        "    padding: 8px 12px;"
-        "    border-bottom: 1px solid #f8f9fa;"
-        "}"
-        
-        "QListWidget::item:hover {"
-        "    background-color: #f8f9fa;"
-        "}"
-        
-        "QPushButton {"
-        "    border: none;"
-        "    border-radius: 6px;"
-        "    padding: 10px 20px;"
-        "    font-size: 14px;"
-        "    font-weight: 500;"
-        "    min-width: 80px;"
-        "}"
-        
-        "#joinButton {"
-        "    background-color: #007bff;"
-        "    color: white;"
-        "}"
-        
-        "#joinButton:hover {"
-        "    background-color: #0056b3;"
-        "}"
-        
-        "#joinButton:pressed {"
-        "    background-color: #004085;"
-        "}"
-        
-        "#joinButton:disabled {"
-        "    background-color: #6c757d;"
-        "    color: #adb5bd;"
-        "}"
-        
-        "#cancelButton {"
-        "    background-color: #6c757d;"
-        "    color: white;"
-        "}"
-        
-        "#cancelButton:hover {"
-        "    background-color: #545b62;"
-        "}"
-        
-        "#cancelButton:pressed {"
-        "    background-color: #3d4142;"
-        "}"
-    );
-    
-    m_joinButton->setObjectName("joinButton");
-    m_cancelButton->setObjectName("cancelButton");
+    // 挂到 TWidget 的内容区
+    mainLayout()->addWidget(content);
 }
 
-void JoinMeetingDialog::setAvailableMeetings(const QStringList &meetingIds, const QStringList &meetingNames)
+void JoinMeetingDialog::setAvailableMeetings(const QStringList &meetingIds,
+                                             const QStringList &meetingNames)
 {
     m_meetingIds = meetingIds;
     m_meetingNames = meetingNames;
-    
+
     m_meetingListWidget->clear();
-    
+
     for (int i = 0; i < meetingIds.size() && i < meetingNames.size(); ++i) {
         QString displayText = QString("%1 - %2").arg(meetingIds[i], meetingNames[i]);
         QListWidgetItem *item = new QListWidgetItem(displayText);
         item->setData(Qt::UserRole, meetingIds[i]); // 存储会议ID
         m_meetingListWidget->addItem(item);
     }
-    
+
     // 如果没有可用会议,禁用选择标签页
     m_tabWidget->setTabEnabled(1, !meetingIds.isEmpty());
 }
@@ -265,7 +153,7 @@ void JoinMeetingDialog::onMeetingIdChanged()
 void JoinMeetingDialog::validateInput()
 {
     bool isValid = false;
-    
+
     if (m_tabWidget->currentIndex() == 0) { // 手动输入
         isValid = !m_meetingIdEdit->text().trimmed().isEmpty();
         m_selectedMeetingId = m_meetingIdEdit->text().trimmed();
@@ -276,24 +164,26 @@ void JoinMeetingDialog::validateInput()
             m_selectedMeetingId = currentItem->data(Qt::UserRole).toString();
         }
     }
-    
+
     m_joinButton->setEnabled(isValid);
 }
 
 void JoinMeetingDialog::accept()
 {
     validateInput();
-    
+
     if (m_selectedMeetingId.isEmpty()) {
         QMessageBox::warning(this, "输入错误", "请输入或选择一个有效的会议ID。");
         return;
     }
-    
-    QDialog::accept();
+
+    TDialog::accept();
 }
 
 void JoinMeetingDialog::reject()
 {
     m_selectedMeetingId.clear();
-    QDialog::reject();
-}
+    TDialog::reject();
+}
+
+// 末尾不再包含 exec()/closeEvent 的本地实现,使用 TDialog 的默认实现

+ 12 - 7
widgets/joinmeetingdialog.h

@@ -1,7 +1,7 @@
 #ifndef JOINMEETINGDIALOG_H
 #define JOINMEETINGDIALOG_H
 
-#include <QDialog>
+#include "framelessbase.h"
 #include <QVBoxLayout>
 #include <QHBoxLayout>
 #include <QLabel>
@@ -12,11 +12,17 @@
 #include <QGroupBox>
 #include <QStringList>
 
-class JoinMeetingDialog : public QDialog
+class QEventLoop;
+class QCloseEvent;
+
+class JoinMeetingDialog : public TDialog
 {
     Q_OBJECT
 
 public:
+    // 兼容性映射:保持 JoinMeetingDialog::Accepted 可用
+    enum DialogCode { Rejected = TDialog::Rejected, Accepted = TDialog::Accepted };
+
     explicit JoinMeetingDialog(QWidget *parent = nullptr);
     ~JoinMeetingDialog();
 
@@ -27,8 +33,8 @@ public:
     void setAvailableMeetings(const QStringList &meetingIds, const QStringList &meetingNames);
 
 public slots:
-    void accept() override;
-    void reject() override;
+    void accept() override;  // 验证后调用 TDialog::accept()
+    void reject() override;  // 清理后调用 TDialog::reject()
 
 private slots:
     void onMeetingItemClicked();
@@ -37,8 +43,7 @@ private slots:
 
 private:
     void setupUI();
-    void applyStyles();
-    
+
     // UI组件
     QVBoxLayout *m_mainLayout;
     QTabWidget *m_tabWidget;
@@ -66,4 +71,4 @@ private:
     QStringList m_meetingNames;
 };
 
-#endif // JOINMEETINGDIALOG_H
+#endif // JOINMEETINGDIALOG_H