import 'dart:async'; import 'dart:io'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:dsbridge_flutter/dsbridge_flutter.dart'; import 'package:electronic_assistant/base/base_controller.dart'; import 'package:electronic_assistant/data/consts/event_report_id.dart'; import 'package:electronic_assistant/data/repositories/account_repository.dart'; import 'package:electronic_assistant/data/repositories/config_repository.dart'; import 'package:electronic_assistant/data/repositories/task_repository.dart'; import 'package:electronic_assistant/handler/event_handler.dart'; import 'package:electronic_assistant/module/chat/view.dart'; import 'package:electronic_assistant/module/login/view.dart'; import 'package:electronic_assistant/module/record/record_handler.dart'; import 'package:electronic_assistant/module/store/view.dart'; import 'package:electronic_assistant/module/talk/mindmap/mind_util.dart'; import 'package:electronic_assistant/module/talk/summary/view.dart'; import 'package:electronic_assistant/module/talk/todo/controller.dart'; import 'package:electronic_assistant/module/talk/todo/view.dart'; import 'package:electronic_assistant/resource/assets.gen.dart'; import 'package:electronic_assistant/resource/colors.gen.dart'; import 'package:electronic_assistant/resource/string.gen.dart'; import 'package:electronic_assistant/router/app_pages.dart'; import 'package:electronic_assistant/utils/audio_picker_utils.dart'; import 'package:electronic_assistant/utils/error_handler.dart'; import 'package:electronic_assistant/utils/expand.dart'; import 'package:electronic_assistant/utils/file_upload_check_helper.dart'; import 'package:electronic_assistant/utils/mmkv_util.dart'; import 'package:electronic_assistant/utils/pair.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:just_audio/just_audio.dart'; import 'package:share_plus/share_plus.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; import '../../data/api/request/agenda_update_bean.dart'; import '../../data/bean/agenda.dart'; import '../../data/bean/agenda_list_all_bean.dart'; import '../../data/bean/talk_tabs.dart'; import '../../data/bean/talks.dart'; import '../../data/bean/template_bean.dart'; import '../../data/repositories/agenda_repository.dart'; import '../../data/repositories/talk_repository.dart'; import '../../dialog/add_agenda_dialog.dart'; import '../../dialog/alert_dialog.dart'; import '../../dialog/loading_dialog.dart'; import '../../dialog/rename_dialog.dart'; import '../../dialog/talk_share_dialog.dart'; import '../../utils/common_utils.dart'; import '../../utils/event_bus.dart'; import '../../utils/system_share_util.dart'; import '../../utils/toast_util.dart'; import 'package:webview_flutter/webview_flutter.dart'; import 'mindmap/view.dart'; import 'original/view.dart'; class TalkController extends BaseController { static const String argumentItem = 'argument_item'; static const String argumentTalkId = 'argument_talk_id'; static const String argumentEventTag = 'argument_event_tag'; final String uploadNoPrompts = "UPLOAD_NO_PROMPTS"; final Rxn talkBean = Rxn(); StreamSubscription? _talkUploadListener; final RxDouble uploadProgress = RxDouble(0); final isShowElectricLow = false.obs; bool isAudioLoading = false; final double sliderMax = 1; bool? audioFileIsExist; bool? isUploadedFile; Rxn isUploading = Rxn(); final isAudioPlaying = false.obs; final audioProgressValue = 0.0.obs; final audioDuration = Duration.zero.obs; final agendaOriginalAllList = []; final agendaAllList = [].obs; final _isEditModel = false.obs; final isSearchModel = false.obs; final Rxn checkTabBean = Rxn(); final List tabBeans = []; final List pages = []; final isInitializedView = false.obs; bool get isEditModel => _isEditModel.value; RxBool get isEditModelRx => _isEditModel; final _audioPlayer = AudioPlayer(); StreamSubscription? _talkBeanListener; TextEditingController? _agendaContentController; TextEditingController? _agendaNameController; TextEditingController get agendaContentController { _agendaContentController ??= TextEditingController(); return _agendaContentController!; } TextEditingController get agendaNameController { _agendaNameController ??= TextEditingController(); return _agendaNameController!; } String? paramId; String? eventTag; bool isLocalFileHas = false; final Rxn playingDuration = Rxn(); bool isFirstRequestTask = true; //模板 Rxn?> templateList = Rxn(); Rxn templateSelectId = Rxn(); final RxBool isShowMindFullScreen = false.obs; //模板最大数量 int? maxTemplateCount; final mindFullDuration = const Duration(milliseconds: 250); GlobalKey tabBarGlobalKey = GlobalKey(); GlobalKey headGlobalKey = GlobalKey(); GlobalKey bottomGlobalKey = GlobalKey(); //高度 RxnDouble bottomViewHeight = RxnDouble(); RxnDouble headViewHeight = RxnDouble(); RxnDouble tabBarHeight = RxnDouble(); final DWebViewController webViewController = MindUtil.createMindWebViewController(); final Rxn _temporaryController = Rxn(); DWebViewController? get temporaryController => _temporaryController.value; RxBool isShowMindMap = false.obs; final RxString searchResultDesc = RxString('0/0'); final RxString searchPrint = RxString(''); Rxn> searchOperationCallback = Rxn(); int defaultIndex = 0; @override void onInit() { super.onInit(); _getArguments(); _analyticWebVersion(); } Future _analyticWebVersion() async { if (Platform.isAndroid) { String? userAgent = await webViewController.getUserAgent(); bool shouldShowMindMap = true; String? version; if (userAgent != null) { RegExp regExp = RegExp(r'Chrome/(\d+)\.'); Match? match = regExp.firstMatch(userAgent); if (match != null) { version = match.group(1) ?? ''; if (version.isNotEmpty && isNumeric(version)) { int versionNum = int.parse(version); shouldShowMindMap = versionNum > 92; } else { shouldShowMindMap = false; } } } else { shouldShowMindMap = false; } _setMindMap(shouldShowMindMap, version: version); } else { _setMindMap(true); } } void _setMindMap(bool isShow, {String? version}) { isShowMindMap.value = isShow; String? talkId = talkBean.value != null ? talkBean.value!.id : paramId; _fitTabsBean(isShow, talkId); if (isShow) { EventHandler.report(EventId.event_101401, params: {EventId.id: version}); } else { EventHandler.report(EventId.event_101402, params: {EventId.id: version}); } if (tabBeans.isNotEmpty) { checkTabBean.value = tabBeans[defaultIndex]; } isInitializedView.value = true; WidgetsBinding.instance.addPostFrameCallback((_) { bottomViewHeight.value = bottomGlobalKey.currentContext?.size?.height; headViewHeight.value = headGlobalKey.currentContext?.size?.height; tabBarHeight.value = tabBarGlobalKey.currentContext?.size?.height; }); } @override void onReady() { super.onReady(); _initAudioPlayer(); eventReport(EventId.event_101001, params: {EventId.id: eventTag}); } void _fitTabsBean(bool isIncludeMind, String? talkId) { final List pageList = []; final List barList = []; final List tabs = configRepository.getTalkTabs(); for (int i = 0; i < tabs.length; i++) { TalkTabs tab = tabs[i]; if (isIncludeMind == false && tab.type == TalkBarType.mindMap) { continue; } if (tab.select == true) { defaultIndex = i; } switch (tab.type) { case TalkBarType.summary: pageList.add(SummaryView(talkId)); barList.add(TalkBarBean(tab.type, tab.name, isShowEdit: true)); break; case TalkBarType.mindMap: pageList.add(MindMapView(talkId)); barList.add(TalkBarBean(tab.type, tab.name, isDisallowScroll: true)); break; case TalkBarType.myTask: pageList.add(TodoView(talkId)); barList.add(TalkBarBean(tab.type, tab.name, isShowEdit: true)); break; case TalkBarType.original: pageList.add(OriginalView(talkId)); barList.add(TalkBarBean(tab.type, tab.name, isShowSearch: true)); break; } } pages.assignAll(pageList); tabBeans.assignAll(barList); } double? getChangeHeadHeight() { if (_isEditModel.value == true || isSearchModel.value == true) { return (headViewHeight.value ?? 0) - (tabBarHeight.value ?? 0); } return isShowMindFullScreen.value ? 0 : headViewHeight.value; } double getChangeBottomHeight() { return isShowMindFullScreen.value || _isEditModel.value || isSearchModel.value ? getBottomViewHeight() : 0.h; } double getBottomViewHeight() { return bottomViewHeight.value != null ? -bottomViewHeight.value! : -250.h; } void eventReport(String eventId, {Map? params}) { if (talkBean.value == null || talkBean.value?.isExample == true) { return; } EventHandler.report(eventId, params: params); } void _initAudioPlayer() { _audioPlayer.playerStateStream.listen((playerState) { if (playerState.processingState == ProcessingState.loading || playerState.processingState == ProcessingState.buffering) { isAudioLoading = true; debugPrint('音频load = true'); } else { debugPrint('音频load = false'); isAudioLoading = false; if (playerState.processingState == ProcessingState.completed) { _audioPlayer.stop(); _audioPlayer.seek(Duration.zero); isAudioPlaying.value = false; debugPrint('音频 播放结束了'); } } isAudioPlaying.value = playerState.playing; }, onError: (Object e, StackTrace stackTrace) { debugPrint('音频加载异常 == $e'); }); _audioPlayer.durationStream.listen((duration) { if (duration != null) { debugPrint('音频总播放时长 == ${duration.inMilliseconds}'); audioDuration.value = duration; } }); _audioPlayer.positionStream.listen((duration) { debugPrint('音频播放时长 == ${duration.inMilliseconds}'); playingDuration.value = duration; if (audioDuration.value.inMilliseconds > 0) { audioProgressValue.value = (duration.inMilliseconds / audioDuration.value.inMilliseconds) .clamp(0.0, sliderMax); } }); } void _dealTalk(TalkBean? bean) async { debugPrint('talkBean == $bean'); String? id = bean?.id; if (id == null) { return; } _loadAudioFile(bean); if (bean?.status.value == TalkStatus.notAnalysis) { setUploadingProgress(id); } if (bean?.status.value == TalkStatus.notAnalysis && talkRepository.isUploadingTalk(id)) { isUploading.value = true; } else { isUploading.value = false; } } void setUploadingProgress(String id) { talkRepository.getUploadProgress(id).listen((progress) { uploadProgress.value = (progress * 20).toFormattedDouble(1); }); } Future _loadAudioFile(TalkBean? bean, {bool? loadPlay}) async { try { Uri? uri; if (bean?.isExample == true && bean?.audioUrl != null) { uri = Uri.parse(bean!.audioUrl!); } else { File? file = await getFileByTalk(talkBean.value); if (file?.existsSync() == true) { uri = file?.uri; } } if (uri == null) { throw '音频文件不存在'; } await _audioPlayer.setAudioSource(AudioSource.uri(uri)); if (loadPlay == true) { clickPlayAudio(); } audioFileIsExist = true; } catch (e) { audioFileIsExist = false; debugPrint('音频设置异常 == $e'); } } void _getArguments() { TalkBean? bean = parameters?[argumentItem]; if (bean != null) { talkBean.value = bean; debugPrint('talkBean == ${bean.summary}'); _dealTalk(bean); } else { paramId = parameters?[argumentTalkId]; if (paramId != null) { talkRepository.talkInfo(paramId!).then((data) { talkBean.value = data.talkInfo; _dealTalk(data.talkInfo); }).catchError((error) { ErrorHandler.toastError(error); }); } } eventTag = parameters?[argumentEventTag]; } void updateProgress(double value) { final newPosition = Duration( milliseconds: (value * audioDuration.value.inMilliseconds).toInt()); _audioPlayer.seek(newPosition); } void clickPlayAudio() async { if (audioFileIsExist != true && isLocalFileHas == false) { ToastUtil.showToast(StringName.talkFileNotFind.tr); return; } if (isLocalFileHas == true && audioFileIsExist == false && !await AudioPickerUtils.hasPermission()) { bool has = await AudioPickerUtils.requestPermissionExtend(); if (has == false) { ToastUtil.showToast(StringName.authorizationFailed.tr); return; } //重新加载 _loadAudioFile(talkBean.value, loadPlay: true); return; } if (isAudioLoading) { ToastUtil.showToast(StringName.talkAudioLoading.tr); return; } if (_audioPlayer.playing) { _audioPlayer.pause(); isAudioPlaying.value = false; } else { _audioPlayer.play(); isAudioPlaying.value = true; } } void _checkFileSizeAndNet() async { String? id = talkBean.value?.id; if (id == null) { return; } File? file = await getFileByTalk(talkBean.value); if (isLocalFileHas == true && audioFileIsExist == false && !await AudioPickerUtils.hasPermission()) { bool has = await AudioPickerUtils.requestPermissionExtend(); if (has == false) { ToastUtil.showToast(StringName.authorizationFailed.tr); return; } //重新上传 _checkFileSizeAndNet(); return; } if (file == null || !file.existsSync()) { ToastUtil.showToast(StringName.talkUploadFileNotExist.tr); return; } bool isCheckRemind = KVUtil.getBool(uploadNoPrompts, false); if (isCheckRemind) { _requestAnalyze(file); return; } //如果文件大小低于250MB 不弹窗提醒 if (file.lengthSync() < 250 * 1024 * 1024) { _requestAnalyze(file); return; } final List connectivityResult = await (Connectivity().checkConnectivity()); if (connectivityResult.contains(ConnectivityResult.wifi)) { _requestAnalyze(file); } else { _showTrafficRemindDialog(file.lengthSync().toReadableSize(), confirmOnTap: (isCheckRemind) { if (isCheckRemind) { KVUtil.putBool(uploadNoPrompts, true); } _requestAnalyze(file); }); } } void _showTrafficRemindDialog(String holderTxt, {void Function(bool isCheckRemind)? confirmOnTap}) { final remindTrafficConsume = false.obs; Widget getSelectIcon() { return Obx(() { return remindTrafficConsume.value ? Assets.images.iconSelectTrue.image() : Assets.images.iconSelectFalse.image(); }); } Assets.images.iconSelectTrue.image(); EAAlertDialog.show( contentWidget: Column( children: [ Text( StringName.talkTrafficRemindTitle.tr .replacePlaceholders([holderTxt]), style: TextStyle(fontSize: 15.sp, color: ColorName.primaryTextColor), ), SizedBox(height: 8.h), GestureDetector( onTap: () { remindTrafficConsume.value = !remindTrafficConsume.value; }, child: IntrinsicWidth( child: Row( children: [ SizedBox(width: 20.w, height: 20.w, child: getSelectIcon()), SizedBox(width: 5.w), Text( StringName.talkTrafficRemindTips.tr, style: TextStyle( fontSize: 15.sp, color: ColorName.tertiaryTextColor), ) ], ), ), ) ], ), cancelText: StringName.cancel.tr, confirmText: StringName.sure.tr, confirmOnTap: () { confirmOnTap?.call(remindTrafficConsume.value); }); } void checkCanAnalyze() { String? id = talkBean.value?.id; double? duration = talkBean.value?.duration; if (id == null || duration == null) { return; } eventReport(EventId.event_101002); talkRepository.checkElectric(duration).then((data) { if (data.enough) { //检查网络以及文件大小 _checkFileSizeAndNet(); } else { ToastUtil.showToast(StringName.talkAnalyseLowToast.tr); isShowElectricLow.value = true; } }).catchError((error) { ErrorHandler.toastError(error); }); } void _requestAnalyze(File file) { String? talkId = talkBean.value?.id; double? duration = talkBean.value?.duration; if (talkId == null || duration == null || isUploadedFile == true) { return; } isUploading.value = true; WakelockPlus.enable(); talkRepository.uploadTalkFile(talkId, duration, file).then((taskId) { isUploadedFile = true; isUploading.value = false; talkBean.value?.progressContent.value = StringName.talkUploadingFileTip.tr; talkBean.value?.progress.value = 20; talkBean.value?.status.value = TalkStatus.analysing; taskRepository.addTask(taskId); }).catchError((error) { isUploading.value = false; ErrorHandler.toastError(error); }).whenComplete(() => WakelockPlus.disable()); } void refreshAgendaAllData({bool isForceRefresh = false}) { String? id = talkBean.value?.id; if (id == null || (!isForceRefresh && agendaAllList.isNotEmpty)) { return; } agendaRepository.agendaListAll(id).then((agenda) { isFirstRequestTask = false; agendaAllList.clear(); agendaOriginalAllList.clear(); if (agenda.list != null) { agendaOriginalAllList.addAll( agenda.list!.map((item) => AgendaListAllBean.from(item)).toList()); agendaAllList.addAll(agenda.list!); } }); } void clickAIAnalysis() async { if (!await checkLogin()) { return; } if (talkBean.value != null) { eventReport(EventId.event_101003); ChatPage.startByTalk( talkBean.value!.isExample == true ? ChatFromType.fromTalkExample : ChatFromType.fromTalkDetail, talkBean.value!); } } void onGoElectricStore() { StorePage.start(fromType: StoreFromType.analyse); Future.delayed(const Duration(milliseconds: 250), () { isShowElectricLow.value = false; }); } void onEditModelClick() async { if (!await checkLogin()) { return; } _isEditModel.value = true; if (_audioPlayer.playing) { _audioPlayer.pause(); isAudioPlaying.value = false; } } void onSearchClick() { isSearchModel.value = true; } void updateTabIndex(int index) { checkTabBean.value = tabBeans[index]; } void onEditCancel() { _isEditModel.value = false; agendaAllList.assignAll(agendaOriginalAllList .map((item) => AgendaListAllBean.from(item)) .toList()); } void onSearchCancel() { isSearchModel.value = false; searchPrint.value = ''; searchResultDesc.value = '0/0'; } void onEditDoneClick() { if (talkBean.value == null) { return; } List list = []; for (AgendaListAllBean item in agendaAllList) { if (item.list != null) { for (Agenda agenda in item.list!) { list.add(AgendaUpdateBean(agenda.id, agenda.name, agenda.content)); } } } agendaRepository.agendaUpdate(talkBean.value!.id, list).then((data) { refreshAgendaAllData(isForceRefresh: true); eventBus.emit(TodoController.refreshTalkMineTask); isEditModelRx.value = false; }).catchError((error) { ErrorHandler.toastError(error); }); } void removeTalkAgenda(List? list, Agenda agenda) { list?.remove(agenda); agendaAllList.refresh(); } void showSingleAddAgendaDialog(BuildContext context) { showAddAgendaDialog(context, agendaContentController, agendaNameController, list: agendaAllList.map((e) => e.name ?? "").toList(), callback: () { if (agendaContentController.text.isEmpty) { ToastUtil.showToast(StringName.talkAddAgendaContentHint.tr); return; } if (agendaNameController.text.isEmpty) { ToastUtil.showToast(StringName.talkAddAgendaNameHint.tr); return; } Get.back(); _dealAddProcedureList(); }); } void _dealAddProcedureList() { String name = agendaNameController.text; final addItem = Agenda( id: "", talkId: "", name: name, ); addItem.content = agendaContentController.text; for (AgendaListAllBean item in agendaAllList) { if (item.name == name) { List list = item.list ?? []; list.add(addItem); item.list = list; agendaAllList.refresh(); agendaContentController.clear(); agendaNameController.clear(); return; } } agendaAllList.add(AgendaListAllBean(name: name, list: [addItem])); agendaContentController.clear(); agendaNameController.clear(); } Future getFileByTalk(TalkBean? bean) async { isLocalFileHas = false; if (bean == null) { return null; } if (bean.uploadType == TalkUploadType.localUpload) { String? audioId = FileUploadCheckHelper.getLocalAudioId(bean.localAudioUrl); if (audioId != null && audioId.isNotEmpty) { isLocalFileHas = true; return await AudioPickerUtils.getAssetFile(audioId); } else { return await FileUploadCheckHelper.getChoiceUploadFile(bean.id); } } else { return await RecordHandler.getRecordFile(bean.id); } } Future checkLogin() async { if (!accountRepository.isLogin.value) { bool isLogin = await LoginPage.start(fromType: LoginFromType.talkDetail); if (isLogin) { backToSpecificPage(RoutePath.mainTab); } return false; } return true; } List _getShareToType(bool isShowMindMap) { List shareToType = [ShareTalkType.summary]; if (isShowMindMap) { shareToType.add(ShareTalkType.mindMap); } shareToType.add(ShareTalkType.original); return shareToType; } void onShareClick() async { if (!await checkLogin()) { return; } if (talkBean.value?.status.value != TalkStatus.analysisSuccess) { return; } eventReport(EventId.event_101004); showTalkShareDialog(talkBean.value?.title.value, shareToType: _getShareToType(isShowMindMap.value), callback: (type, shareTo, fileName, tag) async { try { await isInstalled(shareTo); if (type == ShareTalkType.summary || type == ShareTalkType.original) { _shareSummaryOrOriginal( talkBean.value!.id, fileName, type, shareTo, tag); } else if (type == ShareTalkType.mindMap) { _shareMindMap(fileName, talkBean.value?.summary.value, shareTo, tag); } } catch (error) { if (error is SystemShareException) { ToastUtil.showToast(error.message); } else { ErrorHandler.toastError(error); } } }); } Future isInstalled(ShareTo shareTo) async { if (shareTo == ShareTo.wechat) { bool isInstalled = await SystemShareUtil.isInstalled(SystemShareUtil.wechatPageName); if (!isInstalled) { throw SystemShareException('未安装微信'); } } else if (shareTo == ShareTo.qq) { bool isInstalled = await SystemShareUtil.isInstalled(SystemShareUtil.qqPageName); if (!isInstalled) { throw SystemShareException('未安装QQ'); } } // else if(shareTo == ShareTo.ios){ // //ios不用判断 // } return true; } void _shareMindMap( String title, String? summary, ShareTo shareTo, String tag) { LoadingDialog.show(StringName.mindMapExport.tr, backDismiss: true); if (_temporaryController.value != null) { _temporaryController.value?.dispose(); _temporaryController.value = null; } final temporaryController = MindUtil.createMindWebViewController(); VoidCallback? errorCallback = () { LoadingDialog.hide(); temporaryController.dispose(); ToastUtil.showToast('思维导图导出失败'); }; try { Future.delayed(const Duration(seconds: 10), () { throw Exception('导出超时'); }); _temporaryController.value = temporaryController; temporaryController.loadFlutterAsset(Assets.html.indexExport); temporaryController.setNavigationDelegate( NavigationDelegate( onHttpError: (error) { errorCallback?.call(); errorCallback = null; }, // onWebResourceError: (error) { // errorCallback?.call(); // errorCallback = null; // }, onPageFinished: (String url) { temporaryController.callHandler(MindUtil.functionToJsExport, args: [title, summary], handler: (value) async { if (value == null) { throw Exception('data is null'); } File file = await MindUtil.saveToFile(value, title); temporaryController.dispose(); if (shareTo == ShareTo.wechat) { await SystemShareUtil.shareSystemFile( SystemShareUtil.wechatPageName, file.path, shareTitle: '分享到微信', shareFileType: 'image/*'); } else if (shareTo == ShareTo.qq) { await SystemShareUtil.shareSystemFile( SystemShareUtil.qqPageName, file.path, shareTitle: '分享到QQ', shareFileType: 'image/*'); } else if (shareTo == ShareTo.ios) { await Share.shareXFiles([XFile(file.path)], subject: title); } else { throw Exception('不支持该分享方式'); } SmartDialog.dismiss(tag: tag); LoadingDialog.hide(); }); }, ), ); } catch (e) { errorCallback?.call(); errorCallback = null; } } void _shareSummaryOrOriginal(String id, String fileName, ShareTalkType type, ShareTo shareTo, String tag) async { talkRepository.talkExport(id, fileName, type).then((file) async { if (shareTo == ShareTo.ios) { await Share.shareXFiles([XFile(file.path)], subject: fileName); } else if (shareTo == ShareTo.wechat) { await SystemShareUtil.shareSystemFile( SystemShareUtil.wechatPageName, file.path, shareTitle: '分享到微信', shareFileType: 'text/*'); } else if (shareTo == ShareTo.qq) { await SystemShareUtil.shareSystemFile( SystemShareUtil.qqPageName, file.path, shareTitle: '分享到QQ', shareFileType: 'text/*'); } SmartDialog.dismiss(tag: tag); }).catchError((error) { throw error; }); } void seekTo(int? startMs) { if (startMs == null) { return; } _audioPlayer.seek(Duration(milliseconds: startMs)); } Future refreshTalkDetail() async { String? id = talkBean.value?.id; if (id == null) { return null; } return talkRepository.talkInfo(id).then((data) { var bean = data.talkInfo; if (bean != null) { if (talkBean.value == null) { talkBean.value = data.talkInfo; } else { talkBean.value?.updateBean(bean); } maxTemplateCount = data.maxTemplateCount; templateSelectId.value = bean.templateId; } templateList.value = data.templateList; return bean; }); } void onEditTitleClick() { reNameDialog(StringName.talkRenameTitle.tr, talkBean.value?.title.value, hintTxt: StringName.talkRenameTitleHint.tr, maxLength: 15, returnBuilder: (newName) { talkRepository.talkRename(talkBean.value!.id, newName).then((data) { talkBean.value?.title.value = newName; }).catchError((error) { ErrorHandler.toastError(error); }); }); } void onExitMindFullScreen() { isShowMindFullScreen.value = false; } void selectTemplate(TemplateBean bean) { String? id = talkBean.value?.id; int? templateId = bean.id; if (talkBean.value?.templateId == templateId) { return; } if (id == null || templateId == null) { ToastUtil.showToast('谈话信息获取异常,请退出页面重试!'); return; } LoadingDialog.show('生成总结中...'); talkRepository .talkSummaryGenerate(id, templateId) .timeout(const Duration(seconds: 60)) .then((data) { LoadingDialog.hide(); talkBean.value?.updateBean(data); templateSelectId.value = templateId; ToastUtil.showToast('生成成功', displayType: SmartToastType.last); }).catchError((error) { LoadingDialog.hide(); ToastUtil.showToast('生成失败'); }); } void setSearchChangeTxt(String value) { searchPrint.value = value; } void updateSearchPositionDesc(int now, int total) { searchResultDesc.value = '$now/$total'; } void onSearchPrevious() { searchOperationCallback.value = Pair(checkTabBean.value?.type, SearchOperationType.previous); } void onSearchNext() { searchOperationCallback.value = Pair(checkTabBean.value?.type, SearchOperationType.next); } @override void onClose() { super.onClose(); _talkUploadListener?.cancel(); _talkBeanListener?.cancel(); _audioPlayer.dispose(); _agendaContentController?.dispose(); _agendaNameController?.dispose(); } } enum SearchOperationType { previous, next } enum TalkBarType { summary, mindMap, myTask, original } class TalkBarBean { final TalkBarType type; final String title; final bool? isShowEdit; final bool? isDisallowScroll; final bool? isShowSearch; TalkBarBean(this.type, this.title, {this.isShowEdit, this.isShowSearch, this.isDisallowScroll}); }