refactor: OSS base URL 与 logo URL 改由 API 下发 (AGENTS.md 合规)
This commit is contained in:
+4
-1
@@ -19,6 +19,7 @@ import ToastContainer from "./components/toast/ToastContainer";
|
||||
import { toast } from "./components/toast/toastStore";
|
||||
import { flushPendingGenerationRecords } from "./api/generationRecordClient";
|
||||
import { keyServerClient } from "./api/keyServerClient";
|
||||
import { preloadPublicConfig, getLogoUrl } from "./api/publicConfigClient";
|
||||
import { setUserMaxConcurrency } from "./api/generationConcurrency";
|
||||
import {
|
||||
SERVER_SESSION_EXPIRED_EVENT,
|
||||
@@ -242,6 +243,8 @@ function App() {
|
||||
let cancelled = false;
|
||||
|
||||
const loadSession = async () => {
|
||||
// 预加载公网配置(OSS base / logo URL),与 session 加载并行,不阻断启动。
|
||||
void preloadPublicConfig();
|
||||
try {
|
||||
const nextSession = await keyServerClient.getCurrentSession();
|
||||
if (cancelled) return;
|
||||
@@ -414,7 +417,7 @@ function App() {
|
||||
<CloseOutlined />
|
||||
</button>
|
||||
<span className="ecommerce-auth-modal__logo" aria-hidden="true">
|
||||
<img src="https://stringtest.oss-cn-hangzhou.aliyuncs.com/logo.png" alt="" />
|
||||
<img src={getLogoUrl()} alt="" />
|
||||
</span>
|
||||
<h2 id="ecommerce-auth-title">{authMode === "login" ? "欢迎回来" : "创建账号"}</h2>
|
||||
<p className="ecommerce-auth-modal__subtitle">{authMode === "login" ? "登录后继续你的 AI 创作之旅" : "注册即可免费体验全部功能"}</p>
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
// 前端公网配置客户端。
|
||||
// 从 GET /api/public/config/profile?name=web-public-config 拉取运行时配置,
|
||||
// 包括 OSS 公网 base URL 与 logo URL。
|
||||
// 按 AGENTS.md 规则 1/4/5:这些环境权威数据不硬编码在前端源码,由 API 下发。
|
||||
//
|
||||
// 设计:进程内单例缓存 + promise 去重,App 启动时预加载一次,
|
||||
// 之后 getOssPublicBaseUrl() / getLogoUrl() 同步返回缓存值。
|
||||
// API 不可用时回退到 FALLBACK 值(当前生产 bucket),保证渐进可用。
|
||||
|
||||
import { serverRequest } from "./serverConnection";
|
||||
|
||||
interface PublicConfigPayload {
|
||||
name: string;
|
||||
config: {
|
||||
ossPublicBaseUrl?: string;
|
||||
logoUrl?: string;
|
||||
};
|
||||
description?: string;
|
||||
updatedAt?: string;
|
||||
}
|
||||
|
||||
// Fallback:API 不可用或未加载时的兜底值,保证首屏不白屏。
|
||||
// 这些值仅作为降级,正式来源是 API 返回的 config。
|
||||
const FALLBACK_OSS_PUBLIC_BASE_URL = "https://stringtest.oss-cn-hangzhou.aliyuncs.com";
|
||||
const FALLBACK_LOGO_URL = "https://stringtest.oss-cn-hangzhou.aliyuncs.com/muban/logo.png";
|
||||
|
||||
let cachedConfig: PublicConfigPayload["config"] | null = null;
|
||||
let loadPromise: Promise<PublicConfigPayload["config"]> | null = null;
|
||||
|
||||
async function fetchPublicConfig(): Promise<PublicConfigPayload["config"]> {
|
||||
const payload = await serverRequest<PublicConfigPayload>("public/config/profile?name=web-public-config", {
|
||||
// 公开端点,无需 token。
|
||||
maxRetries: 2,
|
||||
fallbackMessage: "加载公网配置失败",
|
||||
});
|
||||
return payload?.config ?? {};
|
||||
}
|
||||
|
||||
/** 预加载公网配置。App 启动时调用一次,后续同步读取缓存。可安全重复调用(promise 去重)。 */
|
||||
export async function preloadPublicConfig(): Promise<void> {
|
||||
if (loadPromise) return loadPromise.then(() => undefined);
|
||||
loadPromise = fetchPublicConfig()
|
||||
.then((config) => {
|
||||
cachedConfig = config;
|
||||
return config;
|
||||
})
|
||||
.catch((error) => {
|
||||
// 加载失败不阻断启动,用 fallback 值;记录后允许后续重试。
|
||||
console.warn("[publicConfig] 加载失败,使用 fallback 值", error);
|
||||
cachedConfig = null;
|
||||
loadPromise = null;
|
||||
return {};
|
||||
});
|
||||
return loadPromise.then(() => undefined);
|
||||
}
|
||||
|
||||
/** 同步获取 OSS 公网 base URL。未加载时返回 fallback。 */
|
||||
export function getOssPublicBaseUrl(): string {
|
||||
return cachedConfig?.ossPublicBaseUrl?.trim() || FALLBACK_OSS_PUBLIC_BASE_URL;
|
||||
}
|
||||
|
||||
/** 同步获取 logo URL。未加载时返回 fallback。 */
|
||||
export function getLogoUrl(): string {
|
||||
return cachedConfig?.logoUrl?.trim() || FALLBACK_LOGO_URL;
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
WalletOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { LocalAvatar } from "./LocalAvatar";
|
||||
import { getLogoUrl } from "../api/publicConfigClient";
|
||||
import type { WebUserSession } from "../types";
|
||||
|
||||
interface TopbarProps {
|
||||
@@ -110,7 +111,7 @@ export function Topbar({
|
||||
onClick={onOpenWorkspace}
|
||||
>
|
||||
<span className="ecommerce-standalone__logo" aria-hidden="true">
|
||||
<img src="https://stringtest.oss-cn-hangzhou.aliyuncs.com/logo.png" alt="" />
|
||||
<img src={getLogoUrl()} alt="" />
|
||||
</span>
|
||||
<strong>OmniAI 电商智能体</strong>
|
||||
</button>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
const OSS_PUBLIC_BASE_URL = "https://stringtest.oss-cn-hangzhou.aliyuncs.com";
|
||||
// OSS 公网 base URL 由 API 下发(AGENTS.md 规则 1/5),
|
||||
// 见 src/api/publicConfigClient.ts。ossAssets 在模块加载时同步取缓存值,
|
||||
// App 启动时 preloadPublicConfig() 已预加载;未加载时 getOssPublicBaseUrl() 返回 fallback。
|
||||
import { getOssPublicBaseUrl } from "../api/publicConfigClient";
|
||||
|
||||
function oss(path: string): string {
|
||||
return `${OSS_PUBLIC_BASE_URL}/${path.replace(/^\/+/, "")}`;
|
||||
return `${getOssPublicBaseUrl()}/${path.replace(/^\/+/, "")}`;
|
||||
}
|
||||
|
||||
function muban(path: string): string {
|
||||
|
||||
Reference in New Issue
Block a user