npm package: @koi-br/office-provider-sdk
Description: 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
Author: chunyu.ma
Latest version: 1.0.38

# 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>