刘光辉
11 小时以前 0dfe84494048ce27ba8449831782128412d3eb13
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
 * 载入 Document Server 的 api.js。
 *
 * 这个脚本挂的是全局 `window.DocsAPI`,同一页面只能载入一次,所以用单例 Promise 收口——
 * 多个编辑器实例(或反复开关弹窗)并发调用时共用同一次加载。
 *
 * 地址走 `import.meta.env.VITE_GLOB_ONLYOFFICE_URL`,刻意不进 `useGlobSetting()`:
 * 那条链路是白名单式解构(packages/types/global.d.ts → use-app-config.ts → hooks/setting),
 * 加一个字段要改三个跨层共享包。Vite 对 VITE_ 前缀变量本就会静态替换,直接读即可。
 */
const API_PATH = '/web-apps/apps/api/documents/api.js';
 
let loadingPromise: null | Promise<void> = null;
 
export function getDocumentServerUrl(): string {
  const url = 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;
}