接入可配置概览服务并支持自适应缩放
This commit is contained in:
@@ -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) => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user