diff --git a/install.sh b/install.sh index 8b9c997..6e2e24d 100644 --- a/install.sh +++ b/install.sh @@ -29,6 +29,7 @@ cd "${SCRIPT_DIR}" echo "拉取最新代码..." git pull +COMMIT_HASH=$(git rev-parse --short HEAD) echo "编译前端..." cd "${SCRIPT_DIR}/${FRONTEND_DIR}" @@ -41,7 +42,7 @@ npm run build echo "编译 Go 程序..." cd "${SCRIPT_DIR}" -go build -o "${BINARY_NAME}" . +go build -ldflags "-X meshtastic_mqtt_server/internal/web.CommitVersion=${COMMIT_HASH}" -o "${BINARY_NAME}" . echo "检查系统用户..." if ! id -u "${SERVICE_USER}" >/dev/null 2>&1; then diff --git a/internal/web/web.go b/internal/web/web.go index ae67766..e830e21 100644 --- a/internal/web/web.go +++ b/internal/web/web.go @@ -84,6 +84,10 @@ func NewRouter(cfg configpkg.WebConfig, consoleLog bool, store *storepkg.Store, return r } +const BackendVersion = "1.0.0" + +var CommitVersion = "dev" + func registerAPIRoutes(r gin.IRouter, store *storepkg.Store, mapTileCacheDir string) { r.GET("/health", func(c *gin.Context) { status := gin.H{"status": "ok", "database": "ok"} @@ -96,6 +100,10 @@ func registerAPIRoutes(r gin.IRouter, store *storepkg.Store, mapTileCacheDir str c.JSON(http.StatusOK, status) }) + r.GET("/version", func(c *gin.Context) { + c.JSON(http.StatusOK, gin.H{"version": BackendVersion, "commit": CommitVersion}) + }) + registerNodeInfoRoutes(r, store, "/nodeinfo") registerNodeInfoRoutes(r, store, "/nodes") registerMapReportRoutes(r, store) diff --git a/meshmap_frontend/src/App.vue b/meshmap_frontend/src/App.vue index 5d2e574..339a12c 100644 --- a/meshmap_frontend/src/App.vue +++ b/meshmap_frontend/src/App.vue @@ -15,6 +15,7 @@ import AdminMapSource from './components/AdminMapSource.vue' import AdminMqttForward from './components/AdminMqttForward.vue' import AdminSignManagement from './components/AdminSignManagement.vue' import AdminUsers from './components/AdminUsers.vue' +import AppFooter from './components/AppFooter.vue' import ChatPanel from './components/ChatPanel.vue' import ConfirmDeleteModal from './components/ConfirmDeleteModal.vue' import HelpPage from './components/HelpPage.vue' @@ -838,6 +839,8 @@ onBeforeUnmount(() => { /> + + { return getJSON('/api/health') } +export function getBackendVersion(): Promise<{ version: string; commit: string }> { + return getJSON<{ version: string; commit: string }>('/api/version') +} + export function getHelpContent(): Promise { return getJSON('/api/help') } diff --git a/meshmap_frontend/src/components/AppFooter.vue b/meshmap_frontend/src/components/AppFooter.vue new file mode 100644 index 0000000..52ae803 --- /dev/null +++ b/meshmap_frontend/src/components/AppFooter.vue @@ -0,0 +1,29 @@ + + + diff --git a/meshmap_frontend/src/style.css b/meshmap_frontend/src/style.css index 6280c0f..37c67ae 100644 --- a/meshmap_frontend/src/style.css +++ b/meshmap_frontend/src/style.css @@ -75,6 +75,20 @@ a { padding: 16px; } +.app-footer { + display: flex; + justify-content: center; + align-items: center; + gap: 8px; + padding: 8px 0; + font-size: 12px; + color: var(--color-muted); +} + +.app-footer-sep { + opacity: 0.5; +} + .topbar { display: flex; align-items: center; diff --git a/meshmap_frontend/src/version.ts b/meshmap_frontend/src/version.ts new file mode 100644 index 0000000..d3b3679 --- /dev/null +++ b/meshmap_frontend/src/version.ts @@ -0,0 +1 @@ +export const FRONTEND_VERSION = '0.1.0'