351 lines
8.3 KiB
Markdown
351 lines
8.3 KiB
Markdown
# 高级功能开发总结
|
||
|
||
## 概述
|
||
|
||
基于对 ONLYOFFICE 官方 Android 和 iOS 项目的深入研究,我创建了一个**高级功能分支**,提供了完整的编辑器控制能力。
|
||
|
||
## 官方项目研究成果
|
||
|
||
### 从官方 Android 项目学到的关键实现
|
||
|
||
1. **WebView 桥接模式**
|
||
- 使用 `addJavascriptInterface` 在原生代码和 JavaScript 之间通信
|
||
- 实现双向通信:Flutter ↔ JavaScript ↔ DocsAPI
|
||
|
||
2. **图片插入流程**
|
||
```
|
||
用户点击插入图片
|
||
→ 编辑器触发 onRequestInsertImage 事件
|
||
→ Flutter 打开图片选择器
|
||
→ 上传图片到服务器
|
||
→ 调用 docEditor.insertImage() 方法
|
||
```
|
||
|
||
3. **文件下载处理**
|
||
- 拦截下载 URL
|
||
- 使用原生下载管理器
|
||
- 保存到本地存储
|
||
|
||
### 从官方 iOS 项目学到的关键实现
|
||
|
||
1. **WKWebView 消息处理**
|
||
- 使用 `WKScriptMessageHandler` 接收消息
|
||
- 实现 `evaluateJavaScript` 调用编辑器方法
|
||
|
||
2. **生命周期管理**
|
||
- `onAppReady`: 编辑器应用加载完成
|
||
- `onDocumentReady`: 文档加载完成,可以调用方法
|
||
- `onDocumentStateChange`: 跟踪文档修改状态
|
||
|
||
3. **权限和安全**
|
||
- 相机/相册权限请求
|
||
- 文件访问权限
|
||
- JWT 签名验证
|
||
|
||
## 实现的高级功能
|
||
|
||
### 1. YxOnlyOfficeAdvancedViewer
|
||
|
||
完整的高级查看器,提供:
|
||
|
||
```dart
|
||
class YxOnlyOfficeAdvancedViewer extends StatefulWidget {
|
||
// WebViewController 访问
|
||
final Function(WebViewController controller)? onControllerReady;
|
||
|
||
// 生命周期事件
|
||
final Function()? onDocumentReady;
|
||
final Function()? onAppReady;
|
||
|
||
// 图片插入
|
||
final Future<String?> Function()? onRequestImageFromGallery;
|
||
final Future<String?> Function()? onRequestImageFromCamera;
|
||
|
||
// 文件下载
|
||
final Future<void> Function(String url, String filename)? onDownloadFile;
|
||
|
||
// 其他配置...
|
||
}
|
||
```
|
||
|
||
### 2. 编辑器方法调用
|
||
|
||
直接调用 DocsAPI 方法:
|
||
|
||
```dart
|
||
// 插入图片
|
||
await viewerState.insertImage('https://example.com/image.jpg');
|
||
|
||
// 下载文档
|
||
await viewerState.downloadAs('pdf');
|
||
|
||
// 设置审阅模式
|
||
await viewerState.setReviewerMode(true);
|
||
|
||
// 显示修订
|
||
await viewerState.showReviewChanges(true);
|
||
|
||
// 销毁编辑器
|
||
await viewerState.destroyEditor();
|
||
|
||
// 执行自定义 JavaScript
|
||
await viewerState.executeJavaScript('window.docEditor.getDocumentName()');
|
||
```
|
||
|
||
### 3. EditorMethodResult
|
||
|
||
统一的方法调用结果:
|
||
|
||
```dart
|
||
class EditorMethodResult {
|
||
final bool success;
|
||
final dynamic data;
|
||
final String? error;
|
||
}
|
||
```
|
||
|
||
### 4. 图片插入完整流程
|
||
|
||
```dart
|
||
// 1. 用户触发插入
|
||
onRequestInsertImage: (data) async {
|
||
// 2. 选择图片来源
|
||
final source = await showDialog(...);
|
||
|
||
// 3. 打开图片选择器
|
||
final image = await ImagePicker().pickImage(source: source);
|
||
|
||
// 4. 上传到服务器
|
||
final imageUrl = await uploadImage(image);
|
||
|
||
// 5. 插入到文档
|
||
await viewerState.insertImage(imageUrl);
|
||
}
|
||
```
|
||
|
||
### 5. 文件下载处理
|
||
|
||
```dart
|
||
onDownloadFile: (url, filename) async {
|
||
// 1. 下载文件
|
||
final response = await http.get(Uri.parse(url));
|
||
|
||
// 2. 保存到本地
|
||
final directory = await getApplicationDocumentsDirectory();
|
||
final file = File('${directory.path}/$filename');
|
||
await file.writeAsBytes(response.bodyBytes);
|
||
|
||
// 3. 通知用户
|
||
print('文件已保存: ${file.path}');
|
||
}
|
||
```
|
||
|
||
## 完整示例应用
|
||
|
||
创建了 `example/lib/main_advanced.dart`,展示:
|
||
|
||
- ✅ 图片插入(相机/相册)
|
||
- ✅ 文件下载(多种格式)
|
||
- ✅ 审阅模式切换
|
||
- ✅ 显示修订
|
||
- ✅ 自定义 JavaScript 执行
|
||
- ✅ 完整的错误处理
|
||
- ✅ 用户友好的 UI
|
||
- ✅ 编辑器信息面板
|
||
|
||
## 文件结构
|
||
|
||
```
|
||
lib/src/
|
||
├── onlyoffice_config.dart # 配置类(已有)
|
||
├── onlyoffice_html_builder.dart # HTML 构建器(已有)
|
||
├── onlyoffice_viewer.dart # 基础查看器(已有)
|
||
└── onlyoffice_advanced_viewer.dart # 🆕 高级查看器
|
||
|
||
example/lib/
|
||
├── main.dart # 基础示例(已有)
|
||
└── main_advanced.dart # 🆕 高级功能示例
|
||
|
||
docs/
|
||
├── API_REFERENCE.md # API 参考(已有)
|
||
├── QUICK_START.md # 快速开始(已有)
|
||
├── REFACTORING_SUMMARY.md # 重构总结(已有)
|
||
└── ADVANCED_FEATURES.md # 🆕 高级功能指南
|
||
```
|
||
|
||
## 与官方实现的对比
|
||
|
||
| 功能 | 官方 Android/iOS | 我们的实现 | 状态 |
|
||
|------|-----------------|-----------|------|
|
||
| 文档查看/编辑 | ✅ | ✅ | ✅ 完成 |
|
||
| WebView 桥接 | ✅ | ✅ | ✅ 完成 |
|
||
| 图片插入 | ✅ | ✅ | ✅ 完成 |
|
||
| 文件下载 | ✅ | ✅ | ✅ 完成 |
|
||
| 编辑器方法调用 | ✅ | ✅ | ✅ 完成 |
|
||
| 生命周期管理 | ✅ | ✅ | ✅ 完成 |
|
||
| JWT 签名 | ✅ | ✅ | ✅ 完成 |
|
||
| 离线编辑 | ✅ | ❌ | 🔄 未来版本 |
|
||
| 协作编辑 | ✅ | ✅ | ✅ 由 DocsAPI 提供 |
|
||
| 插件系统 | ✅ | ⚠️ | 🔄 可通过 JS 实现 |
|
||
|
||
## 技术亮点
|
||
|
||
### 1. 状态暴露设计
|
||
|
||
将 `_YxOnlyOfficeAdvancedViewerState` 改为公开的 `YxOnlyOfficeAdvancedViewerState`,允许外部访问:
|
||
|
||
```dart
|
||
final GlobalKey<YxOnlyOfficeAdvancedViewerState> viewerKey = GlobalKey();
|
||
|
||
// 可以调用状态方法
|
||
await viewerKey.currentState!.insertImage(url);
|
||
```
|
||
|
||
### 2. 结果封装
|
||
|
||
使用 `EditorMethodResult` 统一封装方法调用结果:
|
||
|
||
```dart
|
||
final result = await viewerState.insertImage(url);
|
||
if (result.success) {
|
||
print('成功: ${result.data}');
|
||
} else {
|
||
print('失败: ${result.error}');
|
||
}
|
||
```
|
||
|
||
### 3. 回调链设计
|
||
|
||
支持多层回调处理:
|
||
|
||
```dart
|
||
// 方式 1: 使用内置处理器
|
||
onRequestImageFromGallery: () async {
|
||
return await pickAndUploadImage();
|
||
}
|
||
|
||
// 方式 2: 手动调用
|
||
await viewerState.insertImage(imageUrl);
|
||
```
|
||
|
||
### 4. 文件下载拦截
|
||
|
||
自动拦截下载 URL:
|
||
|
||
```dart
|
||
bool _isDownloadUrl(String url) {
|
||
return url.contains('/download') ||
|
||
url.contains('download=') ||
|
||
url.contains('outputtype=');
|
||
}
|
||
```
|
||
|
||
## 使用方式对比
|
||
|
||
### 基础版本(YxOnlyOfficeViewer)
|
||
|
||
```dart
|
||
YxOnlyOfficeViewer.create(
|
||
serverUrl: serverUrl,
|
||
fileUrl: fileUrl,
|
||
mode: 'edit',
|
||
onError: (error) => print(error),
|
||
)
|
||
```
|
||
|
||
**适用于**:
|
||
- 简单的文档查看/编辑
|
||
- 不需要高级控制
|
||
- 快速集成
|
||
|
||
### 高级版本(YxOnlyOfficeAdvancedViewer)
|
||
|
||
```dart
|
||
YxOnlyOfficeAdvancedViewer(
|
||
serverUrl: serverUrl,
|
||
config: config,
|
||
onControllerReady: (controller) {
|
||
// 完全控制 WebView
|
||
},
|
||
onDocumentReady: () {
|
||
// 文档准备好,可以调用方法
|
||
},
|
||
onRequestImageFromGallery: () async {
|
||
// 自定义图片选择
|
||
},
|
||
)
|
||
|
||
// 调用编辑器方法
|
||
await viewerState.insertImage(url);
|
||
await viewerState.downloadAs('pdf');
|
||
```
|
||
|
||
**适用于**:
|
||
- 需要完整控制编辑器
|
||
- 图片插入功能
|
||
- 文件下载处理
|
||
- 自定义 JavaScript 执行
|
||
- 高级编辑功能
|
||
|
||
## 运行示例
|
||
|
||
### 基础示例
|
||
|
||
```bash
|
||
flutter run \
|
||
--dart-define ONLYOFFICE_SERVER_URL=https://... \
|
||
--dart-define ONLYOFFICE_FILE_URL=https://...
|
||
```
|
||
|
||
### 高级示例
|
||
|
||
```bash
|
||
flutter run -t lib/main_advanced.dart \
|
||
--dart-define ONLYOFFICE_SERVER_URL=https://... \
|
||
--dart-define ONLYOFFICE_FILE_URL=https://... \
|
||
--dart-define ONLYOFFICE_JWT_SECRET=secret \
|
||
--dart-define UPLOAD_URL=https://...
|
||
```
|
||
|
||
## 未来改进方向
|
||
|
||
基于官方项目,以下功能可以在未来版本中添加:
|
||
|
||
1. **离线编辑支持**
|
||
- 本地文档缓存
|
||
- 离线修改同步
|
||
|
||
2. **更多编辑器方法**
|
||
- 插入表格
|
||
- 插入图表
|
||
- 插入书签
|
||
- 查找/替换
|
||
|
||
3. **插件系统**
|
||
- 支持 ONLYOFFICE 插件
|
||
- 自定义工具栏
|
||
|
||
4. **性能优化**
|
||
- 文档预加载
|
||
- 图片压缩
|
||
- 增量更新
|
||
|
||
5. **协作功能增强**
|
||
- 用户在线状态
|
||
- 实时光标显示
|
||
- 聊天功能
|
||
|
||
## 总结
|
||
|
||
通过深入研究官方 Android 和 iOS 项目,我们成功实现了:
|
||
|
||
✅ **完整的 WebView 桥接** - 实现 Flutter 与 DocsAPI 的双向通信
|
||
✅ **编辑器方法调用** - 直接控制编辑器行为
|
||
✅ **图片插入功能** - 完整的图片选择和插入流程
|
||
✅ **文件下载处理** - 自动拦截和处理下载
|
||
✅ **生命周期管理** - 完整的编辑器生命周期事件
|
||
✅ **高质量示例** - 展示所有高级功能的使用
|
||
|
||
这个高级功能分支为 Flutter 开发者提供了与官方移动应用相当的功能和控制能力!🎉
|
||
|