128 lines
3.4 KiB
TypeScript
128 lines
3.4 KiB
TypeScript
/**
|
||
* Collabora Online 配置生成服务
|
||
*
|
||
* 职责:
|
||
* - 生成 Collabora iframe URL
|
||
* - 生成 WOPI access token
|
||
* - 构建完整的 Collabora 配置
|
||
*
|
||
* @encoding UTF-8
|
||
*/
|
||
|
||
import type { CollaboraConfig } from '~/components/collabora/types';
|
||
import { APP_URL, COLLABORA_URL } from '~/config/api-config';
|
||
import { WopiService } from './collabora.wopi.server';
|
||
|
||
/**
|
||
* Collabora 配置生成参数
|
||
*/
|
||
export interface GenerateConfigParams {
|
||
fileId: string;
|
||
mode: 'view' | 'edit';
|
||
userId: string;
|
||
userName: string;
|
||
frontendJWT: string; // 用户的前端JWT token(用于调用FastAPI)
|
||
}
|
||
|
||
/**
|
||
* 生成 Collabora 配置
|
||
* @param params - 配置参数
|
||
* @returns Collabora 配置对象
|
||
*/
|
||
export async function generateCollaboraConfig(
|
||
params: GenerateConfigParams
|
||
): Promise<CollaboraConfig> {
|
||
const { fileId, mode, userId, userName, frontendJWT } = params;
|
||
|
||
// 创建 WOPI 服务实例
|
||
const wopiService = new WopiService();
|
||
|
||
// 生成 WOPI access token(2 小时有效期)
|
||
const accessToken = wopiService.generateAccessToken(
|
||
{
|
||
fileId,
|
||
mode,
|
||
userId,
|
||
userName,
|
||
frontendJWT,
|
||
},
|
||
7200 // 2 小时
|
||
);
|
||
|
||
// 构建 WOPI Src URL
|
||
const wopiSrc = `${APP_URL}/api/collabora/wopi/files/${encodeURIComponent(fileId)}`;
|
||
|
||
// 构建 Collabora iframe URL
|
||
const iframeUrl = buildCollaboraIframeUrl({
|
||
collaboraUrl: COLLABORA_URL,
|
||
wopiSrc,
|
||
accessToken,
|
||
mode,
|
||
});
|
||
|
||
// 提取文件名
|
||
const fileName = fileId.split('/').pop() || 'document.docx';
|
||
|
||
return {
|
||
iframeUrl,
|
||
accessToken,
|
||
fileName,
|
||
fileId,
|
||
collaboraUrl: COLLABORA_URL,
|
||
wopiSrc,
|
||
mode,
|
||
};
|
||
}
|
||
|
||
/**
|
||
* 构建 Collabora iframe URL
|
||
* @param params - URL 构建参数
|
||
* @returns Collabora iframe URL
|
||
*/
|
||
function buildCollaboraIframeUrl(params: {
|
||
collaboraUrl: string;
|
||
wopiSrc: string;
|
||
accessToken: string;
|
||
mode: 'view' | 'edit';
|
||
}): string {
|
||
const { collaboraUrl, wopiSrc, accessToken, mode } = params;
|
||
|
||
// Collabora iframe 基础 URL
|
||
// fa80579 是 Collabora 的版本号标识,实际部署时可能需要调整
|
||
const baseUrl = `${collaboraUrl}/browser/fa80579/cool.html`;
|
||
|
||
const url = new URL(baseUrl);
|
||
|
||
// 设置 WOPI Src
|
||
url.searchParams.set('WOPISrc', wopiSrc);
|
||
|
||
// 设置 access token
|
||
url.searchParams.set('access_token', accessToken);
|
||
|
||
// 设置 token 过期时间(毫秒)
|
||
url.searchParams.set('access_token_ttl', '7200000'); // 2 小时
|
||
|
||
// UI 定制参数
|
||
const uiDefaults = [
|
||
'UIMode=compact', // 紧凑模式
|
||
'TextRuler=false', // 隐藏标尺
|
||
'TextStatusbar=false', // 隐藏状态栏
|
||
'TextSidebar=false', // 隐藏侧边栏
|
||
'SavedUIState=false', // 不保存 UI 状态
|
||
].join(';');
|
||
url.searchParams.set('ui_defaults', uiDefaults);
|
||
|
||
// 其他 UI 参数
|
||
url.searchParams.set('closebutton', '0'); // 隐藏关闭按钮
|
||
url.searchParams.set('revisionhistory', 'false'); // 禁用修订历史
|
||
url.searchParams.set('lang', 'zh-CN'); // 设置语言为中文
|
||
|
||
// 根据模式设置权限
|
||
if (mode === 'view') {
|
||
// 只读模式:通过 URL 参数限制权限
|
||
url.searchParams.set('permission', 'readonly');
|
||
}
|
||
|
||
return url.toString();
|
||
}
|