From 4623094bad191ec2a973ac82fa07da15c947db9a Mon Sep 17 00:00:00 2001 From: zhutao <1812073942@qq.com> Date: Mon, 8 Sep 2025 15:30:09 +0800 Subject: [PATCH] 1 --- lib/api/dto/plan_detail_dto.dart | 4 +- lib/api/endpoints/plan_api.dart | 27 ++ lib/data/models/plan_acttion_type.dart | 10 + lib/page/home/widget/plan_form_card.dart | 2 +- .../plan/detail/navigation/bar_actions.dart | 80 ++++++ lib/page/plan/detail/plan_detail_page.dart | 67 +---- .../detail/viewmodel/plan_detail_store.dart | 25 +- .../plan/detail/widgets/coach_message.dart | 30 +-- lib/page/plan/detail/widgets/plan_list.dart | 254 +++++++++++------- lib/page/plan/detail/widgets/scroll_box.dart | 5 +- lib/page/plan/detail/widgets/suggested.dart | 91 ++++--- lib/page/plan/history/plan_history_page.dart | 14 - lib/widgets/business/delete_row_item.dart | 2 + pubspec.lock | 8 + pubspec.yaml | 1 + 15 files changed, 374 insertions(+), 246 deletions(-) create mode 100644 lib/data/models/plan_acttion_type.dart create mode 100644 lib/page/plan/detail/navigation/bar_actions.dart diff --git a/lib/api/dto/plan_detail_dto.dart b/lib/api/dto/plan_detail_dto.dart index 76defbd..cfa74b8 100644 --- a/lib/api/dto/plan_detail_dto.dart +++ b/lib/api/dto/plan_detail_dto.dart @@ -1,9 +1,9 @@ class PlanStepDto { - num? id; + int? id; String? stepIcon; String? stepContent; String? stepExplain; - num? stepStatus; + int? stepStatus; PlanStepDto({this.id, this.stepIcon, this.stepContent, this.stepExplain, this.stepStatus}); diff --git a/lib/api/endpoints/plan_api.dart b/lib/api/endpoints/plan_api.dart index 2cdb583..8bf2c96 100644 --- a/lib/api/endpoints/plan_api.dart +++ b/lib/api/endpoints/plan_api.dart @@ -2,6 +2,8 @@ import 'package:plan/api/dto/plan_detail_dto.dart'; import 'package:plan/api/dto/plan_item_dto.dart'; import 'package:plan/api/network/request.dart'; +import '../../data/models/plan_acttion_type.dart'; + ///初始化计划 Future initPlanApi(String need, int agentId) async { var res = await Request().post("/plan/init", { @@ -56,3 +58,28 @@ Future deletePlanApi(int planId) async { "plan_id": planId, }); } + +///编辑用户计划步骤 +Future editPlanStepApi( + int planId, { + required PlanActionType act, + int? stepId, + String? content, + String? explain, +}) async { + await Request().post("/plan/edit_plan_steps_info", { + "plan_id": planId, + "act": act.value, + "step_id": stepId, + "step_content": content, + "step_explain": explain, + }); +} + +///修改步骤顺序 +Future editPlanStepOrderApi(int planId,List list) async { + await Request().post("/plan/change_plan_steps", { + "plan_id": planId, + "steps": list.map((e) => e.toJson()).toList(), + }); +} diff --git a/lib/data/models/plan_acttion_type.dart b/lib/data/models/plan_acttion_type.dart new file mode 100644 index 0000000..5e493f5 --- /dev/null +++ b/lib/data/models/plan_acttion_type.dart @@ -0,0 +1,10 @@ +enum PlanActionType { + delete(1), //删除 + complete(2), //完成 + edit(3), //编辑 + completeAll(99); //全部完成 + + final int value; + + const PlanActionType(this.value); +} diff --git a/lib/page/home/widget/plan_form_card.dart b/lib/page/home/widget/plan_form_card.dart index 5fa893c..8bd1969 100644 --- a/lib/page/home/widget/plan_form_card.dart +++ b/lib/page/home/widget/plan_form_card.dart @@ -12,7 +12,7 @@ class PlanFormCard extends StatefulWidget { } class _PlanFormCardState extends State { - final TextEditingController _inputController = TextEditingController(text: ""); + final TextEditingController _inputController = TextEditingController(text: "刷牙"); void _handSubmit() { if (_inputController.text.isEmpty) { diff --git a/lib/page/plan/detail/navigation/bar_actions.dart b/lib/page/plan/detail/navigation/bar_actions.dart new file mode 100644 index 0000000..2a122ac --- /dev/null +++ b/lib/page/plan/detail/navigation/bar_actions.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:plan/api/endpoints/plan_api.dart'; +import 'package:plan/widgets/ui_kit/popup/popup_action.dart'; +import 'package:remixicon/remixicon.dart'; + +import '../../widgets/edit_desc_dialog.dart'; +import '../viewmodel/plan_detail_store.dart'; + +class BarActions extends StatefulWidget { + final PlanDetailStore store; + + const BarActions({super.key, required this.store}); + + @override + State createState() => _BarActionsState(); +} + +class _BarActionsState extends State { + ///popup菜单 + void _onPopupActionSelected(String value) { + if (value == 'edit_step') { + widget.store.setEdit(true); + } else if (value == 'edit_desc') { + showEditDescDialog( + context, + value: widget.store.planDetail.summary ?? "", + onConfirm: (value) async { + widget.store.updatePlanDetail((dto) { + dto.summary = value; + }); + await editPlanSummaryApi(int.parse(widget.store.planId), value); + }, + ); + } + } + + ///取消编辑 + void _cancelEdit() { + widget.store.setEdit(false); + } + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, // 关键:Row 只占实际内容宽度 + children: [ + AnimatedSwitcher( + duration: Duration(milliseconds: 300), + transitionBuilder: (child, animation) { + // 仅使用渐变动画 + return FadeTransition( + opacity: animation, + child: child, + ); + }, + child: widget.store.isEdit + ? InkWell( + onTap: _cancelEdit, + child: Icon(RemixIcons.check_fill), + ) + : PopupAction( + onSelected: _onPopupActionSelected, + items: [ + PopupMenuItem( + value: 'edit_step', + child: Text("编辑步骤"), + ), + PopupMenuItem( + value: 'edit_desc', + child: Text("编辑摘要"), + ), + ], + child: Icon(RemixIcons.more_fill), + ), + ), + ], + ); + } +} diff --git a/lib/page/plan/detail/plan_detail_page.dart b/lib/page/plan/detail/plan_detail_page.dart index 0e89108..fa6af2b 100644 --- a/lib/page/plan/detail/plan_detail_page.dart +++ b/lib/page/plan/detail/plan_detail_page.dart @@ -1,12 +1,10 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:plan/page/plan/detail/navigation/bar_actions.dart'; import 'package:plan/page/plan/detail/viewmodel/plan_detail_store.dart'; import 'package:plan/theme/decorations/app_shadows.dart'; -import 'package:plan/widgets/ui_kit/popup/popup_action.dart'; import 'package:provider/provider.dart'; -import 'package:remixicon/remixicon.dart'; -import '../widgets/edit_desc_dialog.dart'; import 'widgets/avatar_card.dart'; import 'widgets/coach_message.dart'; import 'widgets/plan_list.dart'; @@ -28,7 +26,6 @@ class PlanDetailPage extends StatefulWidget { } class _PlanDetailPageState extends State { - bool _isEdit = false; final ScrollController scrollController = ScrollController(); ///store对象 @@ -44,28 +41,6 @@ class _PlanDetailPageState extends State { ); } - ///popup菜单 - void _onPopupActionSelected(String value) { - if (value == 'edit_step') { - setState(() { - _isEdit = true; - }); - } else if (value == 'edit_desc') { - showEditDescDialog( - context, - value: "你好", - onConfirm: (value) {}, - ); - } - } - - ///取消编辑 - void _cancelEdit() { - setState(() { - _isEdit = false; - }); - } - @override Widget build(BuildContext context) { return ChangeNotifierProvider( @@ -83,9 +58,8 @@ class _PlanDetailPageState extends State { child: ScrollBox( child: Container( decoration: shadowDecoration, - child: CustomScrollView( - controller: scrollController, - slivers: [ + child: Column( + children: [ CoachMessage(), PlanList(), SuggestedTitle(), @@ -104,40 +78,7 @@ class _PlanDetailPageState extends State { backgroundColor: Colors.white, navigationBar: CupertinoNavigationBar( middle: Text(store.planDetail.summary ?? ""), - trailing: Row( - mainAxisSize: MainAxisSize.min, // 关键:Row 只占实际内容宽度 - children: [ - AnimatedSwitcher( - duration: Duration(milliseconds: 300), - transitionBuilder: (child, animation) { - // 仅使用渐变动画 - return FadeTransition( - opacity: animation, - child: child, - ); - }, - child: _isEdit - ? InkWell( - onTap: _cancelEdit, - child: Icon(RemixIcons.check_fill), - ) - : PopupAction( - onSelected: _onPopupActionSelected, - items: [ - PopupMenuItem( - value: 'edit_step', - child: Text("编辑步骤"), - ), - PopupMenuItem( - value: 'edit_desc', - child: Text("编辑摘要"), - ), - ], - child: Icon(RemixIcons.more_fill), - ), - ), - ], - ), + trailing: BarActions(store: store), ), child: child!, ); diff --git a/lib/page/plan/detail/viewmodel/plan_detail_store.dart b/lib/page/plan/detail/viewmodel/plan_detail_store.dart index 5fc31e5..f28344b 100644 --- a/lib/page/plan/detail/viewmodel/plan_detail_store.dart +++ b/lib/page/plan/detail/viewmodel/plan_detail_store.dart @@ -14,7 +14,7 @@ class PlanDetailStore extends ChangeNotifier { //如果没有id进行初始化 if (planId == "0") { createPlan(); - }else{ + } else { //获取详情 getPlanDetail(); } @@ -42,6 +42,15 @@ class PlanDetailStore extends ChangeNotifier { ///计划详情 PlanDetailDto planDetail = PlanDetailDto(summary: "计划详情"); + ///是否正在编辑 + bool isEdit = false; + + ///切换编辑模式 + void setEdit(bool value) { + isEdit = value; + notifyListeners(); + } + ///流请求工具 StreamUtils streamUtils = StreamUtils(); @@ -49,7 +58,6 @@ class PlanDetailStore extends ChangeNotifier { void createPlan() async { var id = await initPlanApi(planContent, 1); planId = id.toString(); - // planId = "3"; ///生成摘要--------------------------- String summary = ""; @@ -92,9 +100,12 @@ class PlanDetailStore extends ChangeNotifier { .where((e) => e.contains("[NEXT]")) .map((e) => e.replaceAll("[NEXT]", "").trim()) .toList(); - // 直接覆盖 stepsList - planDetail.stepsList = sentences.map((s) => PlanStepDto(stepContent: s)).toList(); + planDetail.stepsList = sentences + .asMap() + .entries + .map((e) => PlanStepDto(id: e.key, stepContent: e.value)) + .toList(); notifyListeners(); }, ); @@ -159,4 +170,10 @@ class PlanDetailStore extends ChangeNotifier { planDetail = await getPlanDetailApi(planId); notifyListeners(); } + + ///更新计划详情 + void updatePlanDetail(void Function(PlanDetailDto dto) updater) { + updater(planDetail); + notifyListeners(); + } } diff --git a/lib/page/plan/detail/widgets/coach_message.dart b/lib/page/plan/detail/widgets/coach_message.dart index 60fd4d7..9bd87e6 100644 --- a/lib/page/plan/detail/widgets/coach_message.dart +++ b/lib/page/plan/detail/widgets/coach_message.dart @@ -14,23 +14,21 @@ class _CoachMessageState extends State { Widget build(BuildContext context) { var store = context.read(); if (store.planContent.isEmpty) { - return SliverToBoxAdapter(); + return SizedBox(); } - return SliverToBoxAdapter( - child: Container( - padding: EdgeInsets.all(20), - child: Column( - children: [ - Text( - "你的教练正在拆分", - style: Theme.of(context).textTheme.bodyMedium, - ), - Text( - '"${store.planContent}"', - style: Theme.of(context).textTheme.titleMedium, - ), - ], - ), + return Container( + padding: EdgeInsets.all(20), + child: Column( + children: [ + Text( + "你的教练正在拆分", + style: Theme.of(context).textTheme.bodyMedium, + ), + Text( + '"${store.planContent}"', + style: Theme.of(context).textTheme.titleMedium, + ), + ], ), ); } diff --git a/lib/page/plan/detail/widgets/plan_list.dart b/lib/page/plan/detail/widgets/plan_list.dart index b3e8969..cb85972 100644 --- a/lib/page/plan/detail/widgets/plan_list.dart +++ b/lib/page/plan/detail/widgets/plan_list.dart @@ -1,5 +1,9 @@ +import 'package:animated_reorderable_list/animated_reorderable_list.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:plan/api/dto/plan_detail_dto.dart'; +import 'package:plan/api/endpoints/plan_api.dart'; +import 'package:plan/data/models/plan_acttion_type.dart'; import 'package:plan/page/plan/detail/viewmodel/plan_detail_store.dart'; import 'package:plan/utils/common.dart'; import 'package:plan/widgets/business/delete_row_item.dart'; @@ -14,143 +18,197 @@ class PlanList extends StatefulWidget { } class _PlanListState extends State { - final GlobalKey _listKey = GlobalKey(); - List _stepsList = []; - @override void initState() { super.initState(); - _initListen(); } - void _initListen() { - final store = context.read(); - //先初始化,只在详情时才会有意义 - _stepsList = store.planDetail.stepsList; - store.addListener(() { - final newList = store.planDetail.stepsList; + ///删除步骤 + void _handDelete(int id) async { + var store = context.read(); + store.updatePlanDetail((dto) { + dto.stepsList = dto.stepsList.where((element) => element.id != id).toList(); + }); + await editPlanStepApi( + int.parse(store.planId), + act: PlanActionType.delete, + stepId: id, + ); + } - // 找出新增的 item - if (newList.length > _stepsList.length) { - final addedItems = newList.sublist(_stepsList.length); + ///确认排序 + void _confirmSort(List list) async { + var store = context.read(); + store.updatePlanDetail((dto) { + dto.stepsList = list; + }); + await editPlanStepOrderApi(int.parse(store.planId), list); + } - for (var item in addedItems) { - final index = _stepsList.length; - _stepsList.add(item); + ///确认完成或者取消 + void _handComplete(int id) async { + HapticFeedback.vibrate(); + var store = context.read(); - // 插入动画 - _listKey.currentState?.insertItem( - index, - duration: Duration(milliseconds: 300), + store.updatePlanDetail((dto) { + dto.stepsList = dto.stepsList.map((step) { + if (step.id == id) { + // 只更新匹配的项 + step.stepStatus = step.stepStatus == 2 ? 0 : 2; + editPlanStepApi( + int.parse(store.planId), + act: PlanActionType.complete, + stepId: id, ); } - } else { - setState(() { - _stepsList = store.planDetail.stepsList; - }); - } + return step; + }).toList(); }); } @override Widget build(BuildContext context) { - return SliverAnimatedList( - key: _listKey, - initialItemCount: _stepsList.length, - itemBuilder: (_, index, animation) { - //动画 - final curvedAnimation = CurvedAnimation( - parent: animation, - curve: Curves.easeInOut, - ); - return PlanItem( - step: _stepsList[index], - curvedAnimation: curvedAnimation, - onDelete: (id) {}, + final isEdit = context.select((s) => s.isEdit); + return Selector>( + selector: (_, store) => store.planDetail.stepsList + .map((e) => '${e.id}_${e.stepExplain}_${e.stepStatus}') + .toList(), + builder: (context, list, _) { + final list = context.read().planDetail.stepsList; + return AnimatedReorderableListView( + items: list, + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemBuilder: (BuildContext context, int index) { + var item = list[index]; + return PlanItem( + key: ValueKey('${item.id ?? index}_${item.hashCode}'), + step: item, + isEdit: isEdit, + onDelete: _handDelete, + onComplete: _handComplete, + ); + }, + enterTransition: [SlideInDown()], + exitTransition: [SlideInUp()], + insertDuration: const Duration(milliseconds: 300), + removeDuration: const Duration(milliseconds: 300), + dragStartDelay: const Duration(milliseconds: 300), + onReorder: (int oldIndex, int newIndex) { + setState(() { + final item = list.removeAt(oldIndex); + list.insert(newIndex, item); + _confirmSort(list); + }); + }, + nonDraggableItems: isEdit ? [] : list, + buildDefaultDragHandles: false, + longPressDraggable: false, + isSameItem: (a, b) => a.stepContent == b.stepContent, ); }, ); } } +///计划item class PlanItem extends StatelessWidget { final PlanStepDto step; - final bool showEdit; - final CurvedAnimation curvedAnimation; + final bool isEdit; final Function(int) onDelete; + final Function(int) onComplete; const PlanItem({ super.key, required this.step, - required this.curvedAnimation, - this.showEdit = false, + this.isEdit = false, required this.onDelete, + required this.onComplete, }); @override Widget build(BuildContext context) { - return FadeTransition( - opacity: curvedAnimation, - child: SizeTransition( - sizeFactor: curvedAnimation, - axis: Axis.vertical, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), - child: DeleteRowItem( - showDelete: showEdit, - onDelete: () {}, - builder: (_, animate) { - return [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - margin: EdgeInsets.only(bottom: 3), - child: Text( - step.stepContent ?? "", - style: Theme.of(context).textTheme.bodyMedium, - ), + return GestureDetector( + onTap: () { + if (!isEdit) { + onComplete(step.id!); + } + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + color: Colors.white, + child: DeleteRowItem( + showDelete: isEdit, + onDelete: () { + onDelete(step.id!); + }, + builder: (_, animate) { + return [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Container( + margin: EdgeInsets.only(bottom: 3), + child: Text( + step.stepContent ?? "", + style: stepTextStyle(context, Theme.of(context).textTheme.bodyMedium), ), - AnimatedSwitcher( - duration: Duration(milliseconds: 300), - transitionBuilder: (child, animation) { - return FadeTransition( - opacity: animation, - child: SizeTransition( - sizeFactor: animation, - axis: Axis.vertical, - child: child, - ), - ); - }, - child: getNotEmpty(step.stepExplain) == null - ? SizedBox.shrink(key: ValueKey("empty")) - : Text( - step.stepExplain!, - style: Theme.of(context).textTheme.labelSmall, - key: ValueKey(step.stepExplain), - ), - ), - ], - ), - ), - SizeTransition( - axis: Axis.horizontal, - sizeFactor: animate, - child: Container( - margin: EdgeInsets.only(left: 10), - child: Opacity( - opacity: 0.4, - child: Icon(RemixIcons.menu_line), ), + AnimatedSwitcher( + duration: Duration(milliseconds: 300), + transitionBuilder: (child, animation) { + return FadeTransition( + opacity: animation, + child: SizeTransition( + sizeFactor: animation, + axis: Axis.vertical, + child: child, + ), + ); + }, + child: getNotEmpty(step.stepExplain) == null + ? SizedBox.shrink(key: ValueKey("empty")) + : Text( + step.stepExplain!, + style: stepTextStyle( + context, + Theme.of(context).textTheme.labelSmall, + ), + key: ValueKey(step.stepExplain), + ), + ), + ], + ), + ), + SizeTransition( + axis: Axis.horizontal, + sizeFactor: animate, + child: Container( + alignment: Alignment.center, + margin: EdgeInsets.only(left: 10), + child: Opacity( + opacity: 0.4, + child: Icon(RemixIcons.menu_line), ), ), - ]; - }, - ), + ), + ]; + }, ), ), ); } + + TextStyle? stepTextStyle(BuildContext context, TextStyle? baseStyle) { + if (step.stepStatus == 2) { + return baseStyle?.copyWith( + decoration: TextDecoration.lineThrough, + decorationThickness: 3, + decorationColor: Theme.of(context).colorScheme.onSurfaceVariant, + color: Theme.of(context).colorScheme.onSurfaceVariant, + ); + } + return baseStyle; + } } diff --git a/lib/page/plan/detail/widgets/scroll_box.dart b/lib/page/plan/detail/widgets/scroll_box.dart index 364c40c..5c95ee0 100644 --- a/lib/page/plan/detail/widgets/scroll_box.dart +++ b/lib/page/plan/detail/widgets/scroll_box.dart @@ -23,8 +23,9 @@ class ScrollBox extends StatelessWidget { radius: const Radius.circular(5), ), child: Scrollbar( - controller: scrollController, - child: child, + child: SingleChildScrollView( + child: child, + ), ), ); } diff --git a/lib/page/plan/detail/widgets/suggested.dart b/lib/page/plan/detail/widgets/suggested.dart index 6e8a7a8..7ca2bf1 100644 --- a/lib/page/plan/detail/widgets/suggested.dart +++ b/lib/page/plan/detail/widgets/suggested.dart @@ -9,51 +9,48 @@ class SuggestedTitle extends StatelessWidget { @override Widget build(BuildContext context) { - var list = context.select>( - (store) => store.planDetail.suggestionsList, - ); - if (list.isEmpty) { - return const SliverToBoxAdapter( - child: SizedBox(), - ); - } - return SliverToBoxAdapter( - child: TweenAnimationBuilder( - tween: Tween(begin: 0, end: 1), // 从透明到完全显示 - duration: const Duration(milliseconds: 300), - builder: (context, value, child) { - return Opacity( - opacity: value, - child: child, - ); - }, - child: Container( - margin: const EdgeInsets.only(top: 20, bottom: 5), - child: Opacity( - opacity: 0.6, - child: Row( - spacing: 20, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 15, - height: 1, - color: Theme.of(context).colorScheme.surfaceContainerHigh, - ), - Text( - "额外建议", - style: Theme.of(context).textTheme.titleSmall, - ), - Container( - width: 15, - height: 1, - color: Theme.of(context).colorScheme.surfaceContainerHigh, - ), - ], + return Consumer( + builder: (context, store, _) { + if (store.planDetail.suggestionsList.isEmpty) { + return SizedBox(); + } + return TweenAnimationBuilder( + tween: Tween(begin: 0, end: 1), // 从透明到完全显示 + duration: const Duration(milliseconds: 300), + builder: (context, value, child) { + return Opacity( + opacity: value, + child: child, + ); + }, + child: Container( + margin: const EdgeInsets.only(top: 20, bottom: 5), + child: Opacity( + opacity: 0.6, + child: Row( + spacing: 20, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 15, + height: 1, + color: Theme.of(context).colorScheme.surfaceContainerHigh, + ), + Text( + "额外建议", + style: Theme.of(context).textTheme.titleSmall, + ), + Container( + width: 15, + height: 1, + color: Theme.of(context).colorScheme.surfaceContainerHigh, + ), + ], + ), ), ), - ), - ), + ); + }, ); } } @@ -67,13 +64,14 @@ class SuggestedList extends StatefulWidget { } class _SuggestedListState extends State { - final GlobalKey _listKey = GlobalKey(); + final GlobalKey _listKey = GlobalKey(); List _suggestionsList = []; @override void initState() { super.initState(); _initListen(); + WidgetsBinding.instance.addPostFrameCallback((_) => _initListen()); } void _initListen() { @@ -82,7 +80,6 @@ class _SuggestedListState extends State { _suggestionsList = store.planDetail.suggestionsList; store.addListener(() { final newList = store.planDetail.suggestionsList; - // 找出新增的 item if (newList.length > _suggestionsList.length) { final addedItems = newList.sublist(_suggestionsList.length); @@ -107,8 +104,10 @@ class _SuggestedListState extends State { @override Widget build(BuildContext context) { - return SliverAnimatedList( + return AnimatedList( key: _listKey, + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), initialItemCount: _suggestionsList.length, itemBuilder: (_, index, animation) { final curvedAnimation = CurvedAnimation( diff --git a/lib/page/plan/history/plan_history_page.dart b/lib/page/plan/history/plan_history_page.dart index 201b6c5..5bd1993 100644 --- a/lib/page/plan/history/plan_history_page.dart +++ b/lib/page/plan/history/plan_history_page.dart @@ -2,10 +2,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:plan/api/dto/plan_item_dto.dart'; import 'package:plan/api/endpoints/plan_api.dart'; -import 'package:remixicon/remixicon.dart'; import 'widgets/history_item.dart'; -import '../../../widgets/ui_kit/popup/popup_action.dart'; import 'widgets/loading_box.dart'; class PlanHistoryPage extends StatefulWidget { @@ -38,23 +36,11 @@ class _PlanHistoryPageState extends State { }); } - ///popup事件 - void _onPopupActionSelected(String value) { - switch (value) { - case 'edit': - setState(() { - _isDelete = !_isDelete; - }); - break; - } - } ///确认删除 void _confirmDelete(int id) { - print(_record.map((e) => e.toJson())); setState(() { _record.removeWhere((element) => element.id == id); - print(_record.map((e) => e.toJson())); }); } diff --git a/lib/widgets/business/delete_row_item.dart b/lib/widgets/business/delete_row_item.dart index 8f8fbc3..2ebe28e 100644 --- a/lib/widgets/business/delete_row_item.dart +++ b/lib/widgets/business/delete_row_item.dart @@ -89,6 +89,7 @@ class _DeleteRowItemState extends State with TickerProviderStateM @override Widget build(BuildContext context) { return Row( + crossAxisAlignment: CrossAxisAlignment.center, children: [ SizeTransition( axis: Axis.horizontal, @@ -98,6 +99,7 @@ class _DeleteRowItemState extends State with TickerProviderStateM onTap: _handleDelete, child: Container( margin: EdgeInsets.only(right: 10), + alignment: Alignment.centerRight, child: Icon( RemixIcons.indeterminate_circle_fill, color: Colors.red, diff --git a/pubspec.lock b/pubspec.lock index 7c80337..1a93f16 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + animated_reorderable_list: + dependency: "direct main" + description: + name: animated_reorderable_list + sha256: "5de5cca556a8c9c8f7b65234ae4b683593dc6e167db498744a5e389302f24d13" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.3.0" args: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d3904cf..596950a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -30,6 +30,7 @@ dependencies: flutter_image_compress: ^2.4.0 cached_network_image: ^3.4.1 intl: ^0.19.0 + animated_reorderable_list: ^1.3.0 dev_dependencies: flutter_test: