Browse Source

修改多选弹窗;

maqiang 1 year ago
parent
commit
daff70336a

+ 54 - 63
lib/page/sample_task/reap_sample_detail/reap_sample_basic_detail_page.dart

@@ -6,7 +6,6 @@ import 'package:lszlgl/main.dart';
6 6
 import 'package:lszlgl/utils/input_formatter.dart';
7 7
 import 'package:lszlgl/utils/location_utils.dart';
8 8
 import 'package:lszlgl/widget/button.dart';
9
-import 'package:lszlgl/widget/menu_dialog.dart';
10 9
 import '../../../base/base_lifecycle_state.dart';
11 10
 import '../../../model/rsp/dict_rsp.dart';
12 11
 import '../../../model/rsp/sample_task_rsp.dart';
@@ -50,11 +49,11 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
50 49
 
51 50
   final name = null.notifier<String?>();
52 51
 
53
-  late List<CardMenuData> personList;
52
+  List<CardMenuData> personList = [];
54 53
 
55 54
   /// 获取行政区划列表
56
-  Future<List<CardMenuData>?> getDistrictList(num level, {num? id}) async {
57
-    MyNavigator.showLoading();
55
+  Future<List<CardMenuData>?> getDistrictList(num level, {num? id, bool showLoading = true}) async {
56
+    if (showLoading) MyNavigator.showLoading();
58 57
     try {
59 58
       var rsp = await MyApi.get().districtList(level, id: id);
60 59
       List<CardMenuData> list = (rsp.data ?? []).map((e) => CardMenuData(e.uname, e.id)).toList();
@@ -63,12 +62,12 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
63 62
       } else if (level == 5) {
64 63
         cunList.value = list;
65 64
       }
66
-      MyNavigator.dismissLoading();
65
+      if (showLoading) MyNavigator.dismissLoading();
67 66
       return list;
68 67
     } catch (e) {
69 68
       logger.e(e);
70 69
     }
71
-    MyNavigator.dismissLoading();
70
+    if (showLoading) MyNavigator.dismissLoading();
72 71
     return null;
73 72
   }
74 73
 
@@ -113,30 +112,26 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
113 112
   }
114 113
 
115 114
   /// 获取编辑数据
116
-  void getEditData() {
117
-    // 市
118
-    if (data?.shengXzqh != null) {
119
-      getDistrictList(2, id: data?.shengXzqh);
120
-    }
121
-    // 区
122
-    if (data?.shiXzqh != null) {
123
-      getDistrictList(3, id: data?.shiXzqh);
124
-    }
115
+  void getEditData() async {
116
+    MyNavigator.showLoading();
125 117
     // 县
126 118
     if (data?.quXzqh != null) {
127
-      getDistrictList(4, id: data?.quXzqh);
119
+      await getDistrictList(4, id: data?.quXzqh, showLoading: false);
128 120
     }
129 121
     // 村
130 122
     if (data?.xiangXzqh != null) {
131
-      getDistrictList(5, id: data?.xiangXzqh);
123
+      await getDistrictList(5, id: data?.xiangXzqh, showLoading: false);
132 124
     }
125
+    MyNavigator.dismissLoading();
133 126
   }
134 127
 
135 128
   void getPersonData() async {
136 129
     try {
137 130
       // 获取扦样人员列表
138 131
       var rsp = await MyApi.get().getPersonMenu(data?.jhcyjg ?? 29964);
139
-      personList = (rsp.data ?? []).map((e) => CardMenuData(e.name, e.id)).toList();
132
+      personList
133
+        ..clear()
134
+        ..addAll((rsp.data ?? []).map((e) => CardMenuData(e.name, e.id)).toList());
140 135
       // 选中扦样人员
141 136
       var nameList = data?.name?.split(',');
142 137
       if (nameList != null) {
@@ -191,44 +186,50 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
191 186
       cun.value = null;
192 187
       cunList.value = [];
193 188
 
189
+      MyNavigator.showLoading();
194 190
       bool stepSuccess = false;
195 191
       // 省
196
-      var provinceList = await getDistrictList(1);
197
-      if (provinceList == null) return;
198
-      for (CardMenuData item in provinceList) {
199
-        if (item.name == province) {
200
-          data?.shengXzqh = item.value;
201
-          sheng.value = item;
202
-          stepSuccess = true;
203
-          break;
204
-        }
205
-      }
206
-      if (!stepSuccess) return;
207
-      stepSuccess = false;
208
-      // 市
209
-      var cityList = await getDistrictList(2, id: data?.shengXzqh);
210
-      if (cityList == null) return;
211
-      for (CardMenuData item in cityList) {
212
-        if (item.name == city) {
213
-          data?.shiXzqh = item.value;
214
-          shi.value = item;
215
-          stepSuccess = true;
216
-          break;
192
+      var provinceList = await getDistrictList(1, showLoading: false);
193
+      if (provinceList != null) {
194
+        for (CardMenuData item in provinceList) {
195
+          if (item.name == province) {
196
+            data?.shengXzqh = item.value;
197
+            sheng.value = item;
198
+            stepSuccess = true;
199
+            break;
200
+          }
217 201
         }
218
-      }
219
-      if (!stepSuccess) return;
220
-      stepSuccess = false;
221
-      // 区
222
-      var districtList = await getDistrictList(3, id: data?.shiXzqh);
223
-      if (districtList == null) return;
224
-      for (CardMenuData item in districtList) {
225
-        if (item.name == district) {
226
-          data?.quXzqh = item.value;
227
-          qu.value = item;
228
-          getDistrictList(4, id: item.value);
229
-          break;
202
+        if (stepSuccess) {
203
+          stepSuccess = false;
204
+          // 市
205
+          var cityList = await getDistrictList(2, id: data?.shengXzqh, showLoading: false);
206
+          if (cityList == null) return;
207
+          for (CardMenuData item in cityList) {
208
+            if (item.name == city) {
209
+              data?.shiXzqh = item.value;
210
+              shi.value = item;
211
+              stepSuccess = true;
212
+              break;
213
+            }
214
+          }
215
+          if (stepSuccess) {
216
+            stepSuccess = false;
217
+            // 区
218
+            var districtList = await getDistrictList(3, id: data?.shiXzqh, showLoading: false);
219
+            if (districtList == null) return;
220
+            for (CardMenuData item in districtList) {
221
+              if (item.name == district) {
222
+                data?.quXzqh = item.value;
223
+                qu.value = item;
224
+                getDistrictList(4, id: item.value, showLoading: false);
225
+                break;
226
+              }
227
+            }
228
+          }
230 229
         }
231 230
       }
231
+      MyNavigator.dismissLoading();
232
+
232 233
       String jwd = '$lon,$lat';
233 234
       qyddjwd.value = jwd;
234 235
       data?.qyddjwd = jwd;
@@ -238,9 +239,7 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
238 239
     }
239 240
   }
240 241
 
241
-  void showPersonMenu() async {
242
-    List<CardMenuData>? selectList = await showMenuDialog(personList, selectCountMax: 3, isScrollControlled: true);
243
-    if (selectList == null) return;
242
+  void personSelCallback(List<CardMenuData> selectList) async {
244 243
     if (selectList.isEmpty) {
245 244
       data?.dgryName = null;
246 245
       name.value = null;
@@ -304,15 +303,7 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
304 303
       children: [
305 304
         CardItemWidget('扦样任务单号', rightText: data?.qyrwdh, bottomLine: true),
306 305
         CardItemWidget('扦样单位', rightText: data?.dwmc, bottomLine: true),
307
-        name.builder(
308
-          (v) => CardItemWidget(
309
-            '扦样人员',
310
-            rightText: v,
311
-            bottomLine: true,
312
-            trailing: isDetail || v != null ? null : Image.asset(imgItemArrowDown, width: 20),
313
-            onTap: isDetail ? null : showPersonMenu,
314
-          ),
315
-        ),
306
+        name.builder((v) => CardWidgets.buildMenuDialog(isDetail, '扦样人员', v, personList, personSelCallback, multiple: true)),
316 307
         CardItemWidget('监测类别', rightText: DictService.getLabel(DictType.jclb, value: data?.jclb), bottomLine: true),
317 308
         sheng.builder((v) => CardItemWidget('省份', rightText: v?.name, bottomLine: true)),
318 309
         shi.builder((v) => CardItemWidget('市区', rightText: v?.name, bottomLine: true)),

+ 32 - 0
lib/widget/card_item.dart

@@ -5,6 +5,7 @@ import 'package:lszlgl/ext/value_notifier_ext.dart';
5 5
 
6 6
 import '../config/pics.dart';
7 7
 import '../router/my_navigator.dart';
8
+import 'menu_dialog.dart';
8 9
 
9 10
 class CardItemWidget extends StatelessWidget {
10 11
   /// 标题文本
@@ -354,6 +355,37 @@ class CardWidgets {
354 355
     });
355 356
   }
356 357
 
358
+  static Widget buildMenuDialog(
359
+    bool isDetail,
360
+    String title,
361
+    String? value,
362
+    List<CardMenuData>? list,
363
+    void Function(List<CardMenuData>)? onSelectTap, {
364
+    bool multiple = false,
365
+    String? hint,
366
+    Widget? trailing,
367
+  }) {
368
+    return CardItemWidget(
369
+      title,
370
+      rightText: value,
371
+      bottomLine: true,
372
+      hint: hint,
373
+      trailing: isDetail || value != null ? null : trailing ?? Image.asset(imgItemArrowDown, width: 20),
374
+      onTap: isDetail
375
+          ? null
376
+          : () async {
377
+              List<CardMenuData>? selectList = await showMenuDialog(
378
+                list,
379
+                title: title,
380
+                multiple: multiple,
381
+                selectCountMax: 3,
382
+              );
383
+              if (selectList == null) return;
384
+              onSelectTap?.call(selectList);
385
+            },
386
+    );
387
+  }
388
+
357 389
   static Widget buildMenu(
358 390
     bool isDetail,
359 391
     String title,

+ 84 - 36
lib/widget/menu_dialog.dart

@@ -5,19 +5,28 @@ import 'package:lszlgl/widget/button.dart';
5 5
 import '../config/colors.dart';
6 6
 import 'card_item.dart';
7 7
 
8
+/// 弹出菜单选项弹框
9
+/// * [list] 选项列表数据源
10
+/// * [title] 标题
11
+/// * [multiple] 多选,默认单选
12
+/// * [selectCountMax] 最大选择数量
13
+/// * [backgroundColor] 背景颜色
14
+/// * [borderRadius] 圆角
15
+/// * [constraints] 尺寸约束
16
+/// * [isScrollControlled] 高度自适应, 默认true
17
+/// * [isDismissible] 点击空白处关闭
18
+/// * [enableDrag] 拖动关闭
8 19
 Future<T?> showMenuDialog<T>(
9 20
   List<CardMenuData>? list, {
21
+  String? title,
22
+  bool multiple = false,
10 23
   int? selectCountMax,
11 24
   Color? backgroundColor = Colors.white,
12 25
   BorderRadiusGeometry? borderRadius,
13 26
   BoxConstraints? constraints,
14
-  bool isScrollControlled = false,
27
+  bool isScrollControlled = true,
15 28
   bool isDismissible = true,
16 29
   bool enableDrag = true,
17
-  bool useSafeArea = false,
18
-  RouteSettings? routeSettings,
19
-  AnimationController? animationCtrl,
20
-  Offset? anchorPoint,
21 30
 }) {
22 31
   return showModalBottomSheet(
23 32
     context: MyNavigator.navigator.currentState!.context,
@@ -25,12 +34,11 @@ Future<T?> showMenuDialog<T>(
25 34
     isScrollControlled: isScrollControlled,
26 35
     isDismissible: isDismissible,
27 36
     enableDrag: enableDrag,
28
-    useSafeArea: useSafeArea,
29
-    routeSettings: routeSettings,
30
-    transitionAnimationController: animationCtrl,
31
-    anchorPoint: anchorPoint,
37
+    useSafeArea: true,
32 38
     builder: (_) => MenuDialog(
33 39
       list: list,
40
+      title: title,
41
+      multiple: multiple,
34 42
       selectCountMax: selectCountMax,
35 43
       backgroundColor: backgroundColor,
36 44
     ),
@@ -38,24 +46,28 @@ Future<T?> showMenuDialog<T>(
38 46
 }
39 47
 
40 48
 class MenuDialog extends StatelessWidget {
41
-  final List<CardMenuData>? list;
49
+  final List<CardMenuData> list;
50
+  final String? title;
51
+  final bool multiple;
42 52
   final int? selectCountMax;
43 53
   final Color? backgroundColor;
44 54
   final BorderRadiusGeometry? borderRadius;
45
-
46 55
   final ValueNotifier<int> selectCount;
47 56
 
48 57
   MenuDialog({
49 58
     super.key,
50
-    this.list,
59
+    List<CardMenuData>? list,
60
+    this.title,
61
+    required this.multiple,
51 62
     this.selectCountMax,
52 63
     this.backgroundColor,
53 64
     this.borderRadius,
54
-  }) : selectCount = (list ?? []).where((e) => e.select).length.notifier<int>();
65
+  })  : list = list ?? [],
66
+        selectCount = (list ?? []).where((e) => e.select).length.notifier<int>();
55 67
 
56 68
   void onEnterClick() {
57
-    if (list == null) return;
58
-    List<CardMenuData> selectList = list!.where((item) => item.select).toList();
69
+    if (list.isEmpty) return;
70
+    List<CardMenuData> selectList = list.where((item) => item.select).toList();
59 71
     MyNavigator.pop(selectList);
60 72
   }
61 73
 
@@ -71,42 +83,77 @@ class MenuDialog extends StatelessWidget {
71 83
         crossAxisAlignment: CrossAxisAlignment.start,
72 84
         children: [
73 85
           buildTitle(),
74
-          Flexible(
75
-            child: SingleChildScrollView(
76
-              child: Column(
77
-                mainAxisSize: MainAxisSize.min,
78
-                children: List.generate(list?.length ?? 0, buildItem).toList(),
79
-              ),
80
-            ),
81
-          ),
86
+          buildList(),
82 87
           buildButton(),
88
+          const SizedBox(width: double.infinity, height: 24),
83 89
         ],
84 90
       ),
85 91
     );
86 92
   }
87 93
 
88 94
   Widget buildTitle() {
89
-    return const Padding(
90
-      padding: EdgeInsets.only(left: 24, top: 16, bottom: 16),
91
-      child: Text(
92
-        '请选择:',
93
-        style: TextStyle(color: Color(0xFF333333), fontSize: 16, fontWeight: FontWeight.w500),
95
+    return Padding(
96
+      padding: const EdgeInsets.only(left: 24, top: 16, bottom: 16, right: 24),
97
+      child: Row(
98
+        children: [
99
+          Expanded(
100
+            child: Text(
101
+              '请选择${title ?? ''}:',
102
+              style: const TextStyle(color: Color(0xFF333333), fontSize: 16, fontWeight: FontWeight.w500),
103
+            ),
104
+          ),
105
+          MyButton('关闭', alignment: null, onTap: () => MyNavigator.pop()),
106
+        ],
107
+      ),
108
+    );
109
+  }
110
+
111
+  Widget buildList() {
112
+    if (list.isEmpty) {
113
+      return Container(
114
+        alignment: Alignment.center,
115
+        padding: const EdgeInsets.symmetric(vertical: 24),
116
+        child: const Text(
117
+          '没有选项数据',
118
+          style: TextStyle(fontSize: 16, color: MyColor.c_666666),
119
+        ),
120
+      );
121
+    }
122
+    return Flexible(
123
+      child: SingleChildScrollView(
124
+        child: Column(
125
+          mainAxisSize: MainAxisSize.min,
126
+          children: List.generate(list.length, buildItem).toList(),
127
+        ),
94 128
       ),
95 129
     );
96 130
   }
97 131
 
98 132
   Widget buildItem(int index) {
99
-    var item = list![index];
133
+    var item = list[index];
100 134
     return StatefulBuilder(builder: (_, setState) {
101 135
       return GestureDetector(
102 136
         behavior: HitTestBehavior.opaque,
103 137
         onTap: () {
104
-          if (!item.select && selectCountMax != null && selectCountMax == selectCount.value) {
105
-            MyNavigator.showToast('选中不能超过$selectCountMax个');
106
-            return;
138
+          if (multiple) {
139
+            if (!item.select && selectCountMax != null && selectCountMax == selectCount.value) {
140
+              MyNavigator.showToast('选中不能超过$selectCountMax个');
141
+              return;
142
+            }
143
+            item.select = !item.select;
144
+            setState(() {});
145
+          } else {
146
+            // 取消之前选择
147
+            for (var value in list) {
148
+              if (value.select) {
149
+                value.select = false;
150
+                break;
151
+              }
152
+            }
153
+            // 选中当前项
154
+            item.select = true;
155
+            onEnterClick();
107 156
           }
108
-          item.select = !item.select;
109
-          setState(() {});
110 157
         },
111 158
         child: Column(
112 159
           mainAxisSize: MainAxisSize.min,
@@ -124,7 +171,7 @@ class MenuDialog extends StatelessWidget {
124 171
                 ),
125 172
               ),
126 173
             ),
127
-            index < list!.length - 1
174
+            index < list.length - 1
128 175
                 ? const Divider(
129 176
                     color: Color(0xFFF3F3F3),
130 177
                     height: 0,
@@ -140,8 +187,9 @@ class MenuDialog extends StatelessWidget {
140 187
   }
141 188
 
142 189
   Widget buildButton() {
190
+    if (!multiple || list.isEmpty) return const SizedBox.shrink();
143 191
     return Padding(
144
-      padding: const EdgeInsets.only(bottom: 16, top: 16),
192
+      padding: const EdgeInsets.only(top: 16),
145 193
       child: Row(
146 194
         children: [
147 195
           const Spacer(),

File diff suppressed because it is too large
+ 135 - 135
pubspec.lock