UNPKG

@koi-br/office-provider-sdk

Version:

Universal Office Provider SDK supporting WPS, OnlyOffice and more. Framework-agnostic library for React, Vue, Angular, and vanilla JavaScript / 通用 Office 提供商 SDK,支持 WPS、OnlyOffice 等多种办公套件。框架无关库,支持 React、Vue、Angular 和原生 JavaScript

962 lines (775 loc) 27.6 kB
# Office Provider SDK 一个**通用的 Office 提供商 SDK**,支持 WPS、OnlyOffice 等多种办公套件。**框架无关**设计,完美适配 React、Vue、Angular 和原生 JavaScript。 A **universal Office Provider SDK** supporting WPS, OnlyOffice and more office suites. **Framework-agnostic** design, perfectly compatible with React, Vue, Angular, and vanilla JavaScript. --- ## ✨ 核心特性 / Core Features - 🌐 **多Provider支持** - 统一 API 支持 WPS、OnlyOffice 等多种办公套件 - 🚀 **框架无关** - 可与 React、Vue、Angular 或原生 JavaScript 无缝集成 - 🤖 **智能配置** - 支持自动配置和手动配置两种模式 - 📝 **TypeScript 支持** - 完整的类型定义,提供出色的开发体验 - ⚡ **高性能** - 基于现代 JavaScript 模式,支持 Tree Shaking - 🛡️ **类型安全** - 严格的类型检查和运行时验证 - 🔧 **易于扩展** - 工厂模式设计,轻松添加新的 Provider --- ## 📦 安装 / Installation ```bash npm install @koi-br/office-provider-sdk ``` ### 主要导出 / Main Exports ```typescript // 主要初始化函数 import { initOfficeSDK } from '@koi-br/office-provider-sdk'; // 类型定义 import { OfficeProviderType, DocumentType, OfficeConfig, ReadyEventDetails, ErrorEventDetails } from '@koi-br/office-provider-sdk'; // SDK 实例创建 import { createOfficeSDK, getGlobalOfficeSDK } from '@koi-br/office-provider-sdk'; // Provider 类(高级用法) import { WPSProvider, OnlyOfficeProvider } from '@koi-br/office-provider-sdk'; // 工具函数 import { createErrorHandler, createReadyHandler, getSupportedProviders, isProviderSupported } from '@koi-br/office-provider-sdk'; ``` --- ## 🚀 快速开始 / Quick Start ### 自动配置模式(推荐)/ Auto Configuration (Recommended) ```typescript import { initOfficeSDK } from '@koi-br/office-provider-sdk'; // 通过 API 自动获取配置 // 注意:configApiUrl 会自动拼接 '/api/office/online-office/config' 路径 const sdk = await initOfficeSDK({ fileId: 'your-document-id', containerSelector: '#office-container', configApiUrl: 'https://api.example.com', // 基础URL,会自动拼接完整路径 token: 'your-auth-token', // 可选:API认证令牌 permissionToken: 'your-permission-token', // 可选:权限认证令牌 isReadOnly: false, onReady: (provider, details) => { console.log('编辑器已就绪:', details); }, onError: (error) => { console.error('编辑器错误:', error); } }); // 使用统一的 API await sdk.saveDocument(); await sdk.searchAndLocateText('Hello World!', true); ``` ### 手动配置模式 / Manual Configuration ```typescript import { initOfficeSDK, OfficeProviderType, DocumentType } from '@koi-br/office-provider-sdk'; // WPS 手动配置 const wpsSDK = await initOfficeSDK({ fileId: 'your-document-id', containerSelector: '#office-container', configApiUrl: '', // 手动模式下可以为空 autoConfig: false, providerType: OfficeProviderType.WPS, manualConfig: { wps: { appId: 'your-wps-app-id', token: 'your-auth-token', refreshToken: 'your-refresh-token', // 可选 documentType: DocumentType.WRITER, // 可选 simple: false // 可选,是否使用简化模式 } } }); // OnlyOffice 手动配置 const onlyOfficeSDK = await initOfficeSDK({ fileId: 'your-document-id', containerSelector: '#office-container', configApiUrl: '', // 手动模式下可以为空 autoConfig: false, providerType: OfficeProviderType.ONLYOFFICE, manualConfig: { onlyoffice: { documentServerUrl: 'https://your-onlyoffice-server.com', token: 'your-jwt-token', // 可选:JWT安全令牌 document: { fileType: 'docx', key: 'unique-document-key', title: 'Document.docx', url: 'https://example.com/document.docx', token: 'document-level-token' // 可选:文档级JWT令牌 }, editorConfig: { // 可选 mode: 'edit', // 'edit' | 'view' callbackUrl: 'https://example.com/callback', user: { id: 'user-id', name: 'User Name' } }, permissions: { // 可选 edit: true, download: true, review: true, comment: true } } } }); ``` --- ## 📚 API 参考 / API Reference ### 初始化配置 / Initialization Config ```typescript interface OfficeConfig { // 必需参数 / Required fileId: string; // 文档ID containerSelector: string; // 容器选择器(CSS选择器,如 '#office-container') configApiUrl: string; // 配置API基础地址(自动模式) // 实际请求URL为: configApiUrl + '/api/office/online-office/config?fileId=xxx&permissionToken=xxx' // 可选参数 / Optional isReadOnly?: boolean; // 只读模式,默认 false autoConfig?: boolean; // 自动配置,默认 true token?: string; // API认证令牌(用于Authorization头) permissionToken?: string; // 权限认证令牌(用于API查询参数) // 手动配置参数 / Manual Configuration(autoConfig=false 时必需) providerType?: OfficeProviderType; // Provider类型('wps' | 'onlyoffice') manualConfig?: ManualProviderConfig; // 具体配置 // 事件回调 / Event Callbacks onReady?: (provider: any, details?: ReadyEventDetails) => void; onError?: (error: ErrorEventDetails) => void; } ``` ### 统一文档操作 API / Unified Document API ```typescript // ========== 文本搜索和定位 ========== // 搜索并定位文本(所有Provider支持) await sdk.searchAndLocateText(text: string, highlight?: boolean); // 根据文本定位(所有Provider支持) await sdk.locateByText({ text: string }); // 搜索并替换(所有Provider支持) await sdk.searchAndReplace({ old: string, new: string }); // ========== WPS 特有文本操作 ========== // ⚠️ 以下方法仅在 WPS Provider 下可用 await sdk.insertTextAtCursor(text: string); // 在光标位置插入文本 await sdk.replaceText(pos: number, length: number, newText: string); // 替换指定位置内容 await sdk.getDocumentLength(); // 获取文档长度 // ========== 高亮操作 ========== // ⚠️ 以下方法仅在 WPS Provider 下可用 await sdk.highlightText(pos: number, length: number); // 高亮指定范围 await sdk.clearHighlight(); // 清除所有高亮 // ========== 内容控制(所有Provider支持) ========== // 添加内容控制字段 await sdk.addContentControl({ fieldId: string, placeholderText?: string }); // 设置内容控制的值 await sdk.setContentControlValue(fieldId: string, value: string); // 删除内容控制 await sdk.removeContentControl(fieldId: string); // 设置内容控制高亮颜色 [R, G, B, A] await sdk.setControlsHighlight([255, 0, 0, 1]); // ========== 文档管理 ========== // 保存文档(所有Provider支持) await sdk.saveDocument(); // 设置只读状态(所有Provider支持) await sdk.setReadOnly(isReadOnly: boolean); // ========== 评论相关(所有Provider支持) ========== // 获取评论列表 await sdk.getCommentsList(key: string); // 跳转到指定评论 await sdk.jumpCommentDto(jumpId: string, documentKey: string); // ========== 视图操作(所有Provider支持) ========== // 滚动到指定位置 await sdk.viewScrollToY(y: number); // 适应宽度 await sdk.zoomFitToWidth(); // ========== 修订管理(WPS 特有) ========== // ⚠️ 以下方法仅在 WPS Provider 下可用 await sdk.getRevisions(date?: string); // 获取修订信息 await sdk.handleRevisions(revisionIds: number[], action: 'accept' | 'reject'); // 处理修订 await sdk.acceptReviewByText({ old: string, new: string }); // 根据文本接受修订 await sdk.rejectReviewByText({ old: string, new: string }); // 根据文本拒绝修订 // ========== 格式化(WPS 特有) ========== // ⚠️ 此方法仅在 WPS Provider 下可用 await sdk.formatDocumentFont({ name?: string, // 字体名称 size?: number, // 字体大小 bold?: boolean, // 是否粗体 italic?: boolean, // 是否斜体 color?: string // 字体颜色(如 '#333333') }); // ========== 高级用法 ========== // 获取原生实例(所有Provider支持,但返回类型因Provider而异) const nativeInstance = sdk.getNativeInstance(); ``` ### Provider 管理 / Provider Management ```typescript // 获取当前 Provider 信息 const providerType = sdk.getCurrentProviderType(); // 返回 'wps' | 'onlyoffice' | null const providerName = sdk.getCurrentProviderName(); // 返回 Provider 名称 // 检查就绪状态 const isReady = sdk.isReady; // boolean // 获取支持的 Provider 列表 const providers = sdk.getSupportedProviders(); // Array<{ name: string, type: OfficeProviderType }> // 切换 Provider(高级用法) await sdk.switchProvider(newConfig); // 销毁实例 await sdk.destroy(); ``` ### 工具函数 / Utility Functions ```typescript import { createErrorHandler, createReadyHandler, getSupportedProviders, isProviderSupported, createOfficeSDK, getGlobalOfficeSDK } from '@koi-br/office-provider-sdk'; // 创建标准化的错误处理回调 const errorHandler = createErrorHandler((error) => { console.error('错误:', error.type, error.message); }); // 创建标准化的就绪回调 const readyHandler = createReadyHandler((provider, details) => { console.log('就绪:', details.providerName); }); // 获取支持的 Provider 列表 const providers = await getSupportedProviders(); // 检查是否支持指定 Provider const isWpsSupported = await isProviderSupported(OfficeProviderType.WPS); // 创建独立的 SDK 实例 const sdk1 = createOfficeSDK(); const sdk2 = createOfficeSDK(); // 获取全局 SDK 实例(单例) const globalSDK = getGlobalOfficeSDK(); ``` --- ## 🌐 框架集成示例 / Framework Integration Examples ### React 集成 / React Integration ```jsx import React, { useEffect, useRef, useState } from 'react'; import { initOfficeSDK } from '@koi-br/office-provider-sdk'; function OfficeEditor() { const [sdk, setSdk] = useState(null); const [isReady, setIsReady] = useState(false); useEffect(() => { const initEditor = async () => { try { const officeSDK = await initOfficeSDK({ fileId: 'react-demo-doc', containerSelector: '#office-container', configApiUrl: 'https://api.example.com', token: 'your-auth-token', permissionToken: 'your-permission-token', onReady: (provider, details) => { setIsReady(true); console.log('React: 编辑器已就绪', details); }, onError: (error) => { console.error('React: 编辑器错误', error); } }); setSdk(officeSDK); } catch (error) { console.error('初始化失败:', error); } }; initEditor(); return () => { if (sdk) { sdk.destroy(); } }; }, []); const handleSearch = async () => { if (sdk && isReady) { await sdk.searchAndLocateText('搜索文本', true); } }; const handleSave = async () => { if (sdk && isReady) { await sdk.saveDocument(); } }; return ( <div> <div className="controls"> <button onClick={handleSearch} disabled={!isReady}> 搜索文本 </button> <button onClick={handleSave} disabled={!isReady}> 保存文档 </button> </div> <div id="office-container" style={{ height: '600px' }} /> </div> ); } ``` ### Vue 3 集成 / Vue 3 Integration ```vue <template> <div> <div class="controls"> <button @click="searchText" :disabled="!isReady">搜索文本</button> <button @click="saveDoc" :disabled="!isReady">保存文档</button> </div> <div id="office-container" style="height: 600px"></div> </div> </template> <script setup> import { ref, onMounted, onUnmounted } from 'vue'; import { initOfficeSDK } from '@koi-br/office-provider-sdk'; const sdk = ref(null); const isReady = ref(false); onMounted(async () => { try { sdk.value = await initOfficeSDK({ fileId: 'vue-demo-doc', containerSelector: '#office-container', configApiUrl: 'https://api.example.com', token: 'your-auth-token', permissionToken: 'your-permission-token', onReady: (provider, details) => { isReady.value = true; console.log('Vue: 编辑器已就绪', details); }, onError: (error) => { console.error('Vue: 编辑器错误', error); } }); } catch (error) { console.error('初始化失败:', error); } }); onUnmounted(() => { if (sdk.value) { sdk.value.destroy(); } }); const searchText = async () => { if (sdk.value && isReady.value) { await sdk.value.searchAndLocateText('搜索文本', true); } }; const saveDoc = async () => { if (sdk.value && isReady.value) { await sdk.value.saveDocument(); } }; </script> ``` ### Angular 集成 / Angular Integration ```typescript // office.service.ts import { Injectable } from '@angular/core'; import { initOfficeSDK, type OfficeSDK } from '@koi-br/office-provider-sdk'; @Injectable({ providedIn: 'root' }) export class OfficeService { private sdk: OfficeSDK | null = null; private isReady = false; async initialize(config: any): Promise<void> { this.sdk = await initOfficeSDK({ ...config, onReady: () => { this.isReady = true; console.log('Angular: 编辑器已就绪'); }, onError: (error) => { console.error('Angular: 编辑器错误', error); } }); } async searchText(text: string): Promise<void> { if (this.sdk && this.isReady) { await this.sdk.searchAndLocateText(text, true); } } async saveDocument(): Promise<void> { if (this.sdk && this.isReady) { await this.sdk.saveDocument(); } } destroy(): Promise<void> { if (this.sdk) { return this.sdk.destroy(); } return Promise.resolve(); } } ``` ```typescript // office.component.ts import { Component, OnInit, OnDestroy } from '@angular/core'; import { OfficeService } from './office.service'; @Component({ selector: 'app-office', template: ` <div class="controls"> <button (click)="searchText()">搜索文本</button> <button (click)="saveDocument()">保存文档</button> </div> <div id="office-container" style="height: 600px;"></div> ` }) export class OfficeComponent implements OnInit, OnDestroy { constructor(private officeService: OfficeService) {} async ngOnInit() { await this.officeService.initialize({ fileId: 'angular-demo-doc', containerSelector: '#office-container', configApiUrl: 'https://api.example.com', token: 'your-auth-token', permissionToken: 'your-permission-token' }); } async ngOnDestroy() { await this.officeService.destroy(); } async searchText() { await this.officeService.searchText('搜索文本'); } async saveDocument() { await this.officeService.saveDocument(); } } ``` ### 原生 JavaScript / Vanilla JavaScript ```html <!DOCTYPE html> <html> <head> <title>Office Provider SDK Demo</title> </head> <body> <div class="controls"> <button onclick="searchText()">搜索文本</button> <button onclick="saveDocument()">保存文档</button> </div> <div id="office-container" style="height: 600px;"></div> <script type="module"> import { initOfficeSDK } from '@koi-br/office-provider-sdk'; let sdk = null; let isReady = false; async function initializeOffice() { try { sdk = await initOfficeSDK({ fileId: 'vanilla-demo-doc', containerSelector: '#office-container', configApiUrl: 'https://api.example.com', token: 'your-auth-token', permissionToken: 'your-permission-token', onReady: (provider, details) => { isReady = true; console.log('Vanilla JS: 编辑器已就绪', details); }, onError: (error) => { console.error('Vanilla JS: 编辑器错误', error); } }); } catch (error) { console.error('初始化失败:', error); } } window.searchText = async function() { if (sdk && isReady) { await sdk.searchAndLocateText('搜索文本', true); } }; window.saveDocument = async function() { if (sdk && isReady) { await sdk.saveDocument(); } }; // 初始化 initializeOffice(); </script> </body> </html> ``` --- ## 🔧 高级用法 / Advanced Usage ### Provider 特定功能 / Provider-Specific Features ```typescript // 获取当前 Provider 类型 const providerType = sdk.getCurrentProviderType(); // WPS 特定功能 if (providerType === OfficeProviderType.WPS) { // WPS 特有的文本操作方法 await sdk.insertTextAtCursor('文本内容'); await sdk.replaceText(0, 5, '新文本'); await sdk.highlightText(0, 10); await sdk.clearHighlight(); // 获取文档长度 const length = await sdk.getDocumentLength(); // 格式化文档 await sdk.formatDocumentFont({ name: '微软雅黑', size: 14, bold: true, color: '#333333' }); // 修订管理 const revisions = await sdk.getRevisions(); await sdk.handleRevisions([1, 2, 3], 'accept'); await sdk.acceptReviewByText({ old: '旧文本', new: '新文本' }); // 获取 WPS 原生实例(高级用法) const nativeInstance = sdk.getNativeInstance(); } // OnlyOffice 特定功能 if (providerType === OfficeProviderType.ONLYOFFICE) { // 内容控制操作(所有Provider都支持,但OnlyOffice有更丰富的功能) await sdk.addContentControl({ fieldId: 'custom-field', placeholderText: '请输入内容' }); await sdk.setContentControlValue('custom-field', '字段内容'); // 获取 OnlyOffice 原生实例(高级用法) const nativeInstance = sdk.getNativeInstance(); } ``` ### 错误处理最佳实践 / Error Handling Best Practices ```typescript import { initOfficeSDK, createErrorHandler, createReadyHandler } from '@koi-br/office-provider-sdk'; const sdk = await initOfficeSDK({ fileId: 'your-document-id', containerSelector: '#office-container', configApiUrl: 'https://api.example.com/office/config', // 使用辅助函数创建标准化的回调 onReady: createReadyHandler((provider, details) => { console.log(`${details.providerName} 已就绪`, details); // 自定义就绪逻辑 }), onError: createErrorHandler((error) => { // 统一的错误处理 switch (error.type) { case 'initialization_error': console.error('初始化失败:', error.message); break; case 'provider_switch_error': console.error('Provider 切换失败:', error.message); break; default: console.error('未知错误:', error); } // 可以添加错误上报、用户提示等逻辑 }) }); ``` ### 多实例管理 / Multiple Instances ```typescript import { createOfficeSDK } from '@koi-br/office-provider-sdk'; // 创建多个独立的 SDK 实例 const sdkInstances = []; for (let i = 0; i < 3; i++) { const sdk = createOfficeSDK(); await sdk.initialize({ fileId: `document-${i}`, containerSelector: `#office-container-${i}`, configApiUrl: 'https://api.example.com', token: 'your-auth-token', permissionToken: 'your-permission-token' }, { onReady: (provider, details) => { console.log(`实例 ${i} 已就绪:`, details); }, onError: (error) => { console.error(`实例 ${i} 错误:`, error); } }); sdkInstances.push(sdk); } // 统一操作所有实例 for (const sdk of sdkInstances) { await sdk.searchAndLocateText('批量操作文本', true); await sdk.saveDocument(); } ``` --- ## 🛠️ 开发和构建 / Development & Build ```bash # 安装依赖 npm install # 开发模式(包含演示) npm run dev # 构建库 npm run build # 构建演示 npm run build:example # 清理构建文件 npm run clean ``` --- ## 📁 项目结构 / Project Structure ``` office-provider-sdk/ ├── src/ │ ├── core/ # 核心 SDK 实现 │ │ ├── OfficeSDK.ts # 主 SDK 类 │ │ └── OfficeProviderFactory.ts # Provider 工厂 │ ├── providers/ # Provider 实现 │ │ ├── WPSProvider.ts # WPS Provider │ │ └── OnlyOfficeProvider.ts # OnlyOffice Provider │ ├── types/ # TypeScript 类型定义 │ │ └── index.ts │ ├── utils/ # 工具函数 │ │ └── index.ts │ └── index.ts # 主入口文件(导出 initOfficeSDK 等) ├── examples/ │ ├── demo.vue # Vue 3 完整演示 │ └── VueDemo.vue # Vue 3 演示(备用) ├── dist/ # 构建输出 ├── sdk/ # 外部 SDK 文件(WPS SDK等) └── README.md ``` --- ## 🌟 设计优势 / Design Advantages ### 统一抽象 / Unified Abstraction - **统一的 API 接口**:无论使用哪种 Office 套件,都使用相同的方法调用 - **Provider 模式**:可扩展的架构,轻松添加新的 Office 提供商 - **类型安全**:完整的 TypeScript 支持,编译时检查错误 ### 智能配置 / Smart Configuration - **自动检测**:通过 API 自动识别文档类型和 Provider - **配置分离**:业务逻辑与具体 Provider 配置解耦 - **降级支持**:自动配置失败时可回退到手动配置 ### 开发体验 / Developer Experience - **框架无关**:可在任何前端技术栈中使用 - **开箱即用**:最少配置即可开始使用 - **渐进增强**:从简单使用到高级定制的平滑过渡 ### 生产就绪 / Production Ready - **错误处理**:完善的错误处理和回调机制 - **性能优化**:基于现代 JavaScript,支持 Tree Shaking - **可维护性**:模块化设计,易于测试和维护 --- ## 📖 更多示例 / More Examples ### 搜索和替换 / Search & Replace ```typescript // 搜索并高亮文本(所有Provider支持) const result = await sdk.searchAndLocateText('目标文本', true); if (result && typeof result === 'object' && result.found) { console.log(`找到文本,位置: ${result.pos}, 长度: ${result.length}`); } // 搜索并替换(所有Provider支持) await sdk.searchAndReplace({ old: '目标文本', new: '新文本' }); // 根据文本定位(所有Provider支持) await sdk.locateByText({ text: '目标文本' }); // 清除所有高亮(仅WPS支持) if (sdk.getCurrentProviderType() === OfficeProviderType.WPS) { await sdk.clearHighlight(); } ``` ### 文档格式化 / Document Formatting ```typescript // 格式化整个文档(仅WPS支持) if (sdk.getCurrentProviderType() === OfficeProviderType.WPS) { await sdk.formatDocumentFont({ name: '微软雅黑', size: 14, bold: false, italic: false, color: '#333333' }); } // 设置文档为只读模式(所有Provider支持) await sdk.setReadOnly(true); ``` ### 内容控制 / Content Control ```typescript // 添加内容控制字段(所有Provider支持) await sdk.addContentControl({ fieldId: 'field-1', placeholderText: '请输入内容' }); // 设置内容控制的值 await sdk.setContentControlValue('field-1', '字段内容'); // 设置内容控制高亮颜色 [R, G, B, A] await sdk.setControlsHighlight([255, 0, 0, 1]); // 红色高亮 // 删除内容控制 await sdk.removeContentControl('field-1'); ``` ### 评论和视图操作 / Comments and View Operations ```typescript // 获取评论列表(所有Provider支持) const comments = await sdk.getCommentsList('document-key'); // 跳转到指定评论 await sdk.jumpCommentDto('comment-id', 'document-key'); // 滚动到指定位置(所有Provider支持) await sdk.viewScrollToY(500); // 适应宽度(所有Provider支持) await sdk.zoomFitToWidth(); ``` ### 修订管理 / Revision Management ```typescript // 获取所有修订 const revisions = await sdk.getRevisions(); console.log(`找到 ${revisions.length} 个修订`); // 批量处理修订 const revisionIds = revisions.map(r => r.index); await sdk.handleRevisions(revisionIds, 'accept'); // 或 'reject' ``` --- ## ❓ 常见问题 / FAQ ### Q: 如何确定使用哪种配置模式? **A:** 推荐使用自动配置模式,它可以根据文档自动选择合适的 Provider。如果你需要精确控制或在离线环境中使用,可以选择手动配置模式。 ### Q: configApiUrl 的完整URL是什么? **A:** SDK 会自动拼接完整路径。如果你传入 `configApiUrl: 'https://api.example.com'`,实际请求的URL是: `https://api.example.com/api/office/online-office/config?fileId=xxx&permissionToken=xxx` ### Q: 是否支持同时加载多个文档? **A:** 是的,你可以使用 `createOfficeSDK()` 创建多个独立的 SDK 实例,每个实例管理一个文档。 ### Q: 哪些功能是WPS特有的? **A:** WPS 特有的功能包括:`insertTextAtCursor`、`replaceText`、`highlightText`、`clearHighlight`、`getDocumentLength`、`formatDocumentFont`、`getRevisions`、`handleRevisions`、`acceptReviewByText`。其他功能(如内容控制、评论、搜索等)所有Provider都支持。 ### Q: 如何处理大文档的性能问题? **A:** SDK 内置了性能优化,包括懒加载、事件节流等。对于特别大的文档,建议使用只读模式或分页加载。 ### Q: 是否支持自定义 Provider? **A:** 是的,你可以实现 `IOfficeProvider` 接口创建自定义 Provider,然后通过 `OfficeProviderFactory` 注册。 ### Q: 如何调试初始化问题? **A:** 启用详细的错误回调,检查控制台输出。确保: - 容器元素存在且可见 - configApiUrl 正确(会自动拼接 `/api/office/online-office/config`) - token 和 permissionToken 有效(如果使用) - 网络连接正常 --- ## 🤝 贡献指南 / Contributing 我们欢迎所有形式的贡献!请查看我们的贡献指南: 1. Fork 项目 2. 创建功能分支 (`git checkout -b feature/AmazingFeature`) 3. 提交更改 (`git commit -m 'Add some AmazingFeature'`) 4. 推送到分支 (`git push origin feature/AmazingFeature`) 5. 开启 Pull Request --- ## 📄 许可证 / License MIT License - 查看 [LICENSE](LICENSE) 文件了解详情。 --- ## 🔗 相关链接 / Related Links - [WPS 开放平台](https://wwo.wps.cn/) - [OnlyOffice API 文档](https://api.onlyoffice.com/) - [TypeScript 官方文档](https://www.typescriptlang.org/) - [Vue.js 官方文档](https://vuejs.org/) - [React 官方文档](https://reactjs.org/) - [Angular 官方文档](https://angular.io/) --- ## 📞 支持 / Support 如果你有任何问题或建议,请: - 创建 [Issue](https://github.com/your-org/office-provider-sdk/issues) - 发送邮件至:[support@example.com](mailto:support@example.com) - 查看 [Wiki 文档](https://github.com/your-org/office-provider-sdk/wiki) --- <div align="center"> **⭐ 如果这个项目对你有帮助,请给它一个 Star!** Made with ❤️ by [Your Team] </div>