fix(version): 界面版本号改为动态读取,统一版本为 v1.0.2

界面侧栏与页脚硬编码 v1.0.0,发版后始终显示陈旧版本。

- 新增 useAppVersion hook:从后端 /version 读取并做模块级缓存
- Sidebar / MainLayout 改用该 hook
- /agent/arch 的 version 字段原先硬编码 "1.0.0",改由 main 注入 router.AppVersion
- Dockerfile 增加 AGENT_VERSION 构建参数,与镜像 VERSION 解耦,
  避免纯前端改动也触发全量 Agent 重推

统一版本:镜像 lghost/aiops:v1.0.2,内置 Agent v1.0.2。

// Logan.Li
This commit is contained in:
Logan.Li committed 2026-09-14 08:46:40 +00:00
1 parent 9360ebefd8
commit 7a96381dc7
7 files changed
+79 -6

No files matched your search

@@ -9,6 +9,7 @@ import { authApi } from '@/api';
import type { JsonData } from '@/types/common';
import { useTranslation } from 'react-i18next';
import { SessionWatermark } from '@/components/common/SessionWatermark';
import { useAppVersion } from '@/hooks/use-app-version';
import { shouldProtectPage } from '@/components/common/sensitivePageWatermark';
/**
@@ -16,6 +17,8 @@ import { shouldProtectPage } from '@/components/common/sensitivePageWatermark';
* 侧栏 + 顶栏 + 面包屑 + 内容区,间距由 --layout-* 令牌驱动 // Logan.Li
*/
export function MainLayout() {
// 页脚版本号同样取自后端 /version。 // Logan.Li
const appVersion = useAppVersion();
const { t } = useTranslation();
const { sidebarCollapsed } = useThemeStore();
const token = useUserStore((s) => s.token);
@@ -97,7 +100,7 @@ export function MainLayout() {
<footer className="dg-app-footer">
<div className="flex items-center justify-between text-xs dg-text-muted">
<span>{t('login.title')}</span>
<span>v1.0.0</span>
<span>{appVersion || 'v1.0.0'}</span>
</div>
</footer>
</div>
+4 -1
View File
@@ -44,6 +44,7 @@ import {
import { Button } from '@/components/ui/button';
import { ScrollArea } from '@/components/ui/scroll-area';
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
import { useAppVersion } from '@/hooks/use-app-version';
interface MenuItem {
id: string;
@@ -363,6 +364,8 @@ interface SidebarProps {
}
export function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) {
// 版本号从后端 /version 读取,避免发版后界面仍显示硬编码的旧版本。 // Logan.Li
const appVersion = useAppVersion();
const { t } = useTranslation();
const { sidebarCollapsed, toggleSidebar } = useThemeStore();
const { hasPermission } = usePermission();
@@ -433,7 +436,7 @@ export function Sidebar({ mobileOpen, onMobileClose }: SidebarProps) {
{!isCollapsed && (
<div className="px-3 py-2 border-t border-[var(--dg-border)] flex-shrink-0">
<div className="text-[10px] text-[var(--dg-text-muted)] text-center">
AIOps v1.0.0
AIOps {appVersion || 'v1.0.0'}
</div>
</div>
)}
+58
View File
@@ -0,0 +1,58 @@
import { useEffect, useState } from 'react';
/**
* 应用版本信息。
*
* 版本号此前在后端 /version 已提供(含 build_time / git_commit),
* 但侧边栏与页脚硬编码了 v1.0.0,导致发版后界面显示陈旧。
* 这里统一从 /version 读取并做模块级缓存,避免多处重复请求。 // Logan.Li
*/
export interface AppVersion {
version: string;
build_time?: string;
git_commit?: string;
mode?: string;
}
// 模块级缓存:整个会话只请求一次。
let cached: AppVersion | null = null;
let inflight: Promise<AppVersion | null> | null = null;
function fetchVersion(): Promise<AppVersion | null> {
if (cached) return Promise.resolve(cached);
if (inflight) return inflight;
// 注意:/version 挂在根路径,不带 /api/v1 前缀,故不能用统一 request 封装。
inflight = fetch('/version')
.then((res) => (res.ok ? res.json() : null))
.then((data) => {
if (data && typeof data.version === 'string') {
cached = data as AppVersion;
return cached;
}
return null;
})
.catch(() => null)
.finally(() => {
inflight = null;
});
return inflight;
}
/** 读取后端版本号;失败时返回空串,调用方负责兜底显示。 */
export function useAppVersion(): string {
const [version, setVersion] = useState<string>(cached?.version ?? '');
useEffect(() => {
let alive = true;
fetchVersion().then((v) => {
if (alive && v?.version) setVersion(v.version);
});
return () => {
alive = false;
};
}, []);
return version;
}