Selaa lähdekoodia

增加筛选:采样品种、扦样地区

mq 1 vuosi sitten
vanhempi
commit
837693d632

+ 2 - 0
lib/base/base_state.dart

@@ -21,12 +21,14 @@ abstract class BaseState<T extends StatefulWidget> extends State<T> {
21 21
     bool autoLeading = true,
22 22
     PreferredSizeWidget? bottom,
23 23
     double? toolbarHeight,
24
+    List<Widget>? actions,
24 25
   }) {
25 26
     return AppBar(
26 27
       title: Text(title),
27 28
       bottom: bottom,
28 29
       automaticallyImplyLeading: autoLeading,
29 30
       toolbarHeight: toolbarHeight,
31
+      actions: actions,
30 32
     );
31 33
   }
32 34
 

+ 8 - 0
lib/model/req/sample_task_list_req.dart

@@ -16,11 +16,19 @@ class SampleTaskListReq {
16 16
   /// 环节类型:1收获环节,2库存环节
17 17
   int? rwlx;
18 18
 
19
+  /// 采样品种ID集合
20
+  List<int>? pzIdList;
21
+
22
+  /// 行政区划
23
+  String? xzqh;
24
+
19 25
   SampleTaskListReq({
20 26
     this.pageNo = 1,
21 27
     this.pageSize = 10,
22 28
     this.deliveryStatus,
23 29
     this.rwlx,
30
+    this.pzIdList,
31
+    this.xzqh,
24 32
   });
25 33
 
26 34
   factory SampleTaskListReq.fromJson(Map<String, dynamic> json) => _$SampleTaskListReqFromJson(json);

+ 5 - 0
lib/model/req/sample_task_list_req.g.dart

@@ -12,6 +12,9 @@ SampleTaskListReq _$SampleTaskListReqFromJson(Map<String, dynamic> json) =>
12 12
       pageSize: json['pageSize'] as int? ?? 10,
13 13
       deliveryStatus: json['deliveryStatus'] as int?,
14 14
       rwlx: json['rwlx'] as int?,
15
+      pzIdList:
16
+          (json['pzIdList'] as List<dynamic>?)?.map((e) => e as int).toList(),
17
+      xzqh: json['xzqh'] as String?,
15 18
     );
16 19
 
17 20
 Map<String, dynamic> _$SampleTaskListReqToJson(SampleTaskListReq instance) =>
@@ -20,4 +23,6 @@ Map<String, dynamic> _$SampleTaskListReqToJson(SampleTaskListReq instance) =>
20 23
       'pageSize': instance.pageSize,
21 24
       'deliveryStatus': instance.deliveryStatus,
22 25
       'rwlx': instance.rwlx,
26
+      'pzIdList': instance.pzIdList,
27
+      'xzqh': instance.xzqh,
23 28
     };

+ 1 - 1
lib/network/api.dart

@@ -82,5 +82,5 @@ abstract class Api {
82 82
 
83 83
   /// 上传图片
84 84
   @POST('/admin-api/infra/file/upload')
85
-  Future<void> upload(@Part(name: 'path', contentType: 'image/png') File path);
85
+  Future<void> upload(@Part(name: 'path') File path);
86 86
 }

+ 163 - 0
lib/page/filter/filter_page.dart

@@ -0,0 +1,163 @@
1
+import 'package:flutter/cupertino.dart';
2
+import 'package:flutter/material.dart';
3
+import 'package:flutter/services.dart';
4
+import 'package:flutter/widgets.dart';
5
+import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
6
+import 'package:lszlgl/base/base_lifecycle_state.dart';
7
+import 'package:lszlgl/base/base_state.dart';
8
+import 'package:lszlgl/service/dict_service.dart';
9
+import 'package:lszlgl/widget/button.dart';
10
+import 'package:lszlgl/widget/card_item.dart';
11
+
12
+import '../../config/colors.dart';
13
+import '../../utils/inject.dart';
14
+import '../sample_task/sample_list_vm.dart';
15
+
16
+class FilterPage extends StatefulWidget {
17
+  const FilterPage({super.key});
18
+
19
+  @override
20
+  State<FilterPage> createState() => _FilterPageState();
21
+}
22
+
23
+class _FilterPageState extends BaseState<FilterPage> {
24
+  late SampleListVM vm;
25
+
26
+  /// 采样品种
27
+  List<CardMenuData> cypzList = [];
28
+  final cypzNames = null.notifier<String?>();
29
+  List<CardMenuData> selectCypzList = [];
30
+
31
+  /// 扦样地区
32
+  String? xzqh;
33
+
34
+  void getCypzList() {
35
+    cypzList = (DictService.getDictList(DictType.cypz) ?? []).map((e) => CardMenuData(e.label, e.value)).toList();
36
+    if ((vm.reqList.first.pzIdList ?? []).isNotEmpty) {
37
+      for (var id in vm.reqList.first.pzIdList!) {
38
+        for (var menu in cypzList) {
39
+          if (int.parse(menu.value) == id) {
40
+            menu.select = true;
41
+            selectCypzList.add(menu);
42
+            break;
43
+          }
44
+        }
45
+      }
46
+    }
47
+    cypzSelCallback(selectCypzList);
48
+  }
49
+
50
+  void cypzSelCallback(List<CardMenuData> selectList) async {
51
+    selectCypzList = selectList;
52
+    if (selectList.isEmpty) {
53
+      cypzNames.value = null;
54
+      return;
55
+    }
56
+    var names = StringBuffer();
57
+    var ids = StringBuffer();
58
+    for (int i = 0; i < selectList.length; i++) {
59
+      var item = selectList[i];
60
+      names.write(item.name);
61
+      ids.write(item.value);
62
+      if (i < selectList.length - 1) {
63
+        names.write(',');
64
+        ids.write(',');
65
+      }
66
+    }
67
+    cypzNames.value = names.toString();
68
+  }
69
+
70
+  void onReset() {
71
+    for (var req in vm.reqList) {
72
+      req.pzIdList = null;
73
+      req.xzqh = null;
74
+    }
75
+    vm.refreshAll();
76
+    MyNavigator.pop();
77
+  }
78
+
79
+  void onConfirm() {
80
+    for (var req in vm.reqList) {
81
+      req.pzIdList = selectCypzList.map((e) => int.parse(e.value)).toList();
82
+      req.xzqh = xzqh;
83
+    }
84
+    vm.refreshAll();
85
+    MyNavigator.pop();
86
+  }
87
+
88
+  @override
89
+  void initState() {
90
+    super.initState();
91
+    vm = Inject.get<SampleListVM>()!;
92
+
93
+    // 采样品种
94
+    getCypzList();
95
+    xzqh = vm.reqList.first.xzqh;
96
+  }
97
+
98
+  @override
99
+  void dispose() {
100
+    cypzNames.dispose();
101
+    super.dispose();
102
+  }
103
+
104
+  @override
105
+  Widget build(BuildContext context) {
106
+    return Padding(
107
+      padding: MediaQuery.of(context).viewInsets,
108
+      child: KeyboardDismissOnTap(
109
+        dismissOnCapturedTaps: true,
110
+        child: Column(
111
+          mainAxisSize: MainAxisSize.min,
112
+          children: [
113
+            buildTitle(),
114
+            cypzNames.builder(
115
+              (v) => CardWidgets.buildMenuDialog(
116
+                false,
117
+                '采样品种',
118
+                v,
119
+                cypzList,
120
+                cypzSelCallback,
121
+                multiple: true,
122
+                showTopLine: true,
123
+                hint: '请选择',
124
+              ),
125
+            ),
126
+            CardWidgets.buildEdit(
127
+              false,
128
+              '扦样地区',
129
+              xzqh,
130
+              onChanged: (value) => xzqh = value,
131
+              hint: '请输入(模糊查询)',
132
+            ),
133
+            Padding(
134
+              padding: const EdgeInsets.only(top: 64, bottom: 48, left: 16, right: 16),
135
+              child: Row(
136
+                children: [
137
+                  Expanded(child: MyButton('重置', onTap: onReset)),
138
+                  const SizedBox(width: 16),
139
+                  Expanded(child: MyButton('确定', onTap: onConfirm)),
140
+                ],
141
+              ),
142
+            ),
143
+          ],
144
+        ),
145
+      ),
146
+    );
147
+  }
148
+
149
+  Widget buildTitle() {
150
+    return Container(
151
+      alignment: Alignment.topLeft,
152
+      padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
153
+      child: const Text(
154
+        '数据筛选',
155
+        style: TextStyle(
156
+          color: MyColor.c_333333,
157
+          fontSize: 16,
158
+          fontWeight: FontWeight.w500,
159
+        ),
160
+      ),
161
+    );
162
+  }
163
+}

+ 10 - 1
lib/page/sample_task/reap_sample_detail/reap_sample_basic_detail_page.dart

@@ -324,7 +324,16 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
324 324
       children: [
325 325
         CardItemWidget('样品单号', rightText: data?.qyrwdh, bottomLine: true),
326 326
         name.builder(
327
-            (v) => CardWidgets.buildMenuDialog(isDetail, '扦样/陪同人员', v, personList, personSelCallback, multiple: true)),
327
+          (v) => CardWidgets.buildMenuDialog(
328
+            isDetail,
329
+            '扦样/陪同人员',
330
+            v,
331
+            personList,
332
+            personSelCallback,
333
+            multiple: true,
334
+            selectCountMax: 3,
335
+          ),
336
+        ),
328 337
         sheng.builder((v) => CardItemWidget('省份', rightText: v?.name, bottomLine: true)),
329 338
         shi.builder((v) => CardItemWidget('市/州', rightText: v?.name, bottomLine: true)),
330 339
         qu.builder((v) => CardItemWidget('区县', rightText: v?.name, bottomLine: true)),

+ 1 - 1
lib/page/sample_task/sample_task_list_page.dart

@@ -154,7 +154,7 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage> wi
154 154
         buildVLine(),
155 155
         const Expanded(
156 156
           child: Text(
157
-            '扦样任务单号',
157
+            '样品单号',
158 158
             style: TextStyle(color: MyColor.c_333333, fontSize: 14, fontWeight: FontWeight.w500),
159 159
           ),
160 160
         ),

+ 28 - 1
lib/page/sample_task/sample_task_list_tab_page.dart

@@ -1,3 +1,4 @@
1
+import 'package:flutter/cupertino.dart';
1 2
 import 'package:flutter/material.dart';
2 3
 import 'package:lszlgl/base/base_lifecycle_state.dart';
3 4
 import 'package:lszlgl/config/colors.dart';
@@ -5,6 +6,8 @@ import 'package:lszlgl/page/sample_task/sample_list_vm.dart';
5 6
 import 'package:lszlgl/page/sample_task/sample_task_list_page.dart';
6 7
 import 'package:lszlgl/utils/inject.dart';
7 8
 
9
+import '../filter/filter_page.dart';
10
+
8 11
 enum StepType {
9 12
   reap('收获环节', 1),
10 13
   stock('库存环节', 2);
@@ -49,6 +52,15 @@ class _SampleTaskListTabPageState extends BaseLifecycleState<SampleTaskListTabPa
49 52
 
50 53
   late SampleListVM vm;
51 54
 
55
+  void showFilter() {
56
+    showModalBottomSheet(
57
+      context: context,
58
+      isScrollControlled: true,
59
+      showDragHandle: true,
60
+      builder: (_) => const FilterPage(),
61
+    );
62
+  }
63
+
52 64
   @override
53 65
   void onInit() {
54 66
     vm = Inject.put<SampleListVM>(SampleListVM(), dispose: (v) => v.dispose());
@@ -90,7 +102,10 @@ class _SampleTaskListTabPageState extends BaseLifecycleState<SampleTaskListTabPa
90 102
   Widget buildBody() {
91 103
     return Column(
92 104
       children: [
93
-        myAppBar(title: widget.args.type.title),
105
+        myAppBar(
106
+          title: widget.args.type.title,
107
+          actions: [buildFilter()],
108
+        ),
94 109
         buildTab(),
95 110
         const SizedBox(height: 12),
96 111
         Expanded(child: buildPage()),
@@ -98,6 +113,18 @@ class _SampleTaskListTabPageState extends BaseLifecycleState<SampleTaskListTabPa
98 113
     );
99 114
   }
100 115
 
116
+  Widget buildFilter() {
117
+    return GestureDetector(
118
+      onTap: showFilter,
119
+      behavior: HitTestBehavior.opaque,
120
+      child: Container(
121
+        padding: const EdgeInsets.symmetric(horizontal: 16),
122
+        alignment: Alignment.center,
123
+        child: const Text('筛选', style: TextStyle(fontSize: 12, color: Colors.white)),
124
+      ),
125
+    );
126
+  }
127
+
101 128
   Widget buildTab() {
102 129
     return Container(
103 130
       clipBehavior: Clip.hardEdge,

+ 3 - 1
lib/service/dict_service.dart

@@ -24,7 +24,9 @@ enum DictType {
24 24
   // 真菌毒素污染类型
25 25
   zjdswrlx('zjdswrlx'),
26 26
   // 重金属污染类型
27
-  zjswrlx('zjswrlx');
27
+  zjswrlx('zjswrlx'),
28
+  // 采样品种
29
+  cypz('cypz');
28 30
 
29 31
   const DictType(this.type);
30 32
 

+ 11 - 4
lib/widget/card_item.dart

@@ -129,6 +129,7 @@ class CardItemWidget extends StatelessWidget {
129 129
   }
130 130
 }
131 131
 
132
+//ignore: must_be_immutable
132 133
 class CardItemMenuWidget extends StatelessWidget {
133 134
   /// 标题文本
134 135
   final String title;
@@ -293,6 +294,7 @@ class CardWidgets {
293 294
     List<TextInputFormatter>? formatters,
294 295
     Color? backgroundColor = Colors.white,
295 296
     bool bottomLine = true,
297
+    TextEditingController? ctrl,
296 298
   }) {
297 299
     if (isDetail) {
298 300
       return CardItemWidget(
@@ -304,8 +306,9 @@ class CardWidgets {
304 306
     }
305 307
     return CardItemWidget(
306 308
       title,
307
-      rightChild: TextField(
308
-        controller: TextEditingController(text: value),
309
+      rightChild: TextFormField(
310
+        controller: ctrl,
311
+        initialValue: value,
309 312
         keyboardType: inputType,
310 313
         textAlign: TextAlign.right,
311 314
         decoration: InputDecoration(
@@ -371,11 +374,15 @@ class CardWidgets {
371 374
     bool multiple = false,
372 375
     String? hint,
373 376
     Widget? trailing,
377
+    int? selectCountMax,
378
+    bool bottomLine = true,
379
+    bool showTopLine = false,
374 380
   }) {
375 381
     return CardItemWidget(
376 382
       title,
377 383
       rightText: value,
378
-      bottomLine: true,
384
+      bottomLine: bottomLine,
385
+      showTopLine: showTopLine,
379 386
       hint: hint,
380 387
       trailing: isDetail || value != null
381 388
           ? null
@@ -392,7 +399,7 @@ class CardWidgets {
392 399
                 list,
393 400
                 title: title,
394 401
                 multiple: multiple,
395
-                selectCountMax: 3,
402
+                selectCountMax: selectCountMax,
396 403
               );
397 404
               if (selectList == null) return;
398 405
               onSelectTap?.call(selectList);