工作日志5/28/14 - setfocus() & add 'I accept' chekbox with validation

本文记录了一天的技术工作经历,包括为networkaccount添加用户同意的复选框,处理数据库列,理解SQL中布尔类型bit的使用,以及在代码中发现并解决了屏幕重新聚焦的问题。此外,还对文档进行了整理,工作内容丰富且涉及多个技术点。

今天一早三点半起来送老陆教授去机场,回来困个半死,彻头彻尾的老学究啊。

八点半来了办公室,开撸。给network account加了个I accept的checkbox,然后搞定了数据库的一个column。SQL的bit是An integer data type that can take a value of 1, 0, or NULL. 就是Boolean,true是1,FALSE是0,另外多一个NULL。

看代码还发现了个好玩的method叫setfocus(),之前总觉得每次点完一个按键屏幕就晃一下,原来这就是元凶,他使得屏幕每次都重新focus,调整用户的页面视角,其实没啥大用,谁知道为啥老头爱用。。

花了一个小时搞定了,三步走,

1. 加一个row,搞定名字和调用的method,enabled那个属性设置为FALSE,不能说disabled因为aSP里面改不了这个。

2. 写method,为了实现只有在点了I accept之后才能有submit request,否则是虚的,这就得用到ifelse判断这个checkbox是否有值,如有则改变button的enable属性为真,否则为假。

'Added by CQ 5/28/14, the 'Submit Request' button should not be allowed to be clicked until the checkbox is checked.
    Protected Sub cbxAccept_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        If Me.cbxAccept.Items(0).Selected = True Then
            btnclick.Enabled = True
        Else
            btnclick.Enabled = False
        End If
    End Sub

3. 修改SQL insert语句,加一项‘Accept’(本来在DB就有),注意前面要有逗号,否则就是invalid near ‘Accept'. 由于Accept是bit属性,前面已介绍,所以1要用引号括起来,这样是SQL的语句。

下午就搞了搞documentation,一点也不累,一天就这么过去了。

// ------------------------- 构造函数 ------------------------- SystemSettingsWidget::SystemSettingsWidget(QWidget *parent) : QWidget(parent) // 初始化父类QWidget , ui(new Ui::SystemSettingsWidget) // 创建UI对象 { setFixedSize(400,600); // 设置固定窗口大小 ui->setupUi(this); // 加载UI界面文件 // 初始化UI组件 createUI(); // 加载当前系统设置 loadSettings(); } // ------------------------- 析构函数 ------------------------- SystemSettingsWidget::~SystemSettingsWidget() { delete ui; // 释放UI对象内存 } // ------------------------- 创建系统设置UI ------------------------- void SystemSettingsWidget::createUI() { /* 创建并初始化所有设置控件 */ // 数据库路径相关控件 dbPathEdit = new QLineEdit(this); // 数据库路径输入框 browseBtn = new QPushButton("浏览...", this); // 浏览按钮 // 密码修改相关控件 oldPwdEdit = new QLineEdit(this); // 旧密码输入框 newPwdEdit = new QLineEdit(this); // 新密码输入框 confirmPwdEdit = new QLineEdit(this); // 确认密码输入框 // 设置密码输入框为密码模式(显示为圆点) oldPwdEdit->setEchoMode(QLineEdit::Password); newPwdEdit->setEchoMode(QLineEdit::Password); confirmPwdEdit->setEchoMode(QLineEdit::Password); // 版本信息显示控件 versionInfoEdit = new QTextEdit(this); // 版本信息文本框 versionInfoEdit->setPlainText("开发环境:QT C++ 6.6,Qt Creator 12.0.2,Win11"); // 设置默认版本信息 versionInfoEdit->setReadOnly(true); // 设置为只读 // 缓存设置复选框 cacheCheckBox = new QCheckBox("记住登录信息", this); // 记住登录信息复选框 // 保存按钮 saveBtn = new QPushButton("保存", this); // 保存设置按钮 // 创建主网格布局 mainLayout = new QGridLayout(this); // 添加控件到布局 mainLayout->addWidget(new QLabel("数据库路径:", this), 0, 0); // 数据库路径标签 mainLayout->addWidget(dbPathEdit, 0, 1); // 数据库路径输入框 mainLayout->addWidget(browseBtn, 0, 2); // 浏览按钮 mainLayout->addWidget(new QLabel("旧密码:", this), 1, 0); // 旧密码标签 mainLayout->addWidget(oldPwdEdit, 1, 1, 1, 2); // 旧密码输入框(跨2列) mainLayout->addWidget(new QLabel("新密码:", this), 2, 0); // 新密码标签 mainLayout->addWidget(newPwdEdit, 2, 1, 1, 2); // 新密码输入框(跨2列) mainLayout->addWidget(new QLabel("确认密码:", this), 3, 0); // 确认密码标签 mainLayout->addWidget(confirmPwdEdit, 3, 1, 1, 2); // 确认密码输入框(跨2列) mainLayout->addWidget(cacheCheckBox, 4, 0, 1, 3); // 缓存复选框(跨3列) mainLayout->addWidget(saveBtn, 5, 1, 1, 2); // 保存按钮(跨2列) mainLayout->addWidget(versionInfoEdit, 6, 0, 1, 3); // 版本信息文本框(跨3列) // 设置主布局 setLayout(mainLayout); // 连接信号与槽 connect(browseBtn, &QPushButton::clicked, this, &SystemSettingsWidget::browseDatabasePath); // 浏览按钮点击事件 connect(saveBtn, &QPushButton::clicked, this, &SystemSettingsWidget::saveSettings); // 保存按钮点击事件 }参考这段代码来写coze.cpp里的setupUI()函数
06-26
我给你目前的代码#ifndef COZE_H #define COZE_H #include <QWidget> #include <QNetworkAccessManager> #include <QNetworkReply> #include <QJsonArray> #include <QJsonObject> #include <QString> #include <QMap> class QVBoxLayout; class QHBoxLayout; class QLineEdit; class QTextEdit; class QPushButton; class QComboBox; class QProgressBar; class QLabel; class coze : public QWidget { Q_OBJECT public: explicit coze(QWidget *parent = nullptr); ~coze(); void setApiCredentials(const QString& token, const QString& id); private slots: void onSendClicked(); void onInputFinished(); void onClearClicked(); void onHistoryClicked(); void onModelChanged(int index); void handleCozeResponse(QNetworkReply* reply); private: void setupUI(); void loadSettings(); void saveSettings(); void resetInputState(); void showError(const QString& message); void appendMessage(const QString& sender, const QString& message, bool isError = false); void sendQueryToCoze(const QString& query); QJsonArray convertToAdditionalMessages(); void saveConversationHistory(); void loadConversationHistory(const QString& filePath = QString()); void processStreamEvent(const QString& eventName, const QJsonObject& data); void handleDeltaMessage(const QJsonObject& messageObj); void handleCompletedMessage(const QJsonObject& messageObj); void handleChatEvent(const QJsonObject& chatObj); void loadConversationHistory(); void appendMessage(const QString& sender, const QString& message); private: QNetworkAccessManager *networkManager; QString apiToken; QString botId; QString userId; QString conversationId; // 新增会话ID QString chatId; // 新增对话ID // UI Elements QLabel *titleLabel; QLabel *statusLabel; QComboBox *modelComboBox; QTextEdit *conversationArea; QLineEdit *inputBox; QPushButton *sendButton; QPushButton *clearButton; QPushButton *historyButton; QProgressBar *progressBar; QJsonArray conversationHistory; // 流式响应处理 QByteArray partialResponse; QString currentAssistantMessageId; QString currentAssistantContent; }; #endif // COZE_H #include "coze.h" #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QVBoxLayout> #include <QHBoxLayout> #include <QLineEdit> #include <QTextEdit> #include <QPushButton> #include <QComboBox> #include <QProgressBar> #include <QJsonDocument> #include <QJsonObject> #include <QJsonArray> #include <QUrl> #include <QMessageBox> #include <QDateTime> #include <QDebug> #include <QSettings> #include <QScrollBar> #include <QShortcut> #include <QFont> #include <QFile> #include <QDir> #include <QStandardPaths> #include <QLabel> #include <QRegularExpression> #include <QListWidget> #include <QDialog> #include <QListWidgetItem> #include <QUrlQuery> // ------------------------- 构造函数 ------------------------- coze::coze(QWidget *parent) : QWidget(parent) , networkManager(new QNetworkAccessManager(this)) , apiToken("") , botId("") , userId("123456789") , conversationId("") , chatId("") { setupUI(); loadSettings(); connect(networkManager, &QNetworkAccessManager::finished, this, &coze::handleCozeResponse); } // ------------------------- 析构函数 ------------------------- coze::~coze() { saveSettings(); } // ------------------------- 设置API凭证 ------------------------- void coze::setApiCredentials(const QString& token, const QString& id) { apiToken = token; botId = id; saveSettings(); } // ------------------------- 创建UI界面 ------------------------- void coze::setupUI() { // 主布局 QVBoxLayout *mainLayout = new QVBoxLayout(this); // 对话区域 conversationArea = new QTextEdit(this); conversationArea->setReadOnly(true); conversationArea->setFont(QFont("Arial", 12)); conversationArea->setStyleSheet("background-color: #f9f9f9; border: 1px solid #ddd;"); mainLayout->addWidget(conversationArea); // 输入区域 QHBoxLayout *inputLayout = new QHBoxLayout(); inputBox = new QLineEdit(this); inputBox->setPlaceholderText("输入您的问题..."); connect(inputBox, &QLineEdit::returnPressed, this, &coze::onInputFinished); inputLayout->addWidget(inputBox); sendButton = new QPushButton("发送", this); connect(sendButton, &QPushButton::clicked, this, &coze::onSendClicked); inputLayout->addWidget(sendButton); clearButton = new QPushButton("清除", this); connect(clearButton, &QPushButton::clicked, this, &coze::onClearClicked); inputLayout->addWidget(clearButton); historyButton = new QPushButton("历史", this); connect(historyButton, &QPushButton::clicked, this, &coze::onHistoryClicked); inputLayout->addWidget(historyButton); mainLayout->addLayout(inputLayout); // 模型选择 QHBoxLayout *modelLayout = new QHBoxLayout(); modelLayout->addWidget(new QLabel("模型:", this)); modelComboBox = new QComboBox(this); modelComboBox->addItem("默认", ""); modelComboBox->addItem("GPT-4", "gpt-4"); modelComboBox->addItem("GPT-3.5", "gpt-3.5-turbo"); modelComboBox->addItem("Claude", "claude-2"); connect(modelComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &coze::onModelChanged); modelLayout->addWidget(modelComboBox); mainLayout->addLayout(modelLayout); // 进度条 progressBar = new QProgressBar(this); progressBar->setRange(0, 0); // 不确定进度 progressBar->setVisible(false); mainLayout->addWidget(progressBar); // 状态标签 statusLabel = new QLabel("准备就绪", this); statusLabel->setAlignment(Qt::AlignCenter); statusLabel->setStyleSheet("color: #666; font-size: 10pt;"); mainLayout->addWidget(statusLabel); // 设置布局 setLayout(mainLayout); setWindowTitle("Coze API 客户端"); resize(800, 600); } // ------------------------- 加载设置 ------------------------- void coze::loadSettings() { QSettings settings("CozeClient", "Settings"); apiToken = settings.value("apiToken", "").toString(); botId = settings.value("botId", "").toString(); userId = settings.value("userId", "123456789").toString(); conversationId = settings.value("conversationId", "").toString(); // 加载对话历史 loadConversationHistory(); } // ------------------------- 保存设置 ------------------------- void coze::saveSettings() { QSettings settings("CozeClient", "Settings"); settings.setValue("apiToken", apiToken); settings.setValue("botId", botId); settings.setValue("userId", userId); settings.setValue("conversationId", conversationId); // 保存对话历史 saveConversationHistory(); } // ------------------------- 加载对话历史 ------------------------- void coze::loadConversationHistory() { QSettings settings("CozeClient", "ConversationHistory"); QJsonArray historyArray = QJsonDocument::fromJson( settings.value("history", "[]").toByteArray() ).array(); conversationHistory = historyArray; // 在UI中显示历史 for (const QJsonValue &value : historyArray) { QJsonObject message = value.toObject(); QString role = message["role"].toString(); QString content = message["content"].toString(); if (!content.isEmpty()) { appendMessage(role == "user" ? "用户" : "AI", content); } } } // ------------------------- 保存对话历史 ------------------------- void coze::saveConversationHistory() { QSettings settings("CozeClient", "ConversationHistory"); QJsonDocument doc(conversationHistory); settings.setValue("history", doc.toJson(QJsonDocument::Compact)); } // ------------------------- 发送消息 ------------------------- void coze::onSendClicked() { QString query = inputBox->text().trimmed(); if (query.isEmpty()) { showError("请输入问题内容"); return; } // 添加到对话历史(用户消息) QJsonObject userMessage; userMessage["role"] = "user"; userMessage["content"] = query; userMessage["content_type"] = "text"; conversationHistory.append(userMessage); // 更新UI appendMessage("用户", query); inputBox->clear(); appendMessage("AI", "正在思考,请稍候..."); // 禁用输入 inputBox->setEnabled(false); sendButton->setEnabled(false); progressBar->setVisible(true); statusLabel->setText("请求发送中..."); // 发送请求 sendQueryToCoze(query); } // ------------------------- 输入完成(回车键) ------------------------- void coze::onInputFinished() { onSendClicked(); } // ------------------------- 清除对话 ------------------------- void coze::onClearClicked() { conversationArea->clear(); conversationHistory = QJsonArray(); conversationId = ""; chatId = ""; saveConversationHistory(); statusLabel->setText("对话已清除"); } // ------------------------- 显示历史记录 ------------------------- void coze::onHistoryClicked() { QDialog historyDialog(this); historyDialog.setWindowTitle("对话历史"); historyDialog.resize(600, 400); QVBoxLayout *layout = new QVBoxLayout(&historyDialog); QListWidget *historyList = new QListWidget(&historyDialog); for (const QJsonValue &value : conversationHistory) { QJsonObject message = value.toObject(); QString role = message["role"].toString(); QString content = message["content"].toString(); if (!content.isEmpty()) { QListWidgetItem *item = new QListWidgetItem( QString("%1: %2").arg(role == "user" ? "用户" : "AI").arg(content) ); historyList->addItem(item); } } layout->addWidget(historyList); historyDialog.exec(); } // ------------------------- 模型改变 ------------------------- void coze::onModelChanged(int index) { Q_UNUSED(index); // 可以添加模型切换后的处理逻辑 } // ------------------------- 转换对话历史为additional_messages格式 ------------------------- QJsonArray coze::convertToAdditionalMessages() { QJsonArray additionalMessages; // 只保留最近的5条消息(避免上下文过长) int startIndex = qMax(0, conversationHistory.size() - 5); for (int i = startIndex; i < conversationHistory.size(); i++) { QJsonObject message = conversationHistory[i].toObject(); QJsonObject additionalMessage; additionalMessage["role"] = message["role"]; additionalMessage["content"] = message["content"]; additionalMessage["content_type"] = message["content_type"]; additionalMessages.append(additionalMessage); } return additionalMessages; } // ------------------------- 发送请求到Coze API ------------------------- void coze::sendQueryToCoze(const QString& query) { if (apiToken.isEmpty() || botId.isEmpty()) { showError("API凭证未设置,请先配置API密钥"); resetInputState(); return; } QNetworkRequest request; QUrl url("https://api.coze.cn/v3/chat"); // 添加会话ID查询参数 if (!conversationId.isEmpty()) { QUrlQuery urlQuery; urlQuery.addQueryItem("conversation_id", conversationId); url.setQuery(urlQuery); } request.setUrl(url); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request.setRawHeader("Authorization", ("Bearer " + apiToken).toUtf8()); // 构建请求体 QJsonObject requestBody; requestBody["bot_id"] = botId; requestBody["user_id"] = userId; requestBody["stream"] = false; // 禁用流式响应 requestBody["auto_save_history"] = true; // 转换对话历史 QJsonArray additionalMessages = convertToAdditionalMessages(); requestBody["additional_messages"] = additionalMessages; // 添加模型参数 QString model = modelComboBox->currentData().toString(); if (!model.isEmpty()) { requestBody["model"] = model; } // 调试输出请求信息 qDebug() << "Authorization Header:" << ("Bearer " + apiToken); qDebug() << "Request URL:" << request.url().toString(); QJsonDocument reqDoc(requestBody); qDebug() << "Request Body:" << reqDoc.toJson(QJsonDocument::Indented); // 发送POST请求 networkManager->post(request, reqDoc.toJson()); } // ------------------------- 处理API响应 ------------------------- void coze::handleCozeResponse(QNetworkReply* reply) { if (reply->error() != QNetworkReply::NoError) { showError("网络错误: " + reply->errorString()); resetInputState(); reply->deleteLater(); return; } QByteArray responseData = reply->readAll(); reply->deleteLater(); // 调试输出原始响应 qDebug() << "API Response:" << QString(responseData); // 解析完整响应 QJsonParseError parseError; QJsonDocument jsonDoc = QJsonDocument::fromJson(responseData, &parseError); if (parseError.error != QJsonParseError::NoError) { showError("JSON解析错误: " + parseError.errorString()); resetInputState(); return; } if (!jsonDoc.isObject()) { showError("API返回格式错误"); resetInputState(); return; } QJsonObject responseObj = jsonDoc.object(); // 检查API状态码 if (responseObj.contains("code")) { int code = responseObj["code"].toInt(); if (code != 0) { QString errorMsg = responseObj["msg"].toString("未知错误"); showError(QString("API错误 [%1]: %2").arg(code).arg(errorMsg)); resetInputState(); return; } } // 检查data字段 if (!responseObj.contains("data")) { showError("API响应缺少data字段"); resetInputState(); return; } QJsonObject dataObj = responseObj["data"].toObject(); // 获取完整消息内容 QString aiResponse = ""; if (dataObj.contains("messages")) { QJsonArray messages = dataObj["messages"].toArray(); for (const QJsonValue &message : messages) { QJsonObject msgObj = message.toObject(); if (msgObj["role"].toString() == "assistant" && msgObj["type"].toString() == "answer") { aiResponse = msgObj["content"].toString(); break; } } } // 更新会话ID if (dataObj.contains("conversation_id")) { conversationId = dataObj["conversation_id"].toString(); qDebug() << "更新会话ID:" << conversationId; } // 更新对话ID if (dataObj.contains("id")) { chatId = dataObj["id"].toString(); qDebug() << "更新对话ID:" << chatId; } // 移除"正在思考"消息 QString lastHtml = conversationArea->toHtml(); if (lastHtml.contains("正在思考")) { lastHtml.replace("<b>AI:</b> 正在思考,请稍候...<br>", ""); conversationArea->setHtml(lastHtml); } // 添加完整的AI响应 if (!aiResponse.isEmpty()) { appendMessage("AI", aiResponse); // 添加到对话历史 QJsonObject aiMessage; aiMessage["role"] = "assistant"; aiMessage["content"] = aiResponse; conversationHistory.append(aiMessage); // 保存对话历史 saveConversationHistory(); statusLabel->setText("响应接收成功"); } else { showError("未收到有效的AI响应"); } resetInputState(); } // ------------------------- 添加消息到对话区域 ------------------------- void coze::appendMessage(const QString& sender, const QString& message) { QString formattedMessage = QString("<b>%1:</b> %2<br>").arg(sender).arg(message); conversationArea->append(formattedMessage); // 滚动到底部 QScrollBar *scrollbar = conversationArea->verticalScrollBar(); scrollbar->setValue(scrollbar->maximum()); } // ------------------------- 显示错误消息 ------------------------- void coze::showError(const QString& error) { statusLabel->setText("<span style='color:red;'>错误: " + error + "</span>"); QMessageBox::critical(this, "错误", error); } // ------------------------- 重置输入状态 ------------------------- void coze::resetInputState() { inputBox->setEnabled(true); sendButton->setEnabled(true); progressBar->setVisible(false); inputBox->setFocus(); } 其中loadConversationHistory(); appendMessage("AI", aiResponse);有问题修改下
06-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值