Browse Source

[new]增加待办编辑功能

zk 1 year ago
parent
commit
26da892463

BIN
assets/images/icon_talk_user.webp


+ 10 - 3
assets/string/base/string.xml

@@ -42,7 +42,8 @@
     <string name="talk_rename_title_hint">请输入谈话记录标题</string>
     <string name="talk_rename_success">修改成功</string>
     <string name="talk_rename_fail">修改失败</string>
-    <string name="talk_rename_delete_prompt">是否删除“%s”模板?该谈话包含您的待办事项,将一并删除。</string>
+    <string name="talk_rename_delete_prompt">是否删除“%s”模板?该谈话包含您的待办事项,将一并删除。
+    </string>
     <string name="talk_delete_success">删除成功</string>
     <string name="talk_delete_fail">删除失败</string>
     <string name="talk_tab_summary">谈话总结</string>
@@ -65,7 +66,8 @@
     <string name="record_status_pending">准备开始录音</string>
     <string name="record_status_recording">我正在听...</string>
     <string name="record_status_paused">录音已暂停</string>
-    <string name="talk_traffic_remind_title">您未在WIFI环境中,此次分析约消耗%s的流量,请问是否继续?</string>
+    <string name="talk_traffic_remind_title">您未在WIFI环境中,此次分析约消耗%s的流量,请问是否继续?
+    </string>
     <string name="talk_traffic_remind_tips">以后不再提示</string>
     <string name="talk_upload_file_not_exist">文件不存在</string>
     <string name="talk_audio_loading">音频正在加载中</string>
@@ -85,7 +87,8 @@
     <string name="load_failed">加载失败</string>
     <string name="talk_analysis_success">谈话分析已完成</string>
     <string name="talk_analysis_success_btn_txt">查看</string>
-    <string name="account_logout_tips">确定要注销此账号吗?一旦注销,账号信息将永久消失,无法恢复。</string>
+    <string name="account_logout_tips">确定要注销此账号吗?一旦注销,账号信息将永久消失,无法恢复。
+    </string>
     <string name="account_logout_success">注销成功</string>
     <string name="error_code_no_login">账号未登录</string>
     <string name="record_notification_channel_id">record</string>
@@ -105,4 +108,8 @@
     <string name="agenda_detail_popup_cancel">取消我的待办</string>
     <string name="agenda_detail_popup_update">编辑</string>
     <string name="talk_add_agenda">补充待办</string>
+    <string name="talk_add_agenda_project">新增待办</string>
+    <string name="talk_add_agenda_content_hint">请输入待办内容</string>
+    <string name="talk_add_agenda_name_hint">请输入待办人</string>
+    <string name="talk_add_agenda_name_title">负责人</string>
 </resources>

+ 1 - 1
lib/data/bean/agenda.dart

@@ -15,7 +15,7 @@ class Agenda {
   String? name;
 
   @JsonKey(name: 'content')
-  Rx<String> _content = ''.obs;
+  final Rx<String> _content = ''.obs;
 
   @JsonKey(name: 'createTime')
   String? createTime;

+ 7 - 0
lib/data/bean/agenda_list_all_bean.dart

@@ -18,4 +18,11 @@ class AgendaListAllBean {
 
   factory AgendaListAllBean.fromJson(Map<String, dynamic> json) =>
       _$AgendaListAllBeanFromJson(json);
+
+  factory AgendaListAllBean.from(AgendaListAllBean original) {
+    return AgendaListAllBean(
+      name: original.name,
+      list: original.list?.map((agenda) => agenda).toList(),
+    );
+  }
 }

+ 5 - 1
lib/data/repositories/agenda_repository.dart

@@ -89,7 +89,11 @@ class AgendaRepository {
   Future<void> agendaUpdate(String talkId, List<AgendaUpdateBean> list) {
     return atmobApi
         .agendaUpdate(AgendaUpdateRequest(talkId, list))
-        .then(HttpHandler.handle(true));
+        .then(HttpHandler.handle(true))
+        .then((data) {
+      requestHomeAgendaData();
+      return data;
+    });
   }
 
   Future<void> agendaTodo(String id, bool isTodo) async {

+ 230 - 0
lib/dialog/add_agenda_dialog.dart

@@ -0,0 +1,230 @@
+import 'package:electronic_assistant/resource/assets.gen.dart';
+import 'package:electronic_assistant/utils/expand.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter_screenutil/flutter_screenutil.dart';
+import 'package:get/get.dart';
+import 'package:get/get_core/src/get_main.dart';
+import '../resource/colors.gen.dart';
+import '../resource/string.gen.dart';
+
+void showAddAgendaDialog(
+    BuildContext context,
+    TextEditingController agendaContentController,
+    TextEditingController agendaNameController,
+    {List<String>? list,
+    void Function()? callback}) {
+  final etContentTxt = agendaContentController.text.obs;
+  final etNameTxt = agendaNameController.text.obs;
+  agendaContentController.addListener(() {
+    etContentTxt.value = agendaContentController.text;
+  });
+  agendaNameController.addListener(() {
+    etNameTxt.value = agendaNameController.text;
+  });
+
+  showModalBottomSheet(
+    context: context,
+    enableDrag: false,
+    isScrollControlled: true,
+    backgroundColor: ColorName.transparent,
+    builder: (BuildContext context) {
+      return Padding(
+        padding: EdgeInsets.only(
+          bottom: MediaQuery.of(context).viewInsets.bottom,
+        ),
+        child: Container(
+          decoration: BoxDecoration(
+            borderRadius: BorderRadius.only(
+                topLeft: Radius.circular(12.w),
+                topRight: Radius.circular(12.w)),
+            color: "#FFFFFF".toColor(),
+          ),
+          child: IntrinsicHeight(
+            child: Column(
+              crossAxisAlignment: CrossAxisAlignment.start,
+              children: [
+                SizedBox(height: 18.h),
+                Row(
+                  children: [
+                    GestureDetector(
+                      onTap: () {
+                        Get.back();
+                      },
+                      child: Container(
+                        color: Colors.transparent,
+                        margin: EdgeInsets.only(left: 16.w),
+                        padding: EdgeInsets.symmetric(horizontal: 8.w),
+                        child: Text(StringName.cancel.tr,
+                            style: TextStyle(
+                                color: ColorName.secondaryTextColor,
+                                fontSize: 14.sp)),
+                      ),
+                    ),
+                    const Spacer(),
+                    Text(StringName.talkAddAgendaProject.tr,
+                        style: TextStyle(
+                            color: ColorName.primaryTextColor,
+                            fontSize: 15.sp)),
+                    const Spacer(),
+                    GestureDetector(
+                      onTap: () {
+                        callback?.call();
+                      },
+                      child: Container(
+                        color: Colors.transparent,
+                        margin: EdgeInsets.only(right: 16.w),
+                        padding: EdgeInsets.symmetric(horizontal: 8.w),
+                        child: Obx(() {
+                          return Text(StringName.done.tr,
+                              style: TextStyle(
+                                  color: etContentTxt.isNotEmpty &&
+                                          etNameTxt.isNotEmpty
+                                      ? ColorName.colorPrimary
+                                      : ColorName.tertiaryTextColor,
+                                  fontSize: 15.sp));
+                        }),
+                      ),
+                    ),
+                  ],
+                ),
+                SizedBox(height: 24.h),
+                Container(
+                  margin: EdgeInsets.symmetric(horizontal: 16.w),
+                  decoration: BoxDecoration(
+                    color: "#F6F5F8".toColor(),
+                    borderRadius: BorderRadius.circular(8),
+                  ),
+                  height: 120.h,
+                  child: TextField(
+                    maxLines: null,
+                    maxLength: 200,
+                    cursorColor: ColorName.colorPrimary,
+                    style: TextStyle(
+                        fontSize: 15.sp, color: ColorName.primaryTextColor),
+                    decoration: InputDecoration(
+                      counterText: '',
+                      border: InputBorder.none,
+                      fillColor: Colors.transparent,
+                      hintText: StringName.talkAddAgendaContentHint.tr,
+                      hintStyle: TextStyle(
+                          fontSize: 15.sp, color: ColorName.tertiaryTextColor),
+                      contentPadding: const EdgeInsets.all(12).w,
+                    ),
+                    controller: agendaContentController,
+                  ),
+                ),
+                SizedBox(height: 16.h),
+                Padding(
+                  padding: EdgeInsets.only(left: 16.w),
+                  child: Text(StringName.talkAddAgendaNameTitle.tr,
+                      style: TextStyle(
+                          fontSize: 14.sp,
+                          color: ColorName.secondaryTextColor)),
+                ),
+                SizedBox(height: 8.h),
+                Container(
+                  margin: EdgeInsets.symmetric(horizontal: 16.w),
+                  decoration: BoxDecoration(
+                    color: "#F6F5F8".toColor(),
+                    borderRadius: BorderRadius.circular(8),
+                  ),
+                  height: 44.h,
+                  child: Row(
+                    children: [
+                      Expanded(
+                        child: TextField(
+                          maxLines: 1,
+                          maxLength: 15,
+                          cursorColor: ColorName.colorPrimary,
+                          style: TextStyle(
+                              fontSize: 15.sp,
+                              color: ColorName.primaryTextColor),
+                          decoration: InputDecoration(
+                            counterText: '',
+                            border: InputBorder.none,
+                            fillColor: Colors.transparent,
+                            hintText: StringName.talkAddAgendaNameHint.tr,
+                            hintStyle: TextStyle(
+                                fontSize: 15.sp,
+                                color: ColorName.tertiaryTextColor),
+                            contentPadding: const EdgeInsets.all(12).w,
+                          ),
+                          controller: agendaNameController,
+                        ),
+                      ),
+                      Obx(() {
+                        return Visibility(
+                          visible: etNameTxt.isNotEmpty,
+                          child: GestureDetector(
+                            onTap: () {
+                              agendaNameController.clear();
+                            },
+                            child: Container(
+                                margin: EdgeInsets.only(right: 12.w),
+                                width: 20.w,
+                                height: 20.w,
+                                child:
+                                    Assets.images.iconRenameClearTxt.image()),
+                          ),
+                        );
+                      })
+                    ],
+                  ),
+                ),
+                SizedBox(height: 12.h),
+                _buildAgendaList(list, itemClick: (item) {
+                  agendaNameController.text = item;
+                }),
+                SizedBox(height: 16.h),
+              ],
+            ),
+          ),
+        ),
+      );
+    },
+  );
+}
+
+Widget _buildAgendaList(List<String>? list,
+    {void Function(String item)? itemClick}) {
+  if (list == null || list.isEmpty) {
+    return Container();
+  }
+  return SizedBox(
+    height: 32.h,
+    child: ListView(
+        padding: EdgeInsets.only(left: 16.w),
+        scrollDirection: Axis.horizontal,
+        children: [
+          for (var item in list)
+            GestureDetector(
+              onTap: () {
+                itemClick?.call(item);
+              },
+              child: Container(
+                margin: EdgeInsets.only(right: 12.w),
+                decoration: BoxDecoration(
+                  color: "#F6F5F8".toColor(),
+                  borderRadius: BorderRadius.circular(16),
+                ),
+                padding: EdgeInsets.symmetric(horizontal: 12.w),
+                height: double.infinity,
+                child: Row(
+                  children: [
+                    SizedBox(
+                        width: 16.w,
+                        height: 16.w,
+                        child: Assets.images.iconTalkUser.image()),
+                    SizedBox(width: 2.w),
+                    Text(
+                      item,
+                      style: TextStyle(
+                          fontSize: 14.sp, color: ColorName.primaryTextColor),
+                    )
+                  ],
+                ),
+              ),
+            ),
+        ]),
+  );
+}

+ 2 - 2
lib/dialog/edit_agenda_dialog.dart

@@ -10,7 +10,7 @@ typedef EditAgendaCallback = void Function(String content);
 void showEditAgendaDialog(
     BuildContext context, TextEditingController etFieldController,
     {String? hintTxt, EditAgendaCallback? callback}) {
-  final etPrintTxt = ''.obs;
+  final etPrintTxt = etFieldController.text.obs;
 
   etFieldController.addListener(() {
     etPrintTxt.value = etFieldController.text;
@@ -34,7 +34,7 @@ void showEditAgendaDialog(
           ),
           child: IntrinsicHeight(
             child: Column(
-              mainAxisSize: MainAxisSize.min, // 使弹窗高度自适应内容
+              mainAxisSize: MainAxisSize.min,
               children: [
                 Row(
                   children: [

+ 1 - 1
lib/module/agenda/detail/controller.dart

@@ -70,7 +70,7 @@ class AgendaDetailController extends BaseController {
       return;
     }
     agendaRepository.agendaUpdate(detailBean.value!.talkId, [
-      AgendaUpdateBean(detailBean.value!.id, null, newContent)
+      AgendaUpdateBean(detailBean.value!.id, detailBean.value!.name, newContent)
     ]).then((data) {
       detailBean.value!.content = newContent;
       etFieldController.clear();

+ 18 - 15
lib/module/home/view.dart

@@ -657,21 +657,24 @@ class HomePage extends BasePage<HomePageController> {
   }
 }
 
-Widget buildAgendaEmptyView(double top) {
-  return Container(
-    width: double.infinity,
-    padding: EdgeInsets.symmetric(vertical: top),
-    child: Column(
-      children: [
-        SizedBox(
-            width: 100.w,
-            height: 100.w,
-            child: Assets.images.iconNoTask.image()),
-        SizedBox(height: 4.h),
-        Text(StringName.agendaNoData.tr,
-            style: TextStyle(
-                color: ColorName.secondaryTextColor, fontSize: 14.sp)),
-      ],
+Widget buildAgendaEmptyView(double top, {bool isVisible = true}) {
+  return Visibility(
+    visible: isVisible,
+    child: Container(
+      width: double.infinity,
+      padding: EdgeInsets.symmetric(vertical: top),
+      child: Column(
+        children: [
+          SizedBox(
+              width: 100.w,
+              height: 100.w,
+              child: Assets.images.iconNoTask.image()),
+          SizedBox(height: 4.h),
+          Text(StringName.agendaNoData.tr,
+              style: TextStyle(
+                  color: ColorName.secondaryTextColor, fontSize: 14.sp)),
+        ],
+      ),
     ),
   );
 }

+ 2 - 2
lib/module/record/controller.dart

@@ -287,8 +287,8 @@ class RecordController extends BaseController {
     } else {
       return FlutterForegroundTask.startService(
         serviceId: 256,
-        notificationTitle: StringName.appName,
-        notificationText: StringName.recordStatusRecording,
+        notificationTitle: StringName.appName.tr,
+        notificationText: StringName.recordStatusRecording.tr,
         notificationIcon: null,
         notificationButtons: [],
         callback: setRecordCallback,

+ 27 - 0
lib/module/talk/common_view.dart

@@ -10,6 +10,33 @@ import '../../resource/assets.gen.dart';
 import '../../resource/colors.gen.dart';
 import '../../resource/string.gen.dart';
 
+Widget getAddAgendaView(String addTxt, {VoidCallback? onClick}) {
+  return GestureDetector(
+    onTap: onClick,
+    child: Container(
+      decoration: BoxDecoration(
+          color: "#F6F5F8".toColor(),
+          border: Border.all(color: '#EAE5EF'.toColor(), width: 1),
+          borderRadius: BorderRadius.circular(8.w)),
+      margin: EdgeInsets.only(bottom: 8.h, top: 6.h),
+      padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 11.w),
+      child: Row(
+        children: [
+          SizedBox(
+              width: 22.w,
+              height: 22.w,
+              child: Assets.images.iconTalkAddAdenda.image()),
+          SizedBox(width: 8.w),
+          Text(
+            addTxt,
+            style: TextStyle(fontSize: 14.sp, color: ColorName.colorPrimary),
+          )
+        ],
+      ),
+    ),
+  );
+}
+
 Widget getTalkUploadingView() {
   return SizedBox(
     width: double.infinity,

+ 113 - 11
lib/module/talk/controller.dart

@@ -6,6 +6,7 @@ import 'package:electronic_assistant/data/repositories/task_repository.dart';
 import 'package:electronic_assistant/module/chat/view.dart';
 import 'package:electronic_assistant/module/home/controller.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';
@@ -18,12 +19,16 @@ import 'package:flutter/material.dart';
 import 'package:flutter_screenutil/flutter_screenutil.dart';
 import 'package:get/get.dart';
 import 'package:connectivity_plus/connectivity_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/talks.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 '../../router/app_pages.dart';
+import '../../utils/event_bus.dart';
 import '../../utils/toast_util.dart';
 import '../record/controller.dart';
 import 'original/view.dart';
@@ -58,6 +63,8 @@ class TalkController extends BaseController {
 
   final _isEditModel = false.obs;
 
+  final TextEditingController editTalkNameController = TextEditingController();
+
   final tabIndex = 0.obs;
 
   final List<String> tabBeans = [
@@ -76,6 +83,19 @@ class TalkController extends BaseController {
 
   final pages = [const SummaryView(), const TodoView(), const OriginalView()];
 
+  TextEditingController? _agendaContentController;
+  TextEditingController? _agendaNameController;
+
+  TextEditingController get agendaContentController {
+    _agendaContentController ??= TextEditingController();
+    return _agendaContentController!;
+  }
+
+  TextEditingController get agendaNameController {
+    _agendaNameController ??= TextEditingController();
+    return _agendaNameController!;
+  }
+
   @override
   void onReady() {
     super.onReady();
@@ -322,8 +342,9 @@ class TalkController extends BaseController {
       agendaAllList.clear();
       agendaOriginalAllList.clear();
       if (agenda.list != null) {
-        agendaOriginalAllList.addAll(agenda.list!);
-        agendaAllList.value = agenda.list!;
+        agendaOriginalAllList.addAll(
+            agenda.list!.map((item) => AgendaListAllBean.from(item)).toList());
+        agendaAllList.addAll(agenda.list!);
       }
     });
   }
@@ -334,13 +355,6 @@ class TalkController extends BaseController {
     }
   }
 
-  @override
-  void onClose() {
-    super.onClose();
-    _talkBeanListener?.cancel();
-    _audioPlayer.dispose();
-  }
-
   void onGoElectricStore() {
     Get.toNamed(RoutePath.store);
     Future.delayed(const Duration(milliseconds: 250), () {
@@ -350,6 +364,11 @@ class TalkController extends BaseController {
 
   void onEditModelClick() {
     _isEditModel.value = true;
+    if (_audioPlayer.playing) {
+      _audioPlayer.pause();
+      isAudioPlaying.value = false;
+    }
+    editTalkNameController.text = talkBean.value?.title.value ?? '';
   }
 
   void updateTabIndex(int index) {
@@ -358,10 +377,93 @@ class TalkController extends BaseController {
 
   void onEditCancel() {
     _isEditModel.value = false;
-    agendaAllList.assignAll(agendaOriginalAllList);
+    agendaAllList.assignAll(agendaOriginalAllList
+        .map((item) => AgendaListAllBean.from(item))
+        .toList());
+  }
+
+  void onEditDoneClick() {
+    if (talkBean.value == null) {
+      return;
+    }
+    List<AgendaUpdateBean> 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);
+    });
+    if (tabIndex.value == 0) {
+      String updateName = editTalkNameController.text;
+      talkRepository.talkRename(talkBean.value!.id, updateName).then((data) {
+        talkBean.value?.title.value = updateName;
+      }).catchError((error) {
+        ErrorHandler.toastError(error);
+      });
+    }
   }
 
-  void onEditDoneClick() {}
+  void removeTalkAgenda(List<Agenda>? 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<Agenda> 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();
+  }
+
+  @override
+  void onClose() {
+    super.onClose();
+    _talkBeanListener?.cancel();
+    _audioPlayer.dispose();
+    _agendaContentController?.dispose();
+    _agendaNameController?.dispose();
+  }
 }
 
 Future<File?> getFileByTalk(String? talkId, int? uploadType) async {

+ 5 - 2
lib/module/talk/summary/controller.dart

@@ -48,8 +48,11 @@ class SummaryController extends BaseController {
   }
 
   void removeTalkAgenda(List<Agenda>? list, Agenda agenda) {
-    list?.remove(agenda);
-    agendaAllList.refresh();
+    talkController.removeTalkAgenda(list, agenda);
+  }
+
+  void showAddAgendaDialog(BuildContext context) {
+    talkController.showSingleAddAgendaDialog(context);
   }
 
   @override

+ 9 - 25
lib/module/talk/summary/view.dart

@@ -10,6 +10,7 @@ import 'package:get/get.dart';
 import 'package:markdown/markdown.dart' as md;
 
 import '../../../data/bean/talks.dart';
+import '../../../dialog/add_agenda_dialog.dart';
 import '../../browser/view.dart';
 import '../../home/view.dart';
 import '../common_view.dart';
@@ -84,7 +85,8 @@ class SummaryView extends BasePage<SummaryController> {
   Widget buildAllTaskList() {
     return Obx(() {
       if (controller.agendaAllList.isEmpty) {
-        return buildAgendaEmptyView(65.h);
+        return buildAgendaEmptyView(65.h,
+            isVisible: controller.isEditModel == false);
       } else {
         return Column(
             children: controller.agendaAllList.map((item) {
@@ -134,30 +136,12 @@ class SummaryView extends BasePage<SummaryController> {
   Widget _buildAddTaskView() {
     return Obx(() {
       return Visibility(
-        visible: controller.isEditModel,
-        child: Container(
-          decoration: BoxDecoration(
-              color: "#F6F5F8".toColor(),
-              border: Border.all(color: '#EAE5EF'.toColor(), width: 1),
-              borderRadius: BorderRadius.circular(8.w)),
-          margin: EdgeInsets.only(bottom: 8.h, top: 6.h),
-          padding: EdgeInsets.symmetric(horizontal: 14.w, vertical: 11.w),
-          child: Row(
-            children: [
-              SizedBox(
-                  width: 22.w,
-                  height: 22.w,
-                  child: Assets.images.iconTalkAddAdenda.image()),
-              SizedBox(width: 8.w),
-              Text(
-                StringName.talkAddAgenda.tr,
-                style: TextStyle(
-                    fontSize: 14.sp, color: ColorName.primaryTextColor),
-              )
-            ],
-          ),
-        ),
-      );
+          visible: controller.isEditModel,
+          child: Builder(builder: (context) {
+            return getAddAgendaView(StringName.talkAddAgenda.tr, onClick: () {
+              controller.showAddAgendaDialog(context);
+            });
+          }));
     });
   }
 }

+ 28 - 6
lib/module/talk/todo/controller.dart

@@ -5,12 +5,16 @@ import 'package:electronic_assistant/data/bean/agenda.dart';
 import 'package:electronic_assistant/data/repositories/agenda_repository.dart';
 import 'package:electronic_assistant/module/chat/view.dart';
 import 'package:electronic_assistant/utils/error_handler.dart';
+import 'package:flutter/cupertino.dart';
 import 'package:get/get.dart';
 import '../../../data/bean/agenda_list_all_bean.dart';
 import '../../../data/bean/talks.dart';
+import '../../../utils/event_bus.dart';
 import '../controller.dart';
 
 class TodoController extends BaseController {
+  static String refreshTalkMineTask = "refreshTalkMineTask";
+
   final TalkController _talkController = Get.find();
 
   StreamSubscription? _talkBeanListener;
@@ -23,6 +27,8 @@ class TodoController extends BaseController {
 
   Rxn<TalkBean> get talkBean => _talkController.talkBean;
 
+  bool get isEditModel => _talkController.isEditModelRx.value;
+
   @override
   void onReady() {
     super.onReady();
@@ -30,6 +36,13 @@ class TodoController extends BaseController {
       _dealTalkUpdate(bean);
     });
     _dealTalkUpdate(_talkController.talkBean.value);
+    _eventRefresh();
+  }
+
+  void _eventRefresh() {
+    eventBus.on(refreshTalkMineTask, (data) {
+      requestMineTodoData();
+    });
   }
 
   void _dealTalkUpdate(TalkBean? bean) {
@@ -49,12 +62,6 @@ class TodoController extends BaseController {
     });
   }
 
-  @override
-  void onClose() {
-    super.onClose();
-    _talkBeanListener?.cancel();
-  }
-
   void agendaTodo(Agenda? agenda) {
     if (agenda == null) {
       return;
@@ -76,4 +83,19 @@ class TodoController extends BaseController {
       ChatPage.start();
     }
   }
+
+  void showAddAgendaDialog(BuildContext context) {
+    _talkController.showSingleAddAgendaDialog(context);
+  }
+
+  void removeTalkAgenda(List<Agenda>? list, Agenda agenda) {
+    _talkController.removeTalkAgenda(list, agenda);
+  }
+
+  @override
+  void onClose() {
+    super.onClose();
+    _talkBeanListener?.cancel();
+    eventBus.off(refreshTalkMineTask);
+  }
 }

+ 84 - 53
lib/module/talk/todo/view.dart

@@ -34,6 +34,7 @@ class TodoView extends BasePage<TodoController> {
               style: TextStyle(
                   fontSize: 14.sp, color: ColorName.secondaryTextColor)),
           SizedBox(height: 12.h),
+          _buildAddAgendaView(),
           buildAllTodoView(),
         ],
       ),
@@ -46,11 +47,18 @@ class TodoView extends BasePage<TodoController> {
           children: controller.agendaAllList.map((agenda) {
         return Padding(
           padding: EdgeInsets.only(bottom: 8.h),
-          child: getTodoItemView(
-              agenda,
-              (list) => getTalkAgendaSettingList(list, itemClick: (agenda) {
-                    controller.agendaTodo(agenda);
-                  })),
+          child: controller.isEditModel
+              ? getTodoItemView(
+                  agenda,
+                  (list) => getTalkAgendaEditModelList(list,
+                          removeCallback: (agenda) {
+                        controller.removeTalkAgenda(list, agenda);
+                      }))
+              : getTodoItemView(
+                  agenda,
+                  (list) => getTalkAgendaSettingList(list, itemClick: (agenda) {
+                        controller.agendaTodo(agenda);
+                      })),
         );
       }).toList());
     });
@@ -63,53 +71,57 @@ class TodoView extends BasePage<TodoController> {
           splashFactory: NoSplash.splashFactory,
         ),
         child: Obx(() {
-          return ExpansionTile(
-            onExpansionChanged: (value) {
-              controller.mineAgendaIsExpanded.value = value;
-            },
-            shape: RoundedRectangleBorder(
-              borderRadius: BorderRadius.circular(4.0),
-              side: const BorderSide(color: Colors.transparent),
-            ),
-            collapsedShape: RoundedRectangleBorder(
-              borderRadius: BorderRadius.circular(4.0),
-              side: const BorderSide(color: Colors.transparent),
-            ),
-            minTileHeight: 46.h,
-            showTrailingIcon: false,
-            childrenPadding: EdgeInsets.zero,
-            tilePadding: EdgeInsets.zero,
-            title: Row(
-              children: [
-                Text(StringName.talkTabMyTask.tr,
-                    style: TextStyle(
-                        fontSize: 14.sp, color: ColorName.secondaryTextColor)),
-                const Spacer(),
-                Obx(() {
-                  return Row(
-                    children: [
-                      Text(
-                        '${controller.agendaMineList.length}${StringName.talkTodoItem.tr}',
-                        style: TextStyle(
-                            fontSize: 15.sp,
-                            color: ColorName.secondaryTextColor),
-                      ),
-                      SizedBox(width: 3.w),
-                      SizedBox(
-                          width: 16.w,
-                          height: 16.w,
-                          child: controller.mineAgendaIsExpanded.value
-                              ? Assets.images.iconTalkExpand.image()
-                              : Assets.images.iconTalkCollapse.image()),
-                    ],
-                  );
-                }),
-                SizedBox(width: 12.w),
-              ],
+          return Visibility(
+            visible: !controller.isEditModel,
+            child: ExpansionTile(
+              onExpansionChanged: (value) {
+                controller.mineAgendaIsExpanded.value = value;
+              },
+              shape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(4.0),
+                side: const BorderSide(color: Colors.transparent),
+              ),
+              collapsedShape: RoundedRectangleBorder(
+                borderRadius: BorderRadius.circular(4.0),
+                side: const BorderSide(color: Colors.transparent),
+              ),
+              minTileHeight: 46.h,
+              showTrailingIcon: false,
+              childrenPadding: EdgeInsets.zero,
+              tilePadding: EdgeInsets.zero,
+              title: Row(
+                children: [
+                  Text(StringName.talkTabMyTask.tr,
+                      style: TextStyle(
+                          fontSize: 14.sp,
+                          color: ColorName.secondaryTextColor)),
+                  const Spacer(),
+                  Obx(() {
+                    return Row(
+                      children: [
+                        Text(
+                          '${controller.agendaMineList.length}${StringName.talkTodoItem.tr}',
+                          style: TextStyle(
+                              fontSize: 15.sp,
+                              color: ColorName.secondaryTextColor),
+                        ),
+                        SizedBox(width: 3.w),
+                        SizedBox(
+                            width: 16.w,
+                            height: 16.w,
+                            child: controller.mineAgendaIsExpanded.value
+                                ? Assets.images.iconTalkExpand.image()
+                                : Assets.images.iconTalkCollapse.image()),
+                      ],
+                    );
+                  }),
+                  SizedBox(width: 12.w),
+                ],
+              ),
+              children: controller.agendaMineList.map((agenda) {
+                return _buildMineItem(agenda);
+              }).toList(),
             ),
-            children: controller.agendaMineList.map((agenda) {
-              return _buildMineItem(agenda);
-            }).toList(),
           );
         }),
       );
@@ -165,7 +177,8 @@ class TodoView extends BasePage<TodoController> {
     } else if (controller.talkBean.value?.status == TalkStatus.analysing ||
         controller.talkBean.value?.status == TalkStatus.waitAnalysis) {
       return getTalkLoadingView();
-    } else if (controller.talkBean.value?.status == TalkStatus.analysisSuccess) {
+    } else if (controller.talkBean.value?.status ==
+        TalkStatus.analysisSuccess) {
       return _buildTodoContent();
     } else {
       return Container();
@@ -173,7 +186,7 @@ class TodoView extends BasePage<TodoController> {
   }
 
   Widget _buildTodoContent() {
-    if (controller.agendaAllList.isEmpty) {
+    if (controller.agendaAllList.isEmpty && !controller.isEditModel) {
       return buildAgendaEmptyView(110.h);
     }
     return ListView(
@@ -181,4 +194,22 @@ class TodoView extends BasePage<TodoController> {
       children: [_buildMineTodoList(), _buildAllTaskView()],
     );
   }
+
+  Widget _buildAddAgendaView() {
+    return Obx(() {
+      if (controller.isEditModel) {
+        return Container(
+          margin: EdgeInsets.only(bottom: 8.h),
+          child: Builder(builder: (context) {
+            return getAddAgendaView(StringName.talkAddAgendaProject.tr,
+                onClick: () {
+              controller.showAddAgendaDialog(context);
+            });
+          }),
+        );
+      } else {
+        return Container();
+      }
+    });
+  }
 }

+ 127 - 70
lib/module/talk/view.dart

@@ -51,35 +51,23 @@ class TalkPage extends BasePage<TalkController> {
                 return Column(
                   crossAxisAlignment: CrossAxisAlignment.start,
                   children: [
-                    Padding(
-                      padding: EdgeInsets.symmetric(horizontal: 12.w),
-                      child: Obx(() {
-                        return Column(
-                          crossAxisAlignment: CrossAxisAlignment.start,
-                          children: [
-                            SizedBox(height: 8.h),
-                            Text(controller.talkBean.value?.title.value ?? '',
-                                style: TextStyle(
-                                    fontSize: 22.sp,
-                                    fontWeight: FontWeight.bold,
-                                    color: ColorName.primaryTextColor)),
-                            SizedBox(height: 4.h),
-                            Text(controller.talkBean.value?.createTime ?? '',
-                                style: TextStyle(
-                                    fontSize: 12.sp,
-                                    color: ColorName.secondaryTextColor)),
-                            SizedBox(height: 14.h),
-                          ],
-                        );
-                      }),
-                    ),
+                    _buildHeaderView(),
                     buildTabBar(context),
-                    Divider(
-                        height: 1,
-                        color: const Color(0xFFf6f6f6),
-                        indent: 12.w,
-                        endIndent: 12.w),
-                    SizedBox(height: 8.h),
+                    Obx(() {
+                      return Visibility(
+                        visible: !controller.isEditModel,
+                        child: Divider(
+                            height: 1,
+                            color: const Color(0xFFf6f6f6),
+                            indent: 12.w,
+                            endIndent: 12.w),
+                      );
+                    }),
+                    Obx(() {
+                      return Visibility(
+                          visible: !controller.isEditModel,
+                          child: SizedBox(height: 8.h));
+                    }),
                     buildTalkContentView()
                   ],
                 );
@@ -93,6 +81,60 @@ class TalkPage extends BasePage<TalkController> {
     );
   }
 
+  Padding _buildHeaderView() {
+    return Padding(
+      padding: EdgeInsets.symmetric(horizontal: 12.w),
+      child: Obx(() {
+        return Column(
+          crossAxisAlignment: CrossAxisAlignment.start,
+          children: [
+            SizedBox(height: 8.h),
+            _buildTalkTitle(),
+            SizedBox(height: 4.h),
+            Text(controller.talkBean.value?.createTime ?? '',
+                style: TextStyle(
+                    fontSize: 12.sp, color: ColorName.secondaryTextColor)),
+            SizedBox(height: 14.h),
+          ],
+        );
+      }),
+    );
+  }
+
+  Widget _buildTalkTitle() {
+    if (!controller.isEditModel || controller.tabIndex.value == 1) {
+      return Text(controller.talkBean.value?.title.value ?? '',
+          style: TextStyle(
+              fontSize: 22.sp,
+              fontWeight: FontWeight.bold,
+              color: ColorName.primaryTextColor));
+    } else {
+      return Container(
+        decoration: BoxDecoration(
+          color: ColorName.white,
+          borderRadius: BorderRadius.circular(6.w),
+          border: Border.all(color: "#E7E9F6".toColor(), width: 1),
+        ),
+        child: TextField(
+            maxLines: null,
+            maxLength: 15,
+            decoration: InputDecoration(
+              counterText: '',
+              border: InputBorder.none,
+              fillColor: Colors.transparent,
+              contentPadding:
+                  EdgeInsets.symmetric(vertical: 6.w, horizontal: 8.w),
+            ),
+            style: TextStyle(
+                fontSize: 22.sp,
+                fontWeight: FontWeight.bold,
+                color: ColorName.primaryTextColor),
+            cursorColor: ColorName.primaryTextColor,
+            controller: controller.editTalkNameController),
+      );
+    }
+  }
+
   Container buildTabBar(BuildContext context) {
     TabController tabController = DefaultTabController.of(context);
     tabController.addListener(() {
@@ -105,19 +147,26 @@ class TalkPage extends BasePage<TalkController> {
             topLeft: Radius.circular(12),
             topRight: Radius.circular(12),
           )),
-      child: TabBar(
-          labelStyle: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold),
-          unselectedLabelStyle: TextStyle(fontSize: 14.sp),
-          labelColor: ColorName.primaryTextColor,
-          unselectedLabelColor: ColorName.secondaryTextColor,
-          labelPadding: EdgeInsets.only(top: 4.h),
-          dividerHeight: 0,
-          indicator: FixedSizeTabIndicator(
-              width: 16.w,
-              height: 3.w,
-              radius: 3,
-              color: ColorName.colorPrimary),
-          tabs: controller.tabBeans.map((txt) => Tab(text: txt)).toList()),
+      child: Obx(() {
+        if (!controller.isEditModel) {
+          return TabBar(
+              labelStyle:
+                  TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold),
+              unselectedLabelStyle: TextStyle(fontSize: 14.sp),
+              labelColor: ColorName.primaryTextColor,
+              unselectedLabelColor: ColorName.secondaryTextColor,
+              labelPadding: EdgeInsets.only(top: 4.h),
+              dividerHeight: 0,
+              indicator: FixedSizeTabIndicator(
+                  width: 16.w,
+                  height: 3.w,
+                  radius: 3,
+                  color: ColorName.colorPrimary),
+              tabs: controller.tabBeans.map((txt) => Tab(text: txt)).toList());
+        } else {
+          return SizedBox(height: 8.h, width: double.infinity);
+        }
+      }),
     );
   }
 
@@ -163,6 +212,9 @@ class TalkPage extends BasePage<TalkController> {
   Widget buildTabContentView() {
     return Expanded(
       child: TabBarView(
+        physics: controller.isEditModel
+            ? const NeverScrollableScrollPhysics()
+            : null,
         children: controller.pages,
       ),
     );
@@ -257,37 +309,42 @@ class TalkPage extends BasePage<TalkController> {
   }
 
   Widget buildBottomView() {
-    return Align(
-      alignment: Alignment.bottomCenter,
-      child: Container(
-        margin: EdgeInsets.only(bottom: 20.h), // 设置底部偏移距离
-        child: IntrinsicHeight(
-          child: Column(
-            crossAxisAlignment: CrossAxisAlignment.end,
-            children: [
-              Obx(() {
-                return Visibility(
-                  visible: controller.talkBean.value?.status.value ==
-                      TalkStatus.analysisSuccess,
-                  child: GestureDetector(
-                    onTap: () {
-                      controller.clickAIAnalysis();
-                    },
-                    child: Container(
-                        margin: EdgeInsets.only(right: 8.w),
-                        width: 64.w,
-                        height: 64.w,
-                        child: Assets.images.iconTalkLogo.image()),
-                  ),
-                );
-              }),
-              SizedBox(height: 24.h),
-              buildAudioView()
-            ],
+    return Obx(() {
+      return Visibility(
+        visible: controller.isEditModel == false,
+        child: Align(
+          alignment: Alignment.bottomCenter,
+          child: Container(
+            margin: EdgeInsets.only(bottom: 20.h), // 设置底部偏移距离
+            child: IntrinsicHeight(
+              child: Column(
+                crossAxisAlignment: CrossAxisAlignment.end,
+                children: [
+                  Obx(() {
+                    return Visibility(
+                      visible: controller.talkBean.value?.status.value ==
+                          TalkStatus.analysisSuccess,
+                      child: GestureDetector(
+                        onTap: () {
+                          controller.clickAIAnalysis();
+                        },
+                        child: Container(
+                            margin: EdgeInsets.only(right: 8.w),
+                            width: 64.w,
+                            height: 64.w,
+                            child: Assets.images.iconTalkLogo.image()),
+                      ),
+                    );
+                  }),
+                  SizedBox(height: 24.h),
+                  buildAudioView()
+                ],
+              ),
+            ),
           ),
         ),
-      ),
-    );
+      );
+    });
   }
 
   buildAIAnalysisView() {