# 高级功能指南 本文档介绍 `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 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 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 上告诉我们。