From 1c8ec37d2b050e04ebdefec779dabe8f60edb8cf Mon Sep 17 00:00:00 2001 From: nikelaluo <2135665716@qq.com> Date: Mon, 20 Jul 2026 06:43:46 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=8C=89=E7=AD=96?= =?UTF-8?q?=E7=95=A5=E7=94=9F=E6=88=90=20Git=20=E6=A0=87=E7=AD=BE=E6=B8=85?= =?UTF-8?q?=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Common/PolicyHelper.cpp | 9 ++-- Common/PolicyHelper.h | 7 +-- Launcher/UpdateLogic.cpp | 59 ++++++++++++++++++++++--- Launcher/UpdateLogic.h | 1 + Launcher/main.cpp | 26 ++++++++--- config/server_config.json | 2 +- i18n/update-client_zh_CN.qm | Bin 21754 -> 22454 bytes i18n/update-client_zh_CN.ts | 86 ++++++++++++++++++++++++++---------- 8 files changed, 147 insertions(+), 43 deletions(-) diff --git a/Common/PolicyHelper.cpp b/Common/PolicyHelper.cpp index 5e3569b..16c9144 100644 --- a/Common/PolicyHelper.cpp +++ b/Common/PolicyHelper.cpp @@ -123,10 +123,11 @@ bool PolicyHelper::isVersionAllowed(const QString& version) const { return true; } bool PolicyHelper::allowRun() const { return isValid() && m_policy.value("allow_run").toBool(); } -bool PolicyHelper::forceUpdate() const { return isValid() && m_policy.value("force_update").toBool(); } -bool PolicyHelper::allowRollback() const { return isValid() && m_policy.value("allow_rollback").toBool(); } -bool PolicyHelper::isOfflineAllowed() const { return isValid() && m_policy.value("offline_allowed").toBool(); } -bool PolicyHelper::isExpired() const { +bool PolicyHelper::forceUpdate() const { return isValid() && m_policy.value("force_update").toBool(); } +bool PolicyHelper::allowRollback() const { return isValid() && m_policy.value("allow_rollback").toBool(); } +bool PolicyHelper::isOfflineAllowed() const { return isValid() && m_policy.value("offline_allowed").toBool(); } +bool PolicyHelper::gitTagsEnabled() const { return isValid() && m_policy.value("git_tags_enabled").toBool(); } +bool PolicyHelper::isExpired() const { if (!isValid()) return true; const QDateTime expiry = QDateTime::fromString(m_policy.value("valid_until").toString(), Qt::ISODate); return !expiry.isValid() || QDateTime::currentDateTimeUtc() > expiry; diff --git a/Common/PolicyHelper.h b/Common/PolicyHelper.h index f65ff78..9cd7424 100644 --- a/Common/PolicyHelper.h +++ b/Common/PolicyHelper.h @@ -15,9 +15,10 @@ public: bool isVersionAllowed(const QString& currentVersion) const; bool allowRun() const; bool forceUpdate() const; - bool allowRollback() const; - bool isOfflineAllowed() const; - bool isExpired() const; + bool allowRollback() const; + bool isOfflineAllowed() const; + bool gitTagsEnabled() const; + bool isExpired() const; qint64 policySeq() const; QString message() const; diff --git a/Launcher/UpdateLogic.cpp b/Launcher/UpdateLogic.cpp index 61c553d..56b1807 100644 --- a/Launcher/UpdateLogic.cpp +++ b/Launcher/UpdateLogic.cpp @@ -101,8 +101,8 @@ void UpdateLogic::getDownloadUrl(const QString& appId, const QString& channel, c }); } -bool UpdateLogic::cacheManifest(const QString& appId, const QString& channel, const QString& version, - int versionId, const QString& cacheDir) +bool UpdateLogic::cacheManifest(const QString& appId, const QString& channel, const QString& version, + int versionId, const QString& cacheDir) { m_error.clear(); if (appId.isEmpty() || channel.isEmpty() || version.isEmpty() || versionId <= 0) { @@ -157,11 +157,56 @@ bool UpdateLogic::cacheManifest(const QString& appId, const QString& channel, co return false; } qDebug() << "Current version manifest cached to" << file.fileName(); - return true; -} - -void UpdateLogic::reportUpdateResult(const QString& deviceId, const QString& fromVer, const QString& toVer, bool success) -{ + return true; +} + +bool UpdateLogic::refreshGitTagsFile(const QString& outputPath) +{ + m_error.clear(); + if (m_serverAddr.isEmpty()) { + m_error = QCoreApplication::translate("UpdateLogic", "Server address is empty."); + return false; + } + + QJsonObject response; + int statusCode = 0; + QJsonObject body; + body["app_id"] = m_appId; + body["channel"] = m_channel; + m_http.postRequest(m_serverAddr + "/api/v1/git/tags", body, + [&](int code, const QJsonObject& resp) { + statusCode = code; + response = resp; + }); + + if (statusCode != 200) { + const QJsonValue detail = response.value("detail"); + const QString message = detail.isObject() + ? detail.toObject().value("msg").toString() + : detail.toString(); + m_error = message.isEmpty() + ? QCoreApplication::translate("UpdateLogic", "Git tags request failed (HTTP %1).").arg(statusCode) + : message; + return false; + } + + const QString tagsText = response.value("tags_text").toString(); + if (tagsText.isEmpty()) { + m_error = QCoreApplication::translate("UpdateLogic", "Git tags response is empty."); + return false; + } + + QString writeError; + if (!ConfigHelper::writeFileWithElevationIfNeeded(outputPath, tagsText.toUtf8(), &writeError)) { + m_error = QCoreApplication::translate("UpdateLogic", "Cannot write Git tags file: %1").arg(writeError); + return false; + } + qDebug() << "Git tags file refreshed:" << outputPath; + return true; +} + +void UpdateLogic::reportUpdateResult(const QString& deviceId, const QString& fromVer, const QString& toVer, bool success) +{ QString url = m_serverAddr + "/api/v1/update/report"; QJsonObject body; body["app_id"] = m_appId; diff --git a/Launcher/UpdateLogic.h b/Launcher/UpdateLogic.h index 2b35e4f..028c4fd 100644 --- a/Launcher/UpdateLogic.h +++ b/Launcher/UpdateLogic.h @@ -15,6 +15,7 @@ public: void reportUpdateResult(const QString& deviceId, const QString& fromVer, const QString& toVer, bool success); bool cacheManifest(const QString& appId, const QString& channel, const QString& version, int versionId, const QString& cacheDir); + bool refreshGitTagsFile(const QString& outputPath); bool getNeedUpdate() const { return m_needUpdate; } QString getLatestVersion() const { return m_latestVer; } diff --git a/Launcher/main.cpp b/Launcher/main.cpp index c9785a9..44e9af1 100644 --- a/Launcher/main.cpp +++ b/Launcher/main.cpp @@ -251,15 +251,31 @@ int main(int argc, char* argv[]) QCoreApplication::translate("Launcher", "A version policy sequence rollback was detected. Startup has been blocked.")); return -1; } - if (state.isSystemTimeRewound()) - { - progress.close(); + if (state.isSystemTimeRewound()) + { + progress.close(); QMessageBox::critical(nullptr, QCoreApplication::translate("Launcher", "Security Check Failed"), QCoreApplication::translate("Launcher", "A possible system time rollback was detected. Startup has been blocked.")); return -1; - } - + } + + if (networkOk && policy.gitTagsEnabled()) + { + progress.setLabelText(QCoreApplication::translate("Launcher", "Generating Git tag list...")); + QApplication::processEvents(); + const QString tagsPath = QDir(appDir).filePath("tags.txt"); + if (!logic.refreshGitTagsFile(tagsPath)) + { + progress.close(); + QMessageBox::warning(nullptr, + QCoreApplication::translate("Launcher", "Git Tag List Failed"), + QCoreApplication::translate("Launcher", "Cannot generate tags.txt, but startup will continue:\n%1").arg(logic.errorString())); + progress.show(); + QApplication::processEvents(); + } + } + if (networkOk && needUpdate) { progress.close(); diff --git a/config/server_config.json b/config/server_config.json index dba1221..099e80f 100644 --- a/config/server_config.json +++ b/config/server_config.json @@ -1,3 +1,3 @@ { - "api_base_url": "http://192.168.1.158:8000" + "api_base_url": "http://192.168.229.128:8000" } diff --git a/i18n/update-client_zh_CN.qm b/i18n/update-client_zh_CN.qm index 421f2878060a7fbca0278e30eefa610927163d93..624bb3760226277b9638d19d481189413fb27b9d 100644 GIT binary patch delta 2132 zcmZuyeNN}-+hgAP&8<_1o*PPYkV*jl^EdRmp^q!cIW!ByBVM-PY7_T-N@_sxBN zU(fTtxpROy@)6U#*efNXqE$pufh5Tt#sj{dVu@tuDaH6cQFIZlO9~_k(bJQAnux;V z=$VlzqWEWN=c#U@pIo8Vs6nE@&!{UPn5gg|o#hV`+bZ#+ceC#=s10T1V~t$$oXw01w+`8xJvA7BUWBB`K6_Iybs zQOZU3%eHnHQLtBDm?4Vsu#=}t%uxO{d)L3Ax3G7o7$QzD;eLmLrMo4C?tbh?OT2av z%N9vm4qk%89!Y-<-p^VfIe7)dD?gB&{S$->8Imvdazutbz9A;m8&%86yFB0x=hQ+E zk+hSGx+K7dk&8>n22BH(^TsG>^0+kzB8gJ-xh*vrM0qc99YOG$uH-u7@%v*Q?wx5J zQI3K8kdHw}Pu*M78@XefzXHw;?o4I_{7blz?2SZ^HgM-&8$@R*gU`H%K!RKN;uEhE z$$R;dix`o#U-D1qV$Ch)TkI#HKb?Og;v)!|qO@EeXw!P$;taCZeBhRBYIU*Arh=Jf)lg z{-ol)6%HbPRMGcPAkp$2ij%t{V0c*ZX+-9FW^dI7oLRGqjpiUU!un(AAM0SI|T zb!SmGfQHnIYdR2zpnmiKp0myBmja+WZ9u&zH5ezUO1-Z(87HS$-4)c1JEm8CTA>_KCS>28+@0Ji&mx0SnDx?gc!E0xP z-0OpA@T^eq?|vNF7Qwh76-j+@Z(Uh0IM1)ZU35^`{w#zkf`py@6GW2JLi4(AG%i)> z-0p2a)I-7tPe57Wa^cu{9j?|fVYGad=#its<-s=GhLghBne_n56~2>1BI29c^cajj z)27W&0H9((TV!d%?K`f0fe7FAeKGwWv?!GcDx3 zMQ;{ak;6O$>np}va6aF6j7BMc@Y&L-?UguBp2UMZ+ zsmy0Lwi@;I_49Be=HWW4wmO_v(dHDb&sDkV*8ezSK&7U*qyF2{q|&VKVJ&>zT3utU W7RxM_YOB*Z2lNA+UQgT$3I7N5%uR;? delta 1430 zcmX9;eN@eN9DaVk`}^JZ`@40QtmLK?nYu+cFQFGIrMj%+Wway1**L6o43W{@i`tka zZaKz|(A}n)NZ1)GLz#AtrW3-5IjTi#Olt@0+T*zYe9rIt@;uMy^E~%^;;`_vQYabh zlrI3UCjx_eph|7Vi(lY*5zw?E+HnvFwjndh8}K=SdAo`MKN$;JdVygb*nGYU2wRBK zz$U=^D%@T^K&A~B<>Nr|Zd}W90|SF`Q*i*}R-#kq2c$hhmwyjnxsI-bxo~1=4SN3G z1B||gXS?PDUK`=5BEYMSf-u$tL>~|=HXHETS|RT0LIVCSBz;K${ZV0tS1B-jv@mDD zVqjXAu<0y?S{4Xf9uO~Lzfe4b_v2HAGkwp2SDeDHfyKa-XTtT+eLzTrXxLEY1P09( zjoY~}WRB?9#z~AW7l%9_0Hm%Kqfh1nHg7Sjgo0v@h(&)Ea6E@ZmxF|38pP65LF_0* ztk}l&V3&BdpOdjfimkJ(z^J+6ow7Z^h(htgt~;AmG0GQVu%}`9R%ytCYa)8gm{eU^=c@ z(^){_DVp~m)0xyDO>w!E_xv+$_iPFyO*h44P+S+e=2pp+>Si$e$MXtjt-)Vjwx&*nHx^L*R-{$cMjqXjohxiY5 z-^Szua+|Jp93wnZ*41wr#6~l9R~Fd;#{u2lGM*2s)b-|*-`?OdOIGKEqk3O6uX`){ zkik`)XM=vsCe{I`^!fY9I`ln#$%w@ac%Q!1bBqD#*FSmO#308TmMrGIs6PyOQymPr z+wgTF12L?`P+h|BNiZC1<9>L6;q*F%fm&fW_q2_{k2mzz1`}UpoK#uG0K{K1e(Xhk z_Bi7%yAOf8jeFOQ;{2M7ZVLtYl^9Q)iDQ7@GS>E7CP9v|;nQ4TqQm%a0tv>ZnMD68 zAn`Mk*EI?p7ikK8gEe`cDK@d40q8ZQ|Hkj6E2gabyzfXixf=^8e5$E_sV9Sj+F= z{aoR?Ef2IUG0&FhUd9mfGS4dhU+m_c-Rv&z9rONZAKLVVx#b6nN@-XMOjl|`)E1wb Tll~XPnjmYfp(cLhn(+StY3-1q diff --git a/i18n/update-client_zh_CN.ts b/i18n/update-client_zh_CN.ts index be6421f..2a07fae 100644 --- a/i18n/update-client_zh_CN.ts +++ b/i18n/update-client_zh_CN.ts @@ -280,7 +280,7 @@ Please enter a new License for %2: - + Offline Update 离线更新 @@ -343,110 +343,150 @@ Please enter a new License for %2: 检测到系统时间可能被回拨,已阻止启动。 - + + Generating Git tag list... + 正在生成 Git 标签清单... + + + + Git Tag List Failed + Git 标签清单生成失败 + + + + Cannot generate tags.txt, but startup will continue: +%1 + 无法生成 tags.txt,但启动会继续: +%1 + + + Version Rollback 版本回退 - + Update Required 必须更新 - + New Version Available 发现新版本 - + The administrator provided version %1 as the rollback target. Downgrade now? 管理员提供了版本 %1 作为回退目标,是否现在降级? - + Version %1 is available. Update now? 发现新版本 %1,是否现在更新? - + Target version: %1 目标版本:%1 - - + + Startup Failed 启动失败 - - + + Cannot start the main application: %1 无法启动主程序:%1 - + Updater Startup Failed 更新器启动失败 - + Cannot start the updater: %1 无法启动更新器:%1 - + Caching signed version manifest... 正在缓存签名版本清单... - + Manifest Cache Failed 清单缓存失败 - + Cannot cache the signed manifest for the current version: %1 无法缓存当前版本的签名清单:%1 - + Server Unavailable 服务器不可用 - + Cannot connect to the update server. Import an offline update package? 当前无法连接更新服务器。是否导入离线更新包? - + No offline update package was selected, or the updater could not be started. 未选择离线更新包或无法启动更新器。 - + Network Unavailable 网络不可用 - + Cannot connect to the update server, and the current policy does not allow offline startup. 无法连接更新服务器,且当前策略不允许离线启动。 - + The application is up to date. Starting... 当前已是最新版本,正在启动... - + Offline mode is active. Starting... 当前处于离线模式,正在启动... + + UpdateLogic + + + Server address is empty. + 服务端地址为空。 + + + + Git tags request failed (HTTP %1). + Git 标签请求失败(HTTP %1)。 + + + + Git tags response is empty. + Git 标签响应为空。 + + + + Cannot write Git tags file: %1 + 无法写入 Git 标签文件:%1 + + Updater