123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634 |
- import 'dart:convert';
- import 'dart:io';
- import 'package:flutter/material.dart';
- import 'package:flutter/services.dart';
- import 'package:flutter_inappwebview/flutter_inappwebview.dart';
- import 'package:get/get.dart';
- import 'package:image_picker/image_picker.dart';
- // import 'package:open_file/open_file.dart';
- import '../../../../common/api/index.dart';
- import '../../../../common/models/index.dart';
- import '../../../../common/routers/index.dart';
- import '../../../../common/utils/index.dart';
- import '../../../../common/values/index.dart';
- import '../../../../common/widgets/index.dart';
- import '../../../common/create_form/index.dart';
- import '../../../common/preview_image/index.dart';
- import '../../../common/process_webview/index.dart';
- import '../../../common/video_player/index.dart';
- import '../cms_app/index.dart';
- import 'index.dart';
- class CmsDocumentController extends GetxController implements JsNavigationInterface {
- CmsDocumentController();
- final state = CmsDocumentState();
- final channel = O2FlutterMethodChannelUtils();
- // webview控件的控制器
- final GlobalKey webViewKey = GlobalKey();
- InAppWebViewController? webviewController;
- // webview 通用方法
- final webviewHelper = WebviewHelper();
- // 安装转化js
- var isInstallJsName = false;
- // 拍照 图片选择
- final ImagePicker _imagePicker = ImagePicker();
- final _eventBus = EventBus();
- String? docId;
- // cms 创建文档使用的对象
- CmsAppData? _app;
- CmsCategoryData? _category;
- Map<String, dynamic>? _cmsMessageData;
- /// 在 widget 内存中分配后立即调用。
- @override
- void onInit() {
- super.onInit();
- }
- /// 在 onInit() 之后调用 1 帧。这是进入的理想场所
- @override
- void onReady() {
- var map = Get.arguments;
- if (map != null) {
- state.title = map["title"] ?? "cms_document_title".tr;
- OLogger.d("文档标题 title: ${state.title} ");
- String id = map["documentId"] ?? "";
- OLogger.d("文档id: $id ");
- if (id.isNotEmpty) {
- docId = id;
- _initCmsUrl(id, map["options"]);
- }
- }
- super.onReady();
- }
- @override
- void closeWindow() {
- OLogger.d('执行了 jsapi closeWindow ');
- _eventBus.emit(EventBus.cmsDocumentCloseMsg, 'close');
- Get.back();
- }
-
- @override
- void goBack() {
- OLogger.d('执行了 jsapi goBack ');
- tapBackBtn();
- }
-
- @override
- void setNavigationTitle(String title) {
- OLogger.d('执行了 jsapi setNavigationTitle $title ');
- state.title = title;
- }
- void _initCmsUrl(String id, Map<String, dynamic>? options) async {
- var url = O2ApiManager.instance.getCmsDocumentUrl(id) ?? '';
- if (options != null) {
- var readonly = options['readonly'];
- if (readonly != null && (readonly == 'false' || readonly == false)) {
- url = O2ApiManager.instance.getCmsDocumentEditUrl(id) ?? '';
- }
- for (var element in options.entries) {
- OLogger.i('参数 ${element.key} : ${element.value}');
- url += '&${element.key}=${Uri.encodeComponent('${element.value}')}';
- }
- }
- if (url.isNotEmpty) {
- final uurl = Uri.parse(url);
- var host = O2ApiManager.instance.getWebHost();
- var domain = uurl.host;
- var tokenName = O2ApiManager.instance.tokenName;
- var token = O2ApiManager.instance.o2User?.token ?? '';
- OLogger.d(
- "加载webview cookie,url: $url domain: $domain tokenName: $tokenName token: $token");
- CookieManager cookieManager = CookieManager.instance();
- await cookieManager.deleteAllCookies();
- await cookieManager.setCookie(
- url: uurl,
- name: tokenName,
- value: token,
- domain: (domain.isEmpty ? host : domain));
- state.url = url;
- }
- OLogger.d("打开网址: $url");
- }
- ///
- /// 点击appbar 返回按钮
- ///
- void tapBackBtn() async {
- OLogger.d('执行了 tapBackBtn ');
- if (await webviewController?.canGoBack() == true) {
- webviewController?.goBack();
- } else {
- closeWindow();
- }
- }
- /// 加载js通道
- void setupWebviewJsHandler(InAppWebViewController c) async {
- webviewController = c;
- webviewController?.addJavaScriptHandler(
- handlerName: O2.webviewChannelNameCommonKey,
- callback: (msgs) {
- OLogger.d(
- "js 通信, name: ${O2.webviewChannelNameCommonKey} msg: $msgs");
- if (msgs.isNotEmpty) {
- String msg = msgs[0] as String? ?? "";
- _jsChannelMessageReceived(msg);
- }
- });
- webviewHelper.setupWebviewJsHandler(c);
- webviewHelper.setupJsNavigationInterface(this);
- }
- /// webview 加载进度
- void progressChanged(InAppWebViewController c, int p) {
- OLogger.d("o2Webview process progress: $p");
- // 这里把 inappwebview的 js handler 方式修改成 我们自定义的
- if (p == 100 && !isInstallJsName) {
- isInstallJsName = true;
- // o2android
- var js = '''
- if (window.flutter_inappwebview && window.flutter_inappwebview.callHandler) {
- window.o2android = {};
- window.o2android.postMessage = function(message){
- window.flutter_inappwebview.callHandler('o2android', message);
- };
- }
- ''';
- c.evaluateJavascript(source: js);
- OLogger.i("执行o2android转化js完成。。。");
- webviewHelper.changeJsHandlerFunName(c);
- }
- }
- /// 打开附件
- void _openAttachmentFile(String filePath, String fileName) {
- if (filePath.isImageFileName) {
- PreviewImagePage.open(filePath, fileName);
- } else if (filePath.isVideoFileName) {
- VideoPlayerPage.openLocalVideo(filePath, title: fileName);
- } else {
- channel.openLocalFile(filePath);
- }
- }
- /// 接收js通道返回数据
- /// h5上调用js执行flutter这边的原生方法
- ///
- // void jsChannelMessageReceived(JavascriptMessage message) {
- // if (message.message.isNotEmpty) {
- void _jsChannelMessageReceived(String message) {
- OLogger.d("h5执行原生方法,message: $message");
- if (message.isEmpty) {
- return;
- }
- var jsMessage = JsMessage.fromJson(O2Utils.parseStringToJson(message));
- switch (jsMessage.type) {
- case "closeDocumentWindow":
- OLogger.d("关闭表单");
- closeWindow();
- break;
- case "downloadAttachment":
- _downloadAttachment(jsMessage.data);
- break;
- case "uploadAttachment":
- _uploadAttachment(jsMessage.data);
- break;
- case "uploadAttachmentForDatagrid":
- _uploadAttachment(jsMessage.data, forGrid: true);
- break;
- case "replaceAttachment":
- _replaceAttachment(jsMessage.data);
- break;
- case "replaceAttachmentForDatagrid":
- _replaceAttachment(jsMessage.data, forGrid: true);
- break;
- case "uploadImage2FileStorage": // imageclipper 图片上传控件
- _uploadImage2FileStorage(jsMessage.data);
- break;
- case 'openO2Work':
- _openWork(jsMessage.data);
- break;
- case 'createO2CmsDocument':
- _createO2CmsDocument(jsMessage.data);
- break;
- case 'openO2CmsApplication':
- _openO2CmsApplication(jsMessage.data);
- break;
- case 'openO2CmsDocument':
- _openO2CmsDocument(jsMessage.data);
- break;
- default:
- OLogger.e('错误的类型,$message');
- break;
- }
- _executeCallbackJs(jsMessage.callback, null);
- }
- /// 选择图片 或者 拍照
- /// 图片控件使用
- Future<void> _pickImageByType(int type, Map<String, dynamic> data) async {
- XFile? file;
- if (type == 0) {
- // 相册
- file = await _imagePicker.pickImage(source: ImageSource.gallery);
- } else if (type == 1) {
- // 拍照
- if (!await O2Utils.cameraPermission()) {
- return;
- }
- file = await _imagePicker.pickImage(source: ImageSource.camera);
- }
- if (file != null) {
- // var mwfId: String = "",//控件id
- // var callback: String = "",//回调函数
- // var referencetype: String = "",//上传文件服务器的业务类型名称
- // var reference: String = "",//关联业务id
- // var fileId: String = ""//上传返回的文件id
- String referencetype = data['referencetype'] ?? '';
- String reference = data['reference'] ?? '';
- String callback = data['callback'] ?? '';
- if (referencetype.isEmpty || reference.isEmpty || callback.isEmpty) {
- Loading.showError('args_error'.tr);
- return;
- }
- Loading.show();
- var id = await FileAssembleService.to.uploadImageWithReferencetype(
- referencetype, reference, File(file.path));
- if (id != null && id.id != null) {
- data['fileId'] = id.id;
- final back = json.encode(data);
- final js = '$callback(\'$back\')';
- OLogger.d('执行js :$js');
- await webviewController?.evaluateJavascript(source: js);
- Loading.dismiss();
- }
- }
- }
- ///
- /// 图片上传控件
- ///
- void _uploadImage2FileStorage(Map<String, dynamic>? data) {
- final myContext = Get.context;
- if (data != null && myContext != null) {
- O2UI.showBottomSheetWithCancel(myContext, [
- ListTile(
- onTap: () {
- Navigator.pop(myContext);
- _pickImageByType(0, data);
- },
- title: Align(
- alignment: Alignment.center,
- child: Text('album'.tr,
- style: Theme.of(myContext).textTheme.bodyMedium),
- ),
- ),
- const Divider(height: 1),
- ListTile(
- onTap: () {
- Navigator.pop(myContext);
- _pickImageByType(1, data);
- },
- title: Align(
- alignment: Alignment.center,
- child: Text('take_photo'.tr,
- style: Theme.of(myContext).textTheme.bodyMedium),
- ),
- ),
- ]);
- }
- }
- ///
- /// 下载附件
- ///
- void _downloadAttachment(Map<String, dynamic>? data) async {
- OLogger.d("下载附件");
- if (data != null) {
- String attachmentId = data["attachmentId"] ?? "";
- if (attachmentId.isNotEmpty && docId != null) {
- Loading.show();
- // 请求附件对象信息
- DocAttachmentInfo? info = await CmsAssembleControlService.to
- .getAttachmentInfoByDocId(docId!, attachmentId);
- if (info != null && info.name != null && info.id != null) {
- String? filePath = await O2FilePathUtil.getCmsFileDownloadLocalPath(
- info.id!, info.name!);
- if (filePath == null || filePath.isEmpty) {
- Loading.showError('process_work_download_file_no_path'.tr);
- return;
- }
- var file = File(filePath);
- if (file.existsSync()) {
- Loading.dismiss();
- _openAttachmentFile(filePath, info.name!);
- } else {
- // 下载附件
- var donwloadUrl = CmsAssembleControlService.to
- .downloadAttachmentUrl(attachmentId);
- try {
- await O2HttpClient.instance.downloadFile(donwloadUrl, filePath);
- Loading.dismiss();
- _openAttachmentFile(filePath, info.name!);
- } on Exception catch (e) {
- Loading.showError(e.toString());
- }
- }
- } else {
- Loading.showError('process_work_download_get_attachmentinfo_fail'.tr);
- }
- }
- }
- }
- ///
- /// 上传附件
- ///
- void _uploadAttachment(Map<String, dynamic>? data,
- {bool forGrid = false}) async {
- if (data != null && docId != null) {
- String site = data["site"] ?? "";
- String param = data["param"] ?? "";
- OLogger.d('上传附件 site $site , param $param');
- O2Utils.pickerFileOrImage((paths) {
- _uploadAttachmentBegin(paths, site, param, forGrid);
- }, allowMultiple: true);
- }
- }
- Future<void> _uploadAttachmentBegin(List<String?> paths, String site, String param, bool forGrid) async {
- Loading.show();
- int errorNumber = 0;
- for (var element in paths) {
- if (element != null && element.isNotEmpty) {
- var resId = await CmsAssembleControlService.to
- .uploadAttachment(docId!, site, File(element));
- if (resId != null && resId.id != null) {
- if (forGrid) {
- webviewController?.evaluateJavascript(
- source:
- "layout.app.appForm.uploadedAttachmentDatagrid(\"$site\", \"${resId.id}\", \"$param\")");
- } else {
- webviewController?.evaluateJavascript(
- source:
- "layout.app.appForm.uploadedAttachment(\"$site\", \"${resId.id}\")");
- }
- OLogger.d('上传附件成功 ${resId.id} ');
- } else {
- errorNumber++;
- }
- }
- }
- if (errorNumber > 0) {
- Loading.showError(
- 'process_attachment_upload_error'.trArgs(['$errorNumber']));
- } else {
- Loading.dismiss();
- }
- }
- ///
- /// 替换附件
- ///
- void _replaceAttachment(Map<String, dynamic>? data, {bool forGrid = false}) async {
- if (data != null && docId != null) {
- String site = data["site"] ?? "";
- String attachmentId = data["attachmentId"] ?? "";
- String param = data["param"] ?? "";
- OLogger.d('替换附件 site $site , attachmentId $attachmentId , param $param');
- O2Utils.pickerFileOrImage((paths) {
- _replaceAttachmentBegin(paths, attachmentId, site, param, forGrid);
- });
- }
- }
- Future<void> _replaceAttachmentBegin(List<String?> paths, String attachmentId, String site, String param, bool forGrid) async {
- if (paths.isEmpty) {
- return;
- }
- String path = paths[0] ?? '';
- if (path.isEmpty) {
- return;
- }
- Loading.show();
- OLogger.d('选择了文件:$path');
- var resId = await ProcessSurfaceService.to
- .replaceAttachment(docId!, attachmentId, File(path));
- if (resId != null && resId.id != null) {
- if (forGrid) {
- webviewController?.evaluateJavascript(
- source:
- "layout.app.appForm.replacedAttachmentDatagrid(\"$site\", \"${resId.id}\", \"$param\")");
- } else {
- webviewController?.evaluateJavascript(
- source:
- "layout.app.appForm.replacedAttachment(\"$site\", \"${resId.id}\")");
- }
- OLogger.d('替换附件成功 ${resId.id} ');
- Loading.dismiss();
- }
- }
- /// 打开工作
- /// workId: String, workCompletedId: String, title: String
- void _openWork(Map<String, dynamic>? data) {
- OLogger.d('===> _openWork, data: $data');
- if (data != null) {
- String workid = data['workId'] ?? '';
- if (workid.isEmpty) {
- workid = data['workCompletedId'] ?? '';
- }
- String darftId = data['draftId'] ?? '';
- if (workid.isNotEmpty) {
- ProcessWebviewPage.open(workid,
- title: data['title'] ?? 'process_work_no_title_no_process'.tr);
- } else if (darftId.isNotEmpty) {
- ProcessWebviewPage.openDraftById(darftId,
- title: data['title'] ?? 'process_work_no_title_no_process'.tr);
- }
- }
- }
- /// 打开信息文档
- /// docId: String, title: String, options: Map<String, dynamic>?
- void _openO2CmsDocument(Map<String, dynamic>? data) {
- if (data != null) {
- String docId = data['docId'] ?? '';
- if (docId.isNotEmpty) {
- CmsDocumentPage.open(docId,
- title: data['title'] ?? '', options: data['options']);
- }
- }
- }
- /// 打开信息中心
- /// appId: String, title: String
- void _openO2CmsApplication(Map<String, dynamic>? data) async {
- if (data != null && data['appId'] != null && data['appId'] is String) {
- var list =
- await CmsAssembleControlService.to.listAppWithCategoryUserCanView();
- if (list != null) {
- var app = list.firstWhereOrNull((element) =>
- element.id == data['appId'] ||
- element.appAlias == data['appId'] ||
- element.appName == data['appId']);
- if (app != null) {
- CmsAppPage.open(app); // 打开对应的
- return;
- }
- }
- }
- // 没有参数 直接打开cms
- Get.toNamed(O2OARoutes.appCms);
- }
- ///
- /// 创建文档
- /// * 创建文档 目前只有 column 和 category 有效果
- /* {
- "column" : column, //(string)可选,内容管理应用(栏目)的名称、别名或ID
- "category" : category, //(string)可选,要创建的文档所属的分类的名称、别名或ID
- "data" : data, //(json object)可选,创建文档时默认的业务数据
- "identity" : identity, //(string)可选,创建文档所使用的身份。如果此参数为空,且当前人有多个身份的情况下,会弹出身份选择对话框;否则使用默认身份。
- "callback" : callback, //(funcation)可选,文档创建后的回调函数。
- "target" : target, //(boolean)可选,为true时,在当前页面打开创建的文档;否则打开新窗口。默认false。
- "latest" : latest, //(boolean)可选,为true时,如果当前用户已经创建了此分类的文档,并且没有发布过,直接调用此文档为新文档;否则创建一个新文档。默认true。
- "selectColumnEnable" : selectColumnEnable, //(boolean)可选,是否可以选择应用和分类进行创建文档。有category参数时为默认false,否则默认为true。
- "ignoreTitle" : ignoreTitle //(boolean)可选,值为false时,创建的时候需要强制填写标题,默认为false。
- "restrictToColumn" : restrictToColumn //(boolean)可选,值为true时,会限制在传入的栏目中选择分类,默认为false。
- } */
- ///
- void _createO2CmsDocument(Map<String, dynamic>? data) async {
- OLogger.d('===> _createO2CmsDocument, data: $data');
- _app = null;
- _category = null;
- if (data != null) {
- _cmsMessageData = data;
- var categoryId = _cmsMessageData?['category'];
- if (categoryId != null && categoryId is String && categoryId.isNotEmpty) {
- // 根据分类id查询 分类和应用
- _category = await CmsAssembleControlService.to.getCategory(categoryId);
- if (_category != null && _category?.appId != null && _app == null) {
- _app = await CmsAssembleControlService.to.getApp(_category!.appId!);
- }
- } else {
- var appId = _cmsMessageData?['column'];
- if (appId != null && appId is String && appId.isNotEmpty) {
- // 只有应用id的情况 弹出分类选择器
- _app = await CmsAssembleControlService.to
- .getAppCanPublishCategories(appId);
- if (_app != null &&
- _app?.wrapOutCategoryList != null &&
- _app!.wrapOutCategoryList!.isNotEmpty) {
- var cList = _app!.wrapOutCategoryList!;
- if (cList.length == 1) {
- _category = cList[0];
- } else {
- _showCmsCategoryChoose(cList);
- return;
- }
- }
- }
- }
- }
- // 传入参数不足,选择分类
- if (_app == null || _category == null) {
- var category = await Get.toNamed(O2OARoutes.appCmsCategoryPicker);
- if (category != null && category is CmsCategoryData) {
- OLogger.d('选择了分类: ${category.toJson()}');
- _app = category.withApp;
- _category = category;
- }
- }
- _startCreateDocument();
- }
- /// 选择分类
- void _showCmsCategoryChoose(List<CmsCategoryData> list) {
- final c = Get.context;
- if (c != null) {
- O2UI.showBottomSheetWithCancel(
- c,
- list
- .map((e) => ListTile(
- onTap: () {
- Navigator.pop(c);
- _category = e;
- _startCreateDocument();
- },
- title: Align(
- alignment: Alignment.center,
- child: Text(e.categoryName ?? '',
- style: Theme.of(c).textTheme.bodyMedium),
- ),
- ))
- .toList());
- }
- }
- ///
- /// 参数查询完成后开始创建文档
- /// _app、_category 都赋值后
- ///
- void _startCreateDocument() async {
- if (_app == null || _category == null) {
- Loading.toast('cms_create_document_no_args'.tr);
- return;
- }
- OLogger.d('创建文档,app:${_app?.toJson()}');
- OLogger.d('创建文档,category:${_category?.toJson()}');
- final config = _app?.config ?? '{}';
- final configMap = O2Utils.parseStringToJson(config);
- final messageData = _cmsMessageData ?? {};
- bool ignoreTitle = false; // 是否忽略标题
- bool latest = true; // 是否查询草稿
- if (messageData.containsKey('ignoreTitle')) {
- ignoreTitle = messageData['ignoreTitle'] ?? false;
- } else if (configMap.containsKey('ignoreTitle')) {
- ignoreTitle = configMap['ignoreTitle'] ?? false;
- }
- if (messageData.containsKey('latest')) {
- latest = messageData['latest'] ?? true;
- } else if (configMap.containsKey('latest')) {
- latest = configMap['latest'] ?? true;
- }
- if (latest) {
- var drafts =
- await CmsAssembleControlService.to.listDocumentDraft(_category!.id!);
- if (drafts != null && drafts.isNotEmpty) {
- OLogger.d('有草稿。。。。');
- CmsDocumentPage.open(drafts[0].id!,
- title: drafts[0].title ?? '', options: {"readonly": false});
- return;
- }
- }
- CreateFormPage.startCmsDoc(ignoreTitle, category: _category!, cmsData: messageData['data']);
- }
- ///
- /// 如果有callback函数 就执行
- ///
- void _executeCallbackJs(String? callback, dynamic result) {
- if (callback != null && callback.isNotEmpty) {
- if (result != null) {
- webviewController?.evaluateJavascript(source: '$callback($result)');
- } else {
- webviewController?.evaluateJavascript(source: '$callback()');
- }
- }
- }
- /// 复制当前链接
- void copyLink() async {
- final url = await webviewController?.getUrl();
- if (url != null) {
- Clipboard.setData(ClipboardData(text: url.toString()));
- Loading.toast('im_chat_success_copy'.tr);
- }
- }
- }
|