Skip to content

Commit f2e43e3

Browse files
客户端和服务器通信检查版本基础功能实现,缺少客户端获取version及os-arch功能
1 parent db8144f commit f2e43e3

6 files changed

Lines changed: 352 additions & 210 deletions

File tree

src/BarcodeWidget.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "version_info/version.h"
88
#include <QCheckBox>
99
#include <QComboBox>
10+
#include <QDesktopServices>
1011
#include <QFileDialog>
1112
#include <QFont>
1213
#include <QFutureWatcher>
@@ -361,6 +362,8 @@ BarcodeWidget::BarcodeWidget(QWidget *parent)
361362
if (!styleSheet.isEmpty()) {
362363
this->setStyleSheet(styleSheet);
363364
}
365+
// 进行版本检查
366+
QTimer::singleShot(0, this, &BarcodeWidget::checkUpdateOnStartup);
364367
}
365368

366369
void BarcodeWidget::updateButtonStates() const {
@@ -1119,6 +1122,46 @@ ZXing::BarcodeFormat BarcodeWidget::stringToBarcodeFormat(const QString &formatS
11191122
return map.value(key, ZXing::BarcodeFormat::None); // 未匹配时返回None
11201123
}
11211124

1125+
void BarcodeWidget::checkUpdateOnStartup() {
1126+
if (!m_updateChecker) {
1127+
m_updateChecker = new UpdateChecker(this);
1128+
}
1129+
// 后端接口地址
1130+
QUrl apiUrl("http://106.14.192.58:10000/update/check_version");
1131+
// 获取当前版本和架构
1132+
//QString version = version::git_tag.data();
1133+
//QString architecture = version::architecture.data();
1134+
QString test_version = "v1.0";
1135+
QString test_os = "windows-x64";
1136+
UpdateCheckRequest request(test_version, test_os);
1137+
// 连接信号
1138+
connect(m_updateChecker, &UpdateChecker::UpdateAvailable, this, [this](const UpdateInfo &info) {
1139+
QMessageBox box(this);
1140+
box.setWindowTitle("发现新版本");
1141+
box.setText(QString("最新版本:%1\n\n更新日志:\n%2\n\n更新链接:%3\n")
1142+
.arg(info.latest, info.changeLog, info.downloadUrl));
1143+
1144+
QPushButton *btnUpdate = box.addButton("立即更新", QMessageBox::AcceptRole);
1145+
QPushButton *btnLater = box.addButton("稍后再说", QMessageBox::RejectRole);
1146+
1147+
box.exec();
1148+
1149+
if (box.clickedButton() == btnUpdate) {
1150+
QDesktopServices::openUrl(QUrl(info.downloadUrl));
1151+
} else if (box.clickedButton() == btnLater) {
1152+
// 关闭弹窗即可;exec() 返回后 box 会析构
1153+
}
1154+
});
1155+
connect(m_updateChecker, &UpdateChecker::NoUpdate, this, []() { spdlog::info("No update!"); });
1156+
1157+
connect(m_updateChecker, &UpdateChecker::ErrorOccured, this, [](const QString &msg) {
1158+
spdlog::error("UpdateCheck Error, Error Message: {}", msg.toStdString());
1159+
});
1160+
1161+
// 发起检查
1162+
m_updateChecker->Check(apiUrl, request);
1163+
}
1164+
11221165
void BarcodeWidget::setupLanguageAction() {
11231166
LanguageManager &languageMgr = LanguageManager::instance();
11241167

src/BarcodeWidget.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <qfuturewatcher.h>
99

1010
#include "CameraWidget.h"
11+
#include "UpdateChecker.h"
1112
#include "convert.h"
1213
#include "mqtt/MQTTMessageWidget.h"
1314
#include "mqtt/mqtt_client.h"
@@ -122,6 +123,12 @@ private slots:
122123
*/
123124
static ZXing::BarcodeFormat stringToBarcodeFormat(const QString &formatStr);
124125

126+
/**
127+
* @brief 在程序启动时与服务器通信判断是否需要更新
128+
*
129+
*/
130+
void checkUpdateOnStartup();
131+
125132
private:
126133
/**
127134
* @brief 初始化语言切换的Action
@@ -173,4 +180,5 @@ private slots:
173180
std::unique_ptr<MqttSubscriber> subscriber_; /**< MQTT订阅者实例 */
174181
std::unique_ptr<MQTTMessageWidget> messageWidget; /**< MQTT消息展示窗口 */
175182
CameraWidget preview; /**< 摄像头预览窗口 */
183+
UpdateChecker *m_updateChecker = nullptr; /**< 版本检查实例 */
176184
};

src/UpdateChecker.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#include "UpdateChecker.h"
2+
#include <QJsonDocument>
3+
#include <QNetworkReply>
4+
#include <QNetworkRequest>
5+
#include <QTimer>
6+
7+
UpdateChecker::UpdateChecker(QObject *parent)
8+
: QObject(parent) {}
9+
10+
void UpdateChecker::Check(const QUrl &apiUrl, const UpdateCheckRequest &request) {
11+
// 1. 构造 request
12+
QNetworkRequest req(apiUrl);
13+
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
14+
QJsonDocument doc(request.toJson());
15+
QByteArray body = doc.toJson(QJsonDocument::Compact);
16+
17+
// 2. 发送网络请求,超时处理
18+
QNetworkReply *reply = m_nam.post(req, body);
19+
QTimer *timer = new QTimer(reply);
20+
timer->setSingleShot(true);
21+
timer->start(4000);
22+
QObject::connect(timer, &QTimer::timeout, reply, [reply]() { reply->abort(); });
23+
24+
// 3. 收到回包处理
25+
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
26+
const auto err = reply->error();
27+
const QByteArray body = reply->readAll();
28+
reply->deleteLater();
29+
// 3.1 出错处理
30+
if (err != QNetworkReply::NoError) {
31+
emit ErrorOccured(QString("网络错误: %1").arg(reply->errorString()));
32+
return;
33+
}
34+
// 3.2 读取回包
35+
QJsonParseError pe{};
36+
QJsonDocument doc = QJsonDocument::fromJson(body, &pe);
37+
if (pe.error != QJsonParseError::NoError || !doc.isObject()) {
38+
emit ErrorOccured(QString("返回不是合法 json"));
39+
return;
40+
}
41+
QJsonObject o = doc.object();
42+
UpdateInfo info;
43+
info.latest = o.value("version").toString();
44+
info.downloadUrl = o.value("update_url").toString();
45+
info.changeLog = o.value("update_log").toString();
46+
info.updateNeed = o.value("update_need").toBool();
47+
if (info.updateNeed) {
48+
emit UpdateAvailable(info);
49+
} else {
50+
emit NoUpdate();
51+
}
52+
});
53+
}

src/UpdateChecker.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#pragma once
2+
#include <QJsonObject>
3+
#include <QNetworkAccessManager>
4+
#include <QObject>
5+
6+
struct UpdateInfo {
7+
QString latest; /**< 最新版本号 */
8+
QString downloadUrl; /**< 下载路径 */
9+
QString changeLog; /**< 版本更新日志 */
10+
bool updateNeed; /**< 是否需要更新 */
11+
};
12+
13+
struct UpdateCheckRequest {
14+
QString version; /**< 客户端版本 */
15+
QString osArch; /**< 客户端架构 */
16+
UpdateCheckRequest(const QString _version, const QString _os)
17+
: version(_version), osArch(_os) {}
18+
// 序列化成 JSON
19+
QJsonObject toJson() const {
20+
QJsonObject o;
21+
o.insert("version", version);
22+
o.insert("os-arch", osArch);
23+
return o;
24+
}
25+
};
26+
class UpdateChecker : public QObject {
27+
Q_OBJECT
28+
public:
29+
explicit UpdateChecker(QObject *parent = nullptr);
30+
void Check(const QUrl &apiUrl, const UpdateCheckRequest &request);
31+
signals:
32+
void NoUpdate();
33+
void UpdateAvailable(const UpdateInfo &info);
34+
void ErrorOccured(const QString &msg);
35+
36+
private:
37+
QNetworkAccessManager m_nam;
38+
};

0 commit comments

Comments
 (0)