yx_only_office_flutter/docs/ADVANCED_FEATURES.md

448 lines
9.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 高级功能指南
本文档介绍 `yx_only_office_flutter` 插件的高级功能,这些功能基于对官方 Android 和 iOS 项目的深入研究实现。
## 概述
高级功能通过 `YxOnlyOfficeAdvancedViewer` 提供,包括:
-**WebViewController 直接访问** - 完全控制 WebView
-**编辑器方法调用** - 直接调用 DocsAPI 方法
-**图片插入** - 从相机/相册插入图片
-**文件下载** - 自动处理文件下载
-**生命周期管理** - 完整的编辑器生命周期事件
-**自定义 JavaScript 执行** - 执行任意 JS 代码
## 快速开始
### 基础使用
```dart
import 'package:yx_only_office_flutter/yx_only_office_flutter.dart';
YxOnlyOfficeAdvancedViewer(
serverUrl: 'https://your-server.com',
config: config,
onControllerReady: (controller) {
// WebViewController 已准备好
print('Controller ready!');
},
onDocumentReady: () {
// 文档已加载完成,可以调用编辑器方法
print('Document ready!');
},
)
```
## 核心功能
### 1. WebViewController 访问
获取底层 WebViewController 进行高级操作:
```dart
WebViewController? _controller;
YxOnlyOfficeAdvancedViewer(
serverUrl: serverUrl,
config: config,
onControllerReady: (controller) {
_controller = controller;
// 现在可以直接使用 WebViewController
controller.runJavaScript('console.log("Hello from Flutter!")');
},
)
```
### 2. 编辑器方法调用
直接调用 DocsAPI 提供的方法:
#### 插入图片
```dart
final GlobalKey<_YxOnlyOfficeAdvancedViewerState> viewerKey = GlobalKey();
// 在 Widget 中
YxOnlyOfficeAdvancedViewer(
key: viewerKey,
serverUrl: serverUrl,
config: config,
)
// 调用方法
final result = await viewerKey.currentState!.insertImage(
'https://example.com/image.jpg'
);
if (result.success) {
print('图片插入成功');
} else {
print('失败: ${result.error}');
}
```
#### 下载文档
```dart
// 下载为 PDF
final result = await viewerKey.currentState!.downloadAs('pdf');
// 下载为 DOCX
final result = await viewerKey.currentState!.downloadAs('docx');
// 支持的格式: docx, pdf, txt, rtf, odt, html, epub 等
```
#### 设置审阅模式
```dart
// 启用审阅模式
await viewerKey.currentState!.setReviewerMode(true);
// 显示修订
await viewerKey.currentState!.showReviewChanges(true);
```
#### 销毁编辑器
```dart
await viewerKey.currentState!.destroyEditor();
```
#### 执行自定义 JavaScript
```dart
final result = await viewerKey.currentState!.executeJavaScript('''
if (window.docEditor) {
return window.docEditor.getDocumentName();
}
return null;
''');
print('文档名称: ${result.data}');
```
### 3. 图片插入功能
#### 方式 1使用内置处理器
```dart
YxOnlyOfficeAdvancedViewer(
serverUrl: serverUrl,
config: config,
onRequestImageFromGallery: () async {
// 从相册选择图片
final image = await ImagePicker().pickImage(
source: ImageSource.gallery,
);
if (image == null) return null;
// 上传到服务器
final imageUrl = await uploadToServer(image.path);
return imageUrl;
},
onRequestImageFromCamera: () async {
// 从相机拍照
final image = await ImagePicker().pickImage(
source: ImageSource.camera,
);
if (image == null) return null;
final imageUrl = await uploadToServer(image.path);
return imageUrl;
},
)
```
#### 方式 2手动调用
```dart
// 选择图片
final image = await ImagePicker().pickImage(source: ImageSource.gallery);
final imageUrl = await uploadToServer(image!.path);
// 插入到文档
final result = await viewerKey.currentState!.insertImage(imageUrl);
```
### 4. 文件下载处理
自动拦截并处理文件下载请求:
```dart
YxOnlyOfficeAdvancedViewer(
serverUrl: serverUrl,
config: config,
enableFileDownload: true,
onDownloadFile: (url, filename) async {
// 下载文件
final response = await http.get(Uri.parse(url));
// 保存到本地
final directory = await getApplicationDocumentsDirectory();
final file = File('${directory.path}/$filename');
await file.writeAsBytes(response.bodyBytes);
print('文件已保存: ${file.path}');
},
)
```
### 5. 生命周期事件
完整的编辑器生命周期管理:
```dart
YxOnlyOfficeAdvancedViewer(
serverUrl: serverUrl,
config: config,
onAppReady: () {
print('✅ 编辑器应用已准备好');
},
onDocumentReady: () {
print('✅ 文档已加载完成');
// 现在可以调用编辑器方法
},
onDocumentStateChange: (data) {
final hasChanges = data == true;
print('📝 文档${hasChanges ? "已修改" : "未修改"}');
},
onError: (error) {
print('❌ 错误: $error');
},
)
```
## 完整示例
查看 `example/lib/main_advanced.dart` 获取完整的可运行示例,包括:
- ✅ 图片插入(相机/相册)
- ✅ 文件下载(多种格式)
- ✅ 审阅模式切换
- ✅ 自定义 JavaScript 执行
- ✅ 完整的错误处理
- ✅ 用户友好的 UI
### 运行高级示例
```bash
cd example
flutter run -t lib/main_advanced.dart \
--dart-define ONLYOFFICE_SERVER_URL=https://your-server.com \
--dart-define ONLYOFFICE_FILE_URL=https://example.com/doc.docx \
--dart-define ONLYOFFICE_JWT_SECRET=your-secret \
--dart-define UPLOAD_URL=https://your-upload-server.com/upload
```
## API 参考
### EditorMethodResult
所有编辑器方法返回 `EditorMethodResult`
```dart
class EditorMethodResult {
final bool success; // 是否成功
final dynamic data; // 返回数据
final String? error; // 错误信息
}
```
### 可用方法
| 方法 | 说明 | 返回值 |
|------|------|--------|
| `insertImage(String url)` | 插入图片 | `EditorMethodResult` |
| `downloadAs(String fileType)` | 下载文档 | `EditorMethodResult` |
| `destroyEditor()` | 销毁编辑器 | `EditorMethodResult` |
| `setReviewerMode(bool enabled)` | 设置审阅模式 | `EditorMethodResult` |
| `showReviewChanges(bool show)` | 显示修订 | `EditorMethodResult` |
| `executeJavaScript(String code)` | 执行 JS 代码 | `EditorMethodResult` |
## 高级配置
### 自定义图片上传
```dart
Future<String?> uploadImage(File imageFile) async {
final request = http.MultipartRequest(
'POST',
Uri.parse('https://your-server.com/upload'),
);
request.files.add(
await http.MultipartFile.fromPath('file', imageFile.path),
);
final response = await request.send();
if (response.statusCode == 200) {
final body = await response.stream.bytesToString();
final json = jsonDecode(body);
return json['url'];
}
return null;
}
```
### 自定义文件下载
```dart
Future<void> downloadFile(String url, String filename) async {
// 显示进度对话框
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => AlertDialog(
content: Row(
children: [
CircularProgressIndicator(),
SizedBox(width: 16),
Text('正在下载...'),
],
),
),
);
try {
final response = await http.get(Uri.parse(url));
final directory = await getApplicationDocumentsDirectory();
final file = File('${directory.path}/$filename');
await file.writeAsBytes(response.bodyBytes);
Navigator.pop(context); // 关闭进度对话框
// 显示成功提示
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('文件已保存: ${file.path}')),
);
} catch (e) {
Navigator.pop(context);
// 显示错误
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('下载失败: $e')),
);
}
}
```
## 与基础版本的对比
| 功能 | YxOnlyOfficeViewer | YxOnlyOfficeAdvancedViewer |
|------|-------------------|---------------------------|
| 查看文档 | ✅ | ✅ |
| 编辑文档 | ✅ | ✅ |
| 基础事件 | ✅ | ✅ |
| WebViewController 访问 | ❌ | ✅ |
| 编辑器方法调用 | ❌ | ✅ |
| 图片插入 | ❌ | ✅ |
| 文件下载处理 | ❌ | ✅ |
| 生命周期事件 | 部分 | ✅ 完整 |
| 自定义 JS 执行 | ❌ | ✅ |
## 最佳实践
### 1. 等待文档准备好
```dart
bool _isDocumentReady = false;
YxOnlyOfficeAdvancedViewer(
onDocumentReady: () {
setState(() => _isDocumentReady = true);
},
)
// 只在文档准备好后调用方法
if (_isDocumentReady) {
await viewerKey.currentState!.insertImage(url);
}
```
### 2. 错误处理
```dart
final result = await viewerKey.currentState!.downloadAs('pdf');
if (result.success) {
print('成功');
} else {
print('失败: ${result.error}');
// 显示错误提示给用户
}
```
### 3. 内存管理
```dart
@override
void dispose() {
// 在页面销毁时销毁编辑器
viewerKey.currentState?.destroyEditor();
super.dispose();
}
```
## 常见问题
### Q: 如何判断编辑器是否准备好?
A: 监听 `onDocumentReady` 回调:
```dart
bool _isReady = false;
onDocumentReady: () {
setState(() => _isReady = true);
}
```
### Q: 图片插入失败怎么办?
A: 检查:
1. 文档是否已准备好(`onDocumentReady` 已触发)
2. 图片 URL 是否可访问
3. 是否有编辑权限(`mode: 'edit'`
### Q: 如何获取编辑器的当前状态?
A: 使用 `executeJavaScript`
```dart
final result = await viewerKey.currentState!.executeJavaScript('''
if (window.docEditor) {
return {
name: window.docEditor.getDocumentName(),
// 其他信息...
};
}
return null;
''');
```
### Q: 支持哪些下载格式?
A: 支持的格式取决于文档类型:
- **Word**: docx, pdf, txt, rtf, odt, html, epub
- **Excel**: xlsx, pdf, csv, ods
- **PowerPoint**: pptx, pdf, odp
## 更多资源
- [基础功能文档](../README.md)
- [API 参考](API_REFERENCE.md)
- [快速开始](QUICK_START.md)
- [ONLYOFFICE 官方文档](https://api.onlyoffice.com/docs/docs-api/)
## 贡献
欢迎提交 Issue 和 Pull Request如果您发现了 Bug 或有功能建议,请在 GitHub 上告诉我们。