From 83415c323c8727843ce63c5228bb41504633957b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=E2=82=82=E2=82=82H=E2=82=82=E2=82=85NO=E2=82=86?= Date: Thu, 25 Jun 2026 20:27:08 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E5=B8=82=E5=9C=BA=E6=97=A7=E7=89=88=E6=9C=AC=E8=AF=AF=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/shared/ExtensionCard.vue | 14 ++++ .../locales/en-US/features/extension.json | 1 + .../locales/ru-RU/features/extension.json | 1 + .../locales/zh-CN/features/extension.json | 1 + .../src/views/extension/useExtensionPage.js | 78 ++++++++++++++++++- 5 files changed, 93 insertions(+), 2 deletions(-) diff --git a/dashboard/src/components/shared/ExtensionCard.vue b/dashboard/src/components/shared/ExtensionCard.vue index 8335c47a53..afcc07e50f 100644 --- a/dashboard/src/components/shared/ExtensionCard.vue +++ b/dashboard/src/components/shared/ExtensionCard.vue @@ -268,6 +268,20 @@ const openWebui = () => { {{ extension.online_version }} + + + {{ + tm("card.status.localVersionAhead", { + version: extension.online_version, + }) + }} + { if (matchedPlugin) { extension.online_version = matchedPlugin.version; + const onlineVersion = String(matchedPlugin.version || "").trim(); + const versionComparison = comparePluginVersions( + extension.version, + onlineVersion, + ); + + extension.version_source_ahead = + typeof versionComparison === "number" && versionComparison > 0; extension.has_update = - extension.version !== matchedPlugin.version && - matchedPlugin.version !== tm("status.unknown"); + typeof versionComparison === "number" && versionComparison < 0; } else { extension.online_version = ""; extension.has_update = false; + extension.version_source_ahead = false; } }); }; @@ -1284,6 +1292,72 @@ export const useExtensionPage = () => { const normalizeAstrBotVersionSpec = (value) => String(value || "").trim(); + const parsePluginVersion = (value) => { + const version = String(value || "").trim().replace(/^v/i, ""); + const match = version.match( + /^([0-9]+(?:\.[0-9]+)*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+(.+))?$/, + ); + if (!match) return null; + + return { + parts: match[1].split(".").map((part) => Number.parseInt(part, 10)), + prerelease: match[2] + ? match[2].split(".").map((part) => { + if (/^\d+$/.test(part)) { + return Number.parseInt(part, 10); + } + return part; + }) + : null, + }; + }; + + const comparePluginVersions = (left, right) => { + const leftVersion = parsePluginVersion(left); + const rightVersion = parsePluginVersion(right); + if (!leftVersion || !rightVersion) return null; + + const length = Math.max(leftVersion.parts.length, rightVersion.parts.length); + for (let i = 0; i < length; i += 1) { + const leftPart = leftVersion.parts[i] || 0; + const rightPart = rightVersion.parts[i] || 0; + if (leftPart > rightPart) return 1; + if (leftPart < rightPart) return -1; + } + + if (leftVersion.prerelease === null && rightVersion.prerelease !== null) { + return 1; + } + if (leftVersion.prerelease !== null && rightVersion.prerelease === null) { + return -1; + } + if (leftVersion.prerelease === null && rightVersion.prerelease === null) { + return 0; + } + + const prereleaseLength = Math.max( + leftVersion.prerelease.length, + rightVersion.prerelease.length, + ); + for (let i = 0; i < prereleaseLength; i += 1) { + const leftPart = leftVersion.prerelease[i]; + const rightPart = rightVersion.prerelease[i]; + + if (leftPart === undefined && rightPart !== undefined) return -1; + if (leftPart !== undefined && rightPart === undefined) return 1; + if (typeof leftPart === "number" && typeof rightPart === "string") { + return -1; + } + if (typeof leftPart === "string" && typeof rightPart === "number") { + return 1; + } + if (leftPart > rightPart) return 1; + if (leftPart < rightPart) return -1; + } + + return 0; + }; + const normalizeVersionParts = (value) => { const version = String(value || "") .trim() From 463cc32265a7924c96c176a2e1ae211d257147fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=E2=82=82=E2=82=82H=E2=82=82=E2=82=85NO=E2=82=86?= Date: Thu, 25 Jun 2026 20:39:39 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E5=A4=84=E7=90=86=E6=8F=92=E4=BB=B6?= =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E7=89=88=E6=9C=AC=E5=BC=82=E5=B8=B8=E6=97=B6?= =?UTF-8?q?=E7=9A=84=E6=9B=B4=E6=96=B0=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dashboard/src/views/extension/useExtensionPage.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dashboard/src/views/extension/useExtensionPage.js b/dashboard/src/views/extension/useExtensionPage.js index 4fde88d3ec..4c7da8e003 100644 --- a/dashboard/src/views/extension/useExtensionPage.js +++ b/dashboard/src/views/extension/useExtensionPage.js @@ -1315,7 +1315,8 @@ export const useExtensionPage = () => { const comparePluginVersions = (left, right) => { const leftVersion = parsePluginVersion(left); const rightVersion = parsePluginVersion(right); - if (!leftVersion || !rightVersion) return null; + if (!rightVersion) return null; + if (!leftVersion) return -1; const length = Math.max(leftVersion.parts.length, rightVersion.parts.length); for (let i = 0; i < length; i += 1) {