import { useState } from "react"; import styles from "./AppIdentity.module.css"; // AppIdentity 是后台中 App 的唯一展示形式:业务页只传目录数据,避免各个下拉、表格和弹窗分别维护 Logo 规则。 export function AppIdentity({ app, appCode, appName, className = "", logoUrl, showLogoFallback = true, size = "medium" }) { // 主后台使用 camelCase,Social BI 的服务端聚合契约使用 snake_case;组件在展示边界统一兼容,业务视图不复制字段转换。 const resolvedCode = String(app?.appCode || app?.app_code || appCode || "").trim(); const resolvedName = String(app?.appName || app?.app_name || appName || resolvedCode || "-").trim(); const resolvedLogoUrl = String(app?.logoUrl || app?.logo_url || logoUrl || "").trim(); return ( {resolvedName} ); } function AppLogo({ appCode, appName, logoUrl, showFallback }) { const [failedLogoUrl, setFailedLogoUrl] = useState(""); const canRenderImage = Boolean(logoUrl) && failedLogoUrl !== logoUrl; if (canRenderImage) { return ( setFailedLogoUrl(logoUrl)} /> ); } if (!showFallback) { // 外管品牌只能展示 apps.logo_url 的真实图片;缺失或加载失败时不伪造一个看似品牌 Logo 的首字母图标。 return null; } // 网络失败或历史数据暂无 Logo 时保留稳定占位,不让选择项高度和表格对齐抖动。 const initial = String(appName || appCode || "?") .trim() .slice(0, 1) .toUpperCase() || "?"; return ( ); }