feat(platform): expose amap runtime health

This commit is contained in:
lingniu
2026-07-04 15:30:51 +08:00
parent 5bbd110743
commit 1f069178d6
6 changed files with 64 additions and 10 deletions

View File

@@ -334,6 +334,10 @@ export interface OpsHealth {
export interface RuntimeInfo {
requestTimeoutMs: number;
amapWebJsConfigured?: boolean;
amapSecurityProxyEnabled?: boolean;
amapSecurityCodeExposed?: boolean;
amapSecurityServiceHost?: string;
}
export interface Page<T> {

View File

@@ -2,7 +2,7 @@ import { Button, Card, Form, Select, Space, Table, Tabs, Tag, Toast, Typography
import { IconCopy } from '@douyinfe/semi-icons';
import { useEffect, useState } from 'react';
import { api } from '../api/client';
import type { VehicleRealtimeRow } from '../api/types';
import type { OpsHealth, VehicleRealtimeRow } from '../api/types';
import { DataEmpty } from '../components/DataEmpty';
import { PageHeader } from '../components/PageHeader';
import { SourceStatusTags } from '../components/SourceStatusTags';
@@ -190,8 +190,13 @@ export function Realtime({
const [loading, setLoading] = useState(true);
const [filters, setFilters] = useState<Record<string, string>>(initialFilters);
const [pagination, setPagination] = useState({ currentPage: 1, pageSize: 50, total: 0 });
const [opsHealth, setOpsHealth] = useState<OpsHealth | null>(null);
const amapConfig = getAMapConfig();
const amapConfigured = isAMapConfigured(amapConfig);
const runtime = opsHealth?.runtime;
const amapConfigured = runtime?.amapWebJsConfigured ?? isAMapConfigured(amapConfig);
const amapSecurityServiceHost = runtime?.amapSecurityServiceHost || amapConfig.securityServiceHost;
const amapSecurityProxyEnabled = runtime?.amapSecurityProxyEnabled ?? Boolean(amapSecurityServiceHost);
const amapSecurityCodeExposed = runtime?.amapSecurityCodeExposed ?? Boolean(amapConfig.securityJsCode && !amapSecurityServiceHost);
const load = (values: Record<string, string> = filters, page = pagination.currentPage, pageSize = pagination.pageSize) => {
setLoading(true);
@@ -212,6 +217,9 @@ export function Realtime({
useEffect(() => {
setFilters(initialFilters);
load(initialFilters, 1, pagination.pageSize);
api.opsHealth()
.then(setOpsHealth)
.catch(() => setOpsHealth(null));
}, [JSON.stringify(initialFilters)]);
const applyFilters = (nextFilters: Record<string, string>) => {
@@ -276,9 +284,15 @@ export function Realtime({
},
{
label: '安全代理',
value: amapConfig.securityServiceHost || '未启用',
color: amapConfig.securityServiceHost ? 'green' as const : 'grey' as const,
detail: amapConfig.securityServiceHost ? '安全密钥由服务端追加,不下发到浏览器。' : '未配置代理时会退回前端安全码模式。'
value: amapSecurityServiceHost || '未启用',
color: amapSecurityProxyEnabled ? 'green' as const : 'grey' as const,
detail: amapSecurityProxyEnabled ? '安全密钥由服务端追加,不下发到浏览器。' : '未配置代理时会退回前端安全码模式。'
},
{
label: '安全码',
value: amapSecurityCodeExposed ? '已暴露' : '未暴露',
color: amapSecurityCodeExposed ? 'red' as const : 'green' as const,
detail: amapSecurityCodeExposed ? '当前安全码会下发到浏览器,只建议调试使用。' : '生产安全码保持在服务端环境变量中。'
},
{
label: '定位覆盖',

View File

@@ -7457,7 +7457,7 @@ test('shows production AMap integration status on realtime page', async () => {
window.history.replaceState(null, '', '/#/realtime');
Object.defineProperty(window, '__LINGNIU_APP_CONFIG__', {
configurable: true,
value: { amapWebJsKey: 'amap-key', amapSecurityServiceHost: '/_AMapService' }
value: {}
});
vi.spyOn(globalThis, 'fetch').mockImplementation(async (input) => {
const path = String(input);
@@ -7465,7 +7465,20 @@ test('shows production AMap integration status on realtime page', async () => {
return {
ok: true,
json: async () => ({
data: { linkHealth: [], kafkaLag: 0, redisOnlineKeys: 0, tdengineWritable: true, mysqlWritable: true, runtime: { requestTimeoutMs: 5000 } },
data: {
linkHealth: [],
kafkaLag: 0,
redisOnlineKeys: 0,
tdengineWritable: true,
mysqlWritable: true,
runtime: {
requestTimeoutMs: 5000,
amapWebJsConfigured: true,
amapSecurityProxyEnabled: true,
amapSecurityCodeExposed: false,
amapSecurityServiceHost: '/_AMapService'
}
},
traceId: 'trace-test',
timestamp: 1783094400000
})