接入可配置概览服务并支持自适应缩放

This commit is contained in:
baiyanyun
2026-07-13 15:53:42 +08:00
parent 041964132a
commit c8a7bdc0f8
13 changed files with 108 additions and 8 deletions

View File

@@ -37,6 +37,7 @@ import SetupWizard from "./components/setup/SetupWizard";
import LoginPage from "./components/setup/LoginPage";
import SetupDependencies from "./components/setup/SetupDependencies";
import ClientPage from "./components/pages/ClientPage";
import OverviewPage from "./components/pages/OverviewPage";
import SettingsPage from "./components/pages/SettingsPage";
import DependenciesPage from "./components/pages/DependenciesPage";
import AboutPage from "./components/pages/AboutPage";
@@ -103,6 +104,7 @@ export function useI18nLang(): I18nContextValue {
// Tab 类型定义(对齐 Tauri 客户端)
type TabKey =
| "overview"
| "client"
| "sessions"
| "legacySessions"
@@ -336,7 +338,7 @@ function App() {
// ============================================
// 核心状态
// ============================================
const [activeTab, setActiveTab] = useState<TabKey>("client");
const [activeTab, setActiveTab] = useState<TabKey>("overview");
const [activeNavKey, setActiveNavKey] = useState<NavKey>("overview");
const [sessionsAutoOpen, setSessionsAutoOpen] = useState(false);
const [aiAgentLaunchContext, setAiAgentLaunchContext] =
@@ -1039,7 +1041,7 @@ function App() {
await logout();
await handleAuthChange();
setIsLoggedIn(false);
setActiveTab("client");
setActiveTab("overview");
setActiveNavKey("overview");
setServices([]);
setServicesLoading(false);
@@ -1057,7 +1059,7 @@ function App() {
setActiveNavKey(key);
if (key === "overview") {
setActiveTab("client");
setActiveTab("overview");
return;
}
@@ -1109,7 +1111,7 @@ function App() {
return;
}
setActiveTab("client");
setActiveTab("overview");
}, []);
const handleLegacySelect = useCallback((key: LegacyTabKey) => {
@@ -1358,6 +1360,7 @@ function App() {
<div
className={
webviewActions ||
activeTab === "overview" ||
activeTab === "document" ||
activeTab === "dataFetch"
? "app-content app-content-fullwidth"
@@ -1373,6 +1376,7 @@ function App() {
background: "var(--color-bg-layout)",
}}
>
{activeTab === "overview" && <OverviewPage />}
{activeTab === "client" && (
<ClientPage
onNavigate={(tab) => {

View File

@@ -6,13 +6,16 @@ import styles from "../../styles/components/ConfiguredServicePage.module.css";
interface ConfiguredServicePageProps {
title: string;
loadServiceUrl: () => Promise<string>;
fitContentWidth?: number;
}
function ConfiguredServicePage({
title,
loadServiceUrl,
fitContentWidth,
}: ConfiguredServicePageProps) {
const webviewRef = useRef<HTMLElement | null>(null);
const webviewReadyRef = useRef(false);
const [serviceUrl, setServiceUrl] = useState<string | null>(null);
const [loadingConfig, setLoadingConfig] = useState(true);
const [loadingPage, setLoadingPage] = useState(false);
@@ -37,14 +40,36 @@ function ConfiguredServicePage({
void loadService();
}, [loadService]);
const applyPageScale = useCallback(() => {
if (!fitContentWidth || !webviewReadyRef.current) return;
const element = webviewRef.current as any;
const availableWidth = element?.clientWidth;
if (!availableWidth || typeof element?.setZoomFactor !== "function") {
return;
}
const zoomFactor = Math.max(
0.35,
Math.min(1, availableWidth / fitContentWidth),
);
element.setZoomFactor(Number(zoomFactor.toFixed(3)));
}, [fitContentWidth]);
useEffect(() => {
const element = webviewRef.current as any;
if (!element || !serviceUrl) return;
webviewReadyRef.current = false;
const handleStart = () => {
setLoadingPage(true);
setError(null);
};
const handleReady = () => {
webviewReadyRef.current = true;
applyPageScale();
};
const handleStop = () => setLoadingPage(false);
const handleFailure = (event: any) => {
if (event.errorCode !== -3) {
@@ -56,14 +81,24 @@ function ConfiguredServicePage({
};
element.addEventListener("did-start-loading", handleStart);
element.addEventListener("dom-ready", handleReady);
element.addEventListener("did-stop-loading", handleStop);
element.addEventListener("did-fail-load", handleFailure);
const resizeObserver = fitContentWidth
? new ResizeObserver(applyPageScale)
: null;
resizeObserver?.observe(element);
return () => {
resizeObserver?.disconnect();
webviewReadyRef.current = false;
element.removeEventListener("did-start-loading", handleStart);
element.removeEventListener("dom-ready", handleReady);
element.removeEventListener("did-stop-loading", handleStop);
element.removeEventListener("did-fail-load", handleFailure);
};
}, [serviceUrl, title]);
}, [applyPageScale, fitContentWidth, serviceUrl, title]);
const handleReload = useCallback(() => {
const element = webviewRef.current as any;

View File

@@ -0,0 +1,15 @@
import React from "react";
import { fetchOverviewServiceUrl } from "../../services/core/servicePages";
import ConfiguredServicePage from "./ConfiguredServicePage";
function OverviewPage() {
return (
<ConfiguredServicePage
title="概览"
loadServiceUrl={fetchOverviewServiceUrl}
fitContentWidth={1920}
/>
);
}
export default OverviewPage;

View File

@@ -7,12 +7,14 @@ import { getDomainTokenKey } from "@shared/utils/domain";
import { normalizeServerHost } from "./auth";
const SUCCESS_CODE = "0000";
const OVERVIEW_FALLBACK_URL = "http://127.0.0.1:5173/_app/digital";
const INTELLIGENT_DATA_FALLBACK_URL = "http://192.168.2.106:3000/test-console";
interface TenantConfigResponse {
code: string;
message?: string;
data?: {
overviewServiceUrl?: string;
intelligentDataServiceUrl?: string;
documentEditorServiceUrl?: string;
};
@@ -77,6 +79,14 @@ async function fetchTenantConfig(): Promise<TenantConfigResponse["data"]> {
return result.data;
}
export async function fetchOverviewServiceUrl(): Promise<string> {
const config = await fetchTenantConfig();
return normalizeServiceUrl(
config?.overviewServiceUrl || OVERVIEW_FALLBACK_URL,
"概览",
);
}
export async function fetchIntelligentDataServiceUrl(): Promise<string> {
const config = await fetchTenantConfig();
return normalizeServiceUrl(