/**
|
* 载入 Document Server 的 api.js。
|
*
|
* 这个脚本挂的是全局 `window.DocsAPI`,同一页面只能载入一次,所以用单例 Promise 收口——
|
* 多个编辑器实例(或反复开关弹窗)并发调用时共用同一次加载。
|
*
|
* 地址来源(2026-09-23 改):
|
* 1. 运行时 `window._JNPF_ADMIN_PRO_APP_CONF_.VITE_GLOB_ONLYOFFICE_URL`(`_app.config.js`)。
|
* 部署时由 cx-web 容器启动脚本按服务器 `.env` 的 `ONLYOFFICE_DS_PUBLIC_URL` 写入——
|
* 同一份前端产物可用于任何环境,换地址只改服务器 `.env`,不用重新构建、也不用每台构建机各配一份。
|
* 2. 回落:构建期 `import.meta.env.VITE_GLOB_ONLYOFFICE_URL`(本地开发的 `.env.development`)。
|
*
|
* 直接读 window 对象,刻意不进 `useGlobSetting()`:那条链路是白名单式解构
|
* (packages/types/global.d.ts → use-app-config.ts → hooks/setting),加一个字段要改三个跨层共享包。
|
*/
|
const API_PATH = '/web-apps/apps/api/documents/api.js';
|
const RUNTIME_CONFIG_KEY = '_JNPF_ADMIN_PRO_APP_CONF_';
|
|
let loadingPromise: null | Promise<void> = null;
|
|
export function getDocumentServerUrl(): string {
|
const runtime = (window as any)[RUNTIME_CONFIG_KEY]?.VITE_GLOB_ONLYOFFICE_URL;
|
const url = (typeof runtime === 'string' && runtime) || import.meta.env.VITE_GLOB_ONLYOFFICE_URL || '';
|
return url.endsWith('/') ? url.slice(0, -1) : url;
|
}
|
|
export function loadDocsApi(): Promise<void> {
|
if ((window as any).DocsAPI?.DocEditor) return Promise.resolve();
|
if (loadingPromise) return loadingPromise;
|
|
const baseUrl = getDocumentServerUrl();
|
if (!baseUrl) {
|
return Promise.reject(new Error('未配置 VITE_GLOB_ONLYOFFICE_URL,无法加载 OnlyOffice 编辑器'));
|
}
|
|
loadingPromise = new Promise<void>((resolve, reject) => {
|
const script = document.createElement('script');
|
script.src = `${baseUrl}${API_PATH}`;
|
script.async = true;
|
script.addEventListener('load', () => resolve());
|
script.addEventListener('error', () => {
|
// 置空以允许重试:网络抖动或 DS 尚未起来时,下次打开还能再试一次
|
loadingPromise = null;
|
script.remove();
|
reject(new Error(`加载 ${baseUrl}${API_PATH} 失败,确认 Document Server 可达`));
|
});
|
document.head.append(script);
|
});
|
|
return loadingPromise;
|
}
|
|
/** 仅供测试重置单例用 */
|
export function resetDocsApiLoaderForTest() {
|
loadingPromise = null;
|
}
|