10 Commitit a6e3192cd5 ... 3147c3685a

Tekijä SHA1 Viesti Päivämäärä
  maqiang 3147c3685a 修改版本号:v0.0.17 1 vuosi sitten
  maqiang e09759759a 增加收获扦样任务单页-品种信息校验数据逻辑; 1 vuosi sitten
  maqiang 0b610e635f 打印try catch日志; 1 vuosi sitten
  maqiang 1d765cb9f4 修复扦样单页面Loading报错的问题; 1 vuosi sitten
  maqiang 487eb66ea4 Merge branch 'master' into mq_dev 1 vuosi sitten
  maqiang ea8d2be759 领取任务单增加弹窗确认; 1 vuosi sitten
  周素华 dcfa81de4e Merge branch 'zhou_dev' 1 vuosi sitten
  maqiang b13782d136 增加收获扦样任务单页-基本信息数据验证逻辑; 1 vuosi sitten
  maqiang e851c65925 修改版本号:v0.0.16 1 vuosi sitten
  maqiang 7174a8a37a 修改扫一扫入口icon、修改扫一扫页面UI,收获扦样单乡镇村改为编辑框; 1 vuosi sitten

+ 22 - 0
android/app/src/main/res/layout/toast_custom.xml

@@ -0,0 +1,22 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
+    xmlns:tools="http://schemas.android.com/tools"
4
+    android:layout_width="wrap_content"
5
+    android:layout_height="wrap_content"
6
+    android:layout_gravity="center_horizontal"
7
+    android:layout_marginStart="50dp"
8
+    android:layout_marginEnd="50dp">
9
+
10
+    <TextView
11
+        android:id="@+id/text"
12
+        android:layout_width="wrap_content"
13
+        android:layout_height="wrap_content"
14
+        android:background="#CC000000"
15
+        android:paddingStart="16dp"
16
+        android:paddingTop="10dp"
17
+        android:paddingEnd="16dp"
18
+        android:paddingBottom="10dp"
19
+        android:textStyle="bold"
20
+        android:textColor="#FFFFFF"
21
+        tools:text="Toast should be short." />
22
+</FrameLayout>

BIN
assets/images/home_scan.webp


BIN
assets/images/scan_back.webp


BIN
assets/images/scan_flash.webp


BIN
assets/images/scan_scanning.webp


+ 8 - 0
lib/config/pics.dart

@@ -23,6 +23,8 @@ const String imgHomeListBg = 'assets/images/home_list_bg.webp';
23 23
 const String imgHomeListPzjc = 'assets/images/home_list_pzjc.webp';
24 24
 // 首页列表整仓检验
25 25
 const String imgHomeListZcjy = 'assets/images/home_list_zcjy.webp';
26
+// 首页扫一扫
27
+const String imgHomeScan = 'assets/images/home_scan.webp';
26 28
 
27 29
 // 用户中心账户
28 30
 const String imgUserCenterAccount = 'assets/images/user_center_account.webp';
@@ -34,6 +36,12 @@ const String imgItemArrowRight = 'assets/images/item_arrow_right.webp';
34 36
 // 列表项下箭头
35 37
 const String imgItemArrowDown = 'assets/images/item_arrow_down.webp';
36 38
 
39
+// 扫一扫 返回
40
+const String imgScanBack = 'assets/images/scan_back.webp';
41
+// 扫一扫 闪光灯
42
+const String imgScanFlash= 'assets/images/scan_flash.webp';
43
+// 扫一扫 扫描中
44
+const String imgScanScanning= 'assets/images/scan_scanning.webp';
37 45
 
38 46
 // 搜索图标
39 47
 const String imgBleSearch = 'assets/images/search_ble.png';

+ 15 - 1
lib/main.dart

@@ -64,6 +64,7 @@ class MyApp extends StatelessWidget {
64 64
 
65 65
   @override
66 66
   Widget build(BuildContext context) {
67
+    var theme = Theme.of(context);
67 68
     return MaterialApp(
68 69
       title: '粮食质量管理${kReleaseMode ? '' : '-测试'}',
69 70
       theme: ThemeData(
@@ -78,11 +79,24 @@ class MyApp extends StatelessWidget {
78 79
           backgroundColor: Colors.transparent,
79 80
           systemOverlayStyle: SystemUiOverlayStyle.light,
80 81
         ),
81
-        bottomSheetTheme: const BottomSheetThemeData(
82
+        bottomSheetTheme: theme.bottomSheetTheme.copyWith(
82 83
           backgroundColor: Colors.white,
83 84
           modalBackgroundColor: Colors.white,
84 85
           surfaceTintColor: Colors.white,
85 86
         ),
87
+        dialogTheme: theme.dialogTheme.copyWith(
88
+          backgroundColor: Colors.white,
89
+          surfaceTintColor: Colors.white,
90
+          titleTextStyle: const TextStyle(
91
+            fontSize: 16,
92
+            color: MyColor.c_333333,
93
+            fontWeight: FontWeight.w500,
94
+          ),
95
+          contentTextStyle: const TextStyle(
96
+            fontSize: 14,
97
+            color: MyColor.c_666666,
98
+          ),
99
+        ),
86 100
         useMaterial3: true,
87 101
       ),
88 102
       builder: FlutterSmartDialog.init(),

+ 3 - 0
lib/model/num_converter.dart

@@ -1,5 +1,7 @@
1 1
 import 'package:json_annotation/json_annotation.dart';
2 2
 
3
+import '../main.dart';
4
+
3 5
 /// Json解析num类型
4 6
 class NumConverter extends JsonConverter<num?, dynamic> {
5 7
   const NumConverter();
@@ -13,6 +15,7 @@ class NumConverter extends JsonConverter<num?, dynamic> {
13 15
       try {
14 16
         return num.parse(json);
15 17
       } catch (e) {
18
+        logger.e(e);
16 19
         return null;
17 20
       }
18 21
     }

+ 1 - 1
lib/page/filter/filter_page.dart

@@ -140,7 +140,7 @@ class _FilterPageState extends BaseState<FilterPage> {
140 140
             ),
141 141
             CardWidgets.buildMenu(
142 142
               false,
143
-              '样品级',
143
+              '样品级',
144 144
               ypdjList,
145 145
               ypdj,
146 146
               (_, sel) {},

+ 1 - 1
lib/page/home/home_page.dart

@@ -76,7 +76,7 @@ class _HomePageState extends BaseState<HomePage> with AutomaticKeepAliveClientMi
76 76
       child: Container(
77 77
         padding: const EdgeInsets.symmetric(horizontal: 16),
78 78
         alignment: Alignment.center,
79
-        child: const Text('扫一扫', style: TextStyle(fontSize: 14, color: Colors.white)),
79
+        child: Image.asset(imgHomeScan, height: 24,width: 24),
80 80
       ),
81 81
     );
82 82
   }

+ 2 - 4
lib/page/login/login_page.dart

@@ -12,13 +12,10 @@ import 'package:lszlgl/service/user_service.dart';
12 12
 import 'package:lszlgl/widget/button.dart';
13 13
 
14 14
 import '../../config/reresh_config.dart';
15
-import '../../drfit/database.dart';
16 15
 import '../../network/base_dio.dart';
17 16
 import '../../utils/location_utils.dart';
18 17
 import '../../utils/sp_utils.dart';
19 18
 import 'package:lszlgl/service/print_service.dart';
20
-import 'package:path_provider/path_provider.dart';
21
-import 'package:path/path.dart' as p;
22 19
 
23 20
 /// 登录页面
24 21
 class LoginPage extends StatefulWidget {
@@ -46,7 +43,8 @@ class _LoginPageState extends BaseLifecycleState<LoginPage> {
46 43
       await UserService.get().saveLogin(login.data);
47 44
       getSystemData();
48 45
     } on DioException catch (_) {
49
-    } catch (_) {
46
+    } catch (e) {
47
+      logger.e(e);
50 48
       MyNavigator.showToast('获取数据失败');
51 49
     }
52 50
     MyNavigator.dismissLoading();

+ 90 - 16
lib/page/qrcode_scan/qrcode_scan_page.dart

@@ -1,6 +1,9 @@
1 1
 import 'dart:io';
2 2
 
3
+import 'package:flutter/cupertino.dart';
3 4
 import 'package:flutter/material.dart';
5
+import 'package:flutter/services.dart';
6
+import 'package:flutter/widgets.dart';
4 7
 import 'package:lszlgl/page/sample_task/reap_sample_detail/reap_sample_task_page.dart';
5 8
 import 'package:qr_code_scanner/qr_code_scanner.dart';
6 9
 
@@ -14,10 +17,12 @@ class QrCodeScanPage extends StatefulWidget {
14 17
   State<QrCodeScanPage> createState() => _QrCodeScanPageState();
15 18
 }
16 19
 
17
-class _QrCodeScanPageState extends BaseLifecycleState<QrCodeScanPage> {
20
+class _QrCodeScanPageState extends BaseLifecycleState<QrCodeScanPage> with SingleTickerProviderStateMixin {
18 21
   final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
19 22
   Barcode? result;
20 23
   QRViewController? controller;
24
+  late AnimationController _ctrl;
25
+  late Animation<Offset> animation;
21 26
 
22 27
   void _onQRViewCreated(QRViewController controller) {
23 28
     this.controller = controller;
@@ -90,28 +95,89 @@ class _QrCodeScanPageState extends BaseLifecycleState<QrCodeScanPage> {
90 95
   @override
91 96
   void dispose() {
92 97
     controller?.dispose();
98
+    _ctrl.dispose();
93 99
     super.dispose();
94 100
   }
95 101
 
96 102
   @override
103
+  void initState() {
104
+    super.initState();
105
+    // 创建动画控制器
106
+    _ctrl = AnimationController(
107
+      vsync: this,
108
+      duration: const Duration(seconds: 2),
109
+    );
110
+    animation = Tween<Offset>(
111
+      begin: const Offset(0, -0.25),
112
+      end: const Offset(0, 0.25),
113
+    ).animate(_ctrl);
114
+    _ctrl.repeat();
115
+  }
116
+
117
+  @override
97 118
   Widget build(BuildContext context) {
98 119
     return myScaffold(child: buildBody());
99 120
   }
100 121
 
101 122
   Widget buildBody() {
102
-    return Column(
103
-      children: [
104
-        myAppBar(
105
-          title: '扫一扫',
106
-          actions: [buildFlash()],
107
-        ),
108
-        Expanded(
109
-          child: QRView(
110
-            key: qrKey,
111
-            onQRViewCreated: _onQRViewCreated,
123
+    return AnnotatedRegion<SystemUiOverlayStyle>(
124
+      value: SystemUiOverlayStyle.light,
125
+      child: Stack(
126
+        fit: StackFit.expand,
127
+        children: [
128
+          // myAppBar(
129
+          //   title: '扫一扫',
130
+          //   actions: [buildFlash()],
131
+          // ),
132
+          Positioned.fill(
133
+            child: QRView(
134
+              key: qrKey,
135
+              onQRViewCreated: _onQRViewCreated,
136
+            ),
112 137
           ),
113
-        ),
114
-      ],
138
+          Positioned(
139
+            top: 0,
140
+            left: 0,
141
+            right: 0,
142
+            child: buildAppBar(),
143
+          ),
144
+          SlideTransition(
145
+            position: animation,
146
+            child: Image.asset(imgScanScanning, width: double.infinity),
147
+          ),
148
+        ],
149
+      ),
150
+    );
151
+  }
152
+
153
+  Widget buildAppBar() {
154
+    return Padding(
155
+      padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
156
+      child: Stack(
157
+        alignment: Alignment.center,
158
+        children: [
159
+          Positioned(left: 0, child: buildBack()),
160
+          const Text(
161
+            '扫一扫',
162
+            textAlign: TextAlign.center,
163
+            style: TextStyle(color: Colors.white, fontSize: 20),
164
+          ),
165
+          Positioned(
166
+            right: 0,
167
+            child: buildFlash(),
168
+          ),
169
+        ],
170
+      ),
171
+    );
172
+  }
173
+
174
+  Widget buildBack() {
175
+    return GestureDetector(
176
+      onTap: () => MyNavigator.pop(),
177
+      child: Padding(
178
+        padding: const EdgeInsets.symmetric(horizontal: 16),
179
+        child: Image.asset(imgScanBack, width: 24, height: 24),
180
+      ),
115 181
     );
116 182
   }
117 183
 
@@ -119,10 +185,18 @@ class _QrCodeScanPageState extends BaseLifecycleState<QrCodeScanPage> {
119 185
     return GestureDetector(
120 186
       onTap: () => controller?.toggleFlash(),
121 187
       behavior: HitTestBehavior.opaque,
122
-      child: Container(
188
+      child: Padding(
123 189
         padding: const EdgeInsets.symmetric(horizontal: 16),
124
-        alignment: Alignment.center,
125
-        child: const Text('闪光灯', style: TextStyle(fontSize: 14, color: Colors.white)),
190
+        child: Row(
191
+          children: [
192
+            Image.asset(imgScanFlash, width: 24, height: 24),
193
+            const Text(
194
+              '闪光灯',
195
+              textAlign: TextAlign.center,
196
+              style: TextStyle(color: Colors.white, fontSize: 14),
197
+            ),
198
+          ],
199
+        ),
126 200
       ),
127 201
     );
128 202
   }

+ 106 - 52
lib/page/sample_task/reap_sample_detail/reap_sample_basic_detail_page.dart

@@ -18,24 +18,26 @@ import '../../../network/my_api.dart';
18 18
 import '../../../service/user_service.dart';
19 19
 import '../../../utils/file_utils.dart';
20 20
 import '../../../widget/card_item.dart';
21
+import 'reap_sample_task_page.dart';
21 22
 
22 23
 /// 收获扦样-基础信息
23 24
 class ReapSampleBasicDetailPage extends StatefulWidget {
24 25
   final SampleTaskItem? data;
25 26
   final bool detail;
27
+  final ReapSampleTaskController ctrl;
26 28
 
27 29
   const ReapSampleBasicDetailPage(
28 30
     this.data, {
29 31
     super.key,
30 32
     this.detail = true,
33
+    required this.ctrl,
31 34
   });
32 35
 
33 36
   @override
34 37
   State<ReapSampleBasicDetailPage> createState() => _ReapSampleBasicDetailPageState();
35 38
 }
36 39
 
37
-class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasicDetailPage>
38
-    with AutomaticKeepAliveClientMixin {
40
+class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasicDetailPage> with AutomaticKeepAliveClientMixin {
39 41
   SampleTaskItem? data;
40 42
   late bool isDetail;
41 43
 
@@ -46,8 +48,8 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
46 48
   final sheng = null.notifier<CardMenuData?>();
47 49
   final shi = null.notifier<CardMenuData?>();
48 50
   final qu = null.notifier<CardMenuData?>();
49
-  final xian = null.notifier<CardMenuData?>();
50
-  final cun = null.notifier<CardMenuData?>();
51
+  final TextEditingController xian = TextEditingController();
52
+  final TextEditingController cun = TextEditingController();
51 53
 
52 54
   final trxxList = <CardMenuData>[].notifier<List<CardMenuData>>();
53 55
   final trxx = null.notifier<CardMenuData?>();
@@ -59,8 +61,7 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
59 61
   List<CardMenuData> personList = [];
60 62
 
61 63
   /// 获取行政区划列表
62
-  Future<List<CardMenuData>?> getDistrictList(num level, {num? id, bool showLoading = true}) async {
63
-    if (showLoading) MyNavigator.showLoading();
64
+  Future<List<CardMenuData>?> getDistrictList(num level, {num? id}) async {
64 65
     try {
65 66
       var rsp = await MyApi.get().districtList(level, id: id);
66 67
       List<CardMenuData> list = (rsp.data ?? []).map((e) => CardMenuData(e.uname, e.id)).toList();
@@ -69,18 +70,15 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
69 70
       } else if (level == 5) {
70 71
         cunList.value = list;
71 72
       }
72
-      if (showLoading) MyNavigator.dismissLoading();
73 73
       return list;
74 74
     } catch (e) {
75 75
       logger.e(e);
76 76
     }
77
-    if (showLoading) MyNavigator.dismissLoading();
78 77
     return null;
79 78
   }
80 79
 
81 80
   /// 获取土壤信息列表
82 81
   Future<void> getTrxxList() async {
83
-    MyNavigator.showLoading();
84 82
     try {
85 83
       var rsp = await MyApi.get().trxxList();
86 84
       List<CardMenuData> list = [];
@@ -99,38 +97,38 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
99 97
     MyNavigator.dismissLoading();
100 98
   }
101 99
 
102
-  /// 选中行政区划
103
-  void onSelectXzqh(ValueNotifier<CardMenuData?> selNotifier, CardMenuData selData) {
104
-    num level = 100;
105
-    if (selNotifier == xian) {
106
-      level = 4;
107
-      data?.xiangXzqh = selData.value;
108
-      data?.cunXzqh = null;
109
-      cun.value = null;
110
-      cunList.value = [];
111
-    } else if (selNotifier == cun) {
112
-      level = 5;
113
-      data?.cunXzqh = selData.value;
114
-    }
115
-    if (level < 5) {
116
-      // 获取下一个等级的菜单数据
117
-      getDistrictList(level + 1, id: selData.value ?? 0);
118
-    }
119
-  }
120
-
121
-  /// 获取编辑数据
122
-  void getEditData() async {
123
-    MyNavigator.showLoading();
124
-    // 县
125
-    if (data?.quXzqh != null) {
126
-      await getDistrictList(4, id: data?.quXzqh, showLoading: false);
127
-    }
128
-    // 村
129
-    if (data?.xiangXzqh != null) {
130
-      await getDistrictList(5, id: data?.xiangXzqh, showLoading: false);
131
-    }
132
-    MyNavigator.dismissLoading();
133
-  }
100
+  // /// 选中行政区划
101
+  // void onSelectXzqh(ValueNotifier<CardMenuData?> selNotifier, CardMenuData selData) {
102
+  //   num level = 100;
103
+  //   if (selNotifier == xian) {
104
+  //     level = 4;
105
+  //     data?.xiangXzqh = selData.value;
106
+  //     data?.cunXzqh = null;
107
+  //     cun.value = null;
108
+  //     cunList.value = [];
109
+  //   } else if (selNotifier == cun) {
110
+  //     level = 5;
111
+  //     data?.cunXzqh = selData.value;
112
+  //   }
113
+  //   if (level < 5) {
114
+  //     // 获取下一个等级的菜单数据
115
+  //     getDistrictList(level + 1, id: selData.value ?? 0);
116
+  //   }
117
+  // }
118
+
119
+  // /// 获取编辑数据
120
+  // void getEditData() async {
121
+  //   MyNavigator.showLoading();
122
+  //   // 县
123
+  //   if (data?.quXzqh != null) {
124
+  //     await getDistrictList(4, id: data?.quXzqh, showLoading: false);
125
+  //   }
126
+  //   // 村
127
+  //   if (data?.xiangXzqh != null) {
128
+  //     await getDistrictList(5, id: data?.xiangXzqh, showLoading: false);
129
+  //   }
130
+  //   MyNavigator.dismissLoading();
131
+  // }
134 132
 
135 133
   void getPersonData() async {
136 134
     try {
@@ -191,14 +189,14 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
191 189
       shi.value = null;
192 190
       qu.value = null;
193 191
       data?.xiangXzqhName = null;
194
-      xian.value = null;
192
+      xian.text = '';
195 193
       data?.cunXzqhName = null;
196
-      cun.value = null;
194
+      cun.text = '';
197 195
 
198 196
       MyNavigator.showLoading();
199 197
       bool stepSuccess = false;
200 198
       // 省
201
-      var provinceList = await getDistrictList(1, showLoading: false);
199
+      var provinceList = await getDistrictList(1);
202 200
       if (provinceList != null) {
203 201
         for (CardMenuData item in provinceList) {
204 202
           if (item.name == province) {
@@ -210,7 +208,7 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
210 208
         if (stepSuccess) {
211 209
           stepSuccess = false;
212 210
           // 市
213
-          var cityList = await getDistrictList(2, id: sheng.value!.value, showLoading: false);
211
+          var cityList = await getDistrictList(2, id: sheng.value!.value);
214 212
           if (cityList == null) return;
215 213
           for (CardMenuData item in cityList) {
216 214
             if (item.name == city) {
@@ -224,7 +222,7 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
224 222
             stepSuccess = false;
225 223
             // 区
226 224
             if (district.isNotEmpty) {
227
-              var districtList = await getDistrictList(3, id: shi.value!.value, showLoading: false);
225
+              var districtList = await getDistrictList(3, id: shi.value!.value);
228 226
               if (districtList == null) return;
229 227
               for (CardMenuData item in districtList) {
230 228
                 if (item.name == district) {
@@ -242,8 +240,8 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
242 240
               // 乡、村
243 241
               data?.xiangXzqhName = street;
244 242
               data?.cunXzqhName = streetNumber;
245
-              xian.value = CardMenuData(street, null);
246
-              cun.value = CardMenuData(streetNumber, null);
243
+              xian.text = street;
244
+              cun.text = streetNumber;
247 245
             }
248 246
           }
249 247
         }
@@ -389,6 +387,41 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
389 387
     }
390 388
   }
391 389
 
390
+  /// 校验数据
391
+  bool verifyData() {
392
+    // 扦样/陪同人员
393
+    if ((data?.dgryName ?? '').isEmpty) {
394
+      MyNavigator.showToast('扦样/陪同人员不能为空');
395
+      return false;
396
+    }
397
+    // 乡镇
398
+    if ((data?.xiangXzqhName ?? '').isEmpty) {
399
+      MyNavigator.showToast('乡镇不能为空');
400
+      return false;
401
+    }
402
+    // 村
403
+    if ((data?.cunXzqhName ?? '').isEmpty) {
404
+      MyNavigator.showToast('村不能为空');
405
+      return false;
406
+    }
407
+    // 扦样地点经纬度
408
+    if ((data?.qyddjwd ?? '').isEmpty) {
409
+      MyNavigator.showToast('扦样地点经纬度不能为空');
410
+      return false;
411
+    }
412
+    // 种植面积(亩地)
413
+    if (data?.zzmj == null) {
414
+      MyNavigator.showToast('种植面积不能为空');
415
+      return false;
416
+    }
417
+    // 土壤地理类型
418
+    if (data?.trdllx == null) {
419
+      MyNavigator.showToast('土壤地理类型不能为空');
420
+      return false;
421
+    }
422
+    return true;
423
+  }
424
+
392 425
   @override
393 426
   bool get wantKeepAlive => true;
394 427
 
@@ -396,14 +429,16 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
396 429
   void onInit() {
397 430
     data = widget.data;
398 431
     isDetail = widget.detail;
432
+    widget.ctrl.verifyData = verifyData;
433
+
399 434
     // 土壤信息
400 435
     getTrxxList();
401 436
 
402 437
     if (data?.sheng != null) sheng.value = CardMenuData(data?.sheng, data?.shengXzqh);
403 438
     if (data?.shi != null) shi.value = CardMenuData(data?.shi, data?.shiXzqh);
404 439
     if (data?.qu != null) qu.value = CardMenuData(data?.qu, data?.quXzqh);
405
-    if (data?.xian != null) xian.value = CardMenuData(data?.xian, data?.xiangXzqh);
406
-    if (data?.cun != null) cun.value = CardMenuData(data?.cun, data?.cunXzqh);
440
+    if (data?.xiangXzqhName != null) xian.text = data!.xiangXzqhName!;
441
+    if (data?.cunXzqhName != null) cun.text = data!.cunXzqhName!;
407 442
     qyddjwd.value = data?.qyddjwd;
408 443
     if ((data?.dgryName ?? '0') == '0') {
409 444
       data?.dgryName = UserService.get().getUser()?.nickname;
@@ -417,6 +452,11 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
417 452
   }
418 453
 
419 454
   @override
455
+  void onFirstShow(Duration timeStamp) {
456
+    MyNavigator.showLoading();
457
+  }
458
+
459
+  @override
420 460
   void onDestroy() {
421 461
     LocationUtils.stopLocation();
422 462
     LocationUtils.destroy();
@@ -447,8 +487,22 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
447 487
         sheng.builder((v) => CardItemWidget('省份', rightText: v?.name, bottomLine: true)),
448 488
         shi.builder((v) => CardItemWidget('市/州', rightText: v?.name, bottomLine: true)),
449 489
         qu.builder((v) => CardItemWidget('区县', rightText: v?.name, bottomLine: true)),
450
-        xian.builder((v) => CardItemWidget('乡镇', rightText: v?.name, bottomLine: true)),
451
-        cun.builder((v) => CardItemWidget('村', rightText: v?.name, bottomLine: true)),
490
+        // xian.builder((v) => CardItemWidget('乡镇', rightText: v?.name, bottomLine: true)),
491
+        // cun.builder((v) => CardItemWidget('村', rightText: v?.name, bottomLine: true)),
492
+        CardWidgets.buildEdit(
493
+          isDetail,
494
+          ctrl: xian,
495
+          '乡镇',
496
+          data?.xiangXzqhName?.toString(),
497
+          onChanged: (value) => data?.xiangXzqhName = value.isEmpty ? null : value,
498
+        ),
499
+        CardWidgets.buildEdit(
500
+          isDetail,
501
+          ctrl: cun,
502
+          '村',
503
+          data?.cunXzqhName?.toString(),
504
+          onChanged: (value) => data?.cunXzqhName = value.isEmpty ? null : value,
505
+        ),
452 506
         qyddjwd.builder(
453 507
           (v) => CardItemWidget(
454 508
             '扦样地点经纬度',

+ 14 - 7
lib/page/sample_task/reap_sample_detail/reap_sample_disaster_detail_page.dart

@@ -6,24 +6,26 @@ import 'package:lszlgl/widget/card_item.dart';
6 6
 import '../../../model/rsp/dict_rsp.dart';
7 7
 import '../../../model/rsp/sample_task_rsp.dart';
8 8
 import '../../../service/dict_service.dart';
9
+import 'reap_sample_task_page.dart';
9 10
 
10 11
 /// 收获扦样-灾害污染
11 12
 class ReapSampleDisasterDetailPage extends StatefulWidget {
12 13
   final SampleTaskItem? data;
13 14
   final bool detail;
15
+  final ReapSampleTaskController ctrl;
14 16
 
15 17
   const ReapSampleDisasterDetailPage(
16 18
     this.data, {
17 19
     super.key,
18 20
     this.detail = true,
21
+    required this.ctrl,
19 22
   });
20 23
 
21 24
   @override
22 25
   State<ReapSampleDisasterDetailPage> createState() => _ReapSampleDisasterDetailPageState();
23 26
 }
24 27
 
25
-class _ReapSampleDisasterDetailPageState extends BaseLifecycleState<ReapSampleDisasterDetailPage>
26
-    with AutomaticKeepAliveClientMixin {
28
+class _ReapSampleDisasterDetailPageState extends BaseLifecycleState<ReapSampleDisasterDetailPage> with AutomaticKeepAliveClientMixin {
27 29
   SampleTaskItem? data;
28 30
   late bool isDetail;
29 31
 
@@ -76,17 +78,25 @@ class _ReapSampleDisasterDetailPageState extends BaseLifecycleState<ReapSampleDi
76 78
     num? selValue,
77 79
   ) {
78 80
     // 菜单数据
79
-    notifier.value =
80
-        (DictService.getDictList(type) ?? []).map((e) => CardMenuData(e.label, num.parse(e.value ?? '0'))).toList();
81
+    notifier.value = (DictService.getDictList(type) ?? []).map((e) => CardMenuData(e.label, num.parse(e.value ?? '0'))).toList();
81 82
     // 选中项
82 83
     DictRsp? dict = DictService.getDict(type, value: selValue);
83 84
     if (dict != null) selNotifier.value = CardMenuData(dict.label, dict.value);
84 85
   }
85 86
 
87
+  /// 校验数据
88
+  bool verifyData() {
89
+    return true;
90
+  }
91
+
92
+  @override
93
+  bool get wantKeepAlive => true;
94
+
86 95
   @override
87 96
   void onInit() {
88 97
     data = widget.data;
89 98
     isDetail = widget.detail;
99
+    widget.ctrl.verifyData = verifyData;
90 100
 
91 101
     // 工厂排污
92 102
     setBoolMenuSelNotifier(zztdzwsfygcpw, data?.zztdzwsfygcpw);
@@ -115,9 +125,6 @@ class _ReapSampleDisasterDetailPageState extends BaseLifecycleState<ReapSampleDi
115 125
   }
116 126
 
117 127
   @override
118
-  bool get wantKeepAlive => true;
119
-
120
-  @override
121 128
   Widget build(BuildContext context) {
122 129
     super.build(context);
123 130
     return SingleChildScrollView(child: buildList());

+ 23 - 15
lib/page/sample_task/reap_sample_detail/reap_sample_medicine_detail_page.dart

@@ -6,24 +6,26 @@ import '../../../model/rsp/sample_task_rsp.dart';
6 6
 import '../../../utils/date_time_utils.dart';
7 7
 import '../../../utils/input_formatter.dart';
8 8
 import '../../../widget/button.dart';
9
+import 'reap_sample_task_page.dart';
9 10
 
10 11
 /// 收获扦样-用药情况
11 12
 class ReapSampleMedicineDetailPage extends StatefulWidget {
12 13
   final SampleTaskItem? data;
13 14
   final bool detail;
15
+  final ReapSampleTaskController ctrl;
14 16
 
15 17
   const ReapSampleMedicineDetailPage(
16 18
     this.data, {
17 19
     super.key,
18 20
     this.detail = true,
21
+    required this.ctrl,
19 22
   });
20 23
 
21 24
   @override
22 25
   State<ReapSampleMedicineDetailPage> createState() => _ReapSampleMedicineDetailPageState();
23 26
 }
24 27
 
25
-class _ReapSampleMedicineDetailPageState extends BaseLifecycleState<ReapSampleMedicineDetailPage>
26
-    with AutomaticKeepAliveClientMixin {
28
+class _ReapSampleMedicineDetailPageState extends BaseLifecycleState<ReapSampleMedicineDetailPage> with AutomaticKeepAliveClientMixin {
27 29
   SampleTaskItem? data;
28 30
   late bool isDetail;
29 31
 
@@ -52,38 +54,44 @@ class _ReapSampleMedicineDetailPageState extends BaseLifecycleState<ReapSampleMe
52 54
   }
53 55
 
54 56
   void onRemove(UseMedicineItem item) async {
55
-    var delete = await showDialog(
56
-      context: context,
57
+    var delete = await MyNavigator.showDialog(
58
+      tag: 'delete',
57 59
       builder: (_) => AlertDialog(
58
-        title: const Text('是否删除用药记录?'),
60
+        title: const Text('系统提示'),
61
+        content: const Text('是否删除用药记录?'),
59 62
         actions: [
60 63
           MyButton(
61 64
             '删除',
62 65
             alignment: null,
63 66
             backgroundColor: const Color(0xFFCE615A),
64
-            onTap: () => MyNavigator.pop(true),
67
+            onTap: () => MyNavigator.dismiss(tag: 'delete', result: true),
65 68
           ),
66
-          MyButton('取消', alignment: null, onTap: () => MyNavigator.pop()),
69
+          MyButton('取消', alignment: null, onTap: () => MyNavigator.dismiss(tag: 'delete')),
67 70
         ],
68 71
       ),
69 72
     );
70
-    if (delete ?? false) {
71
-      setState(() {
72
-        data?.codeUseMedicineList?.remove(item);
73
-      });
74
-    }
73
+    if (!(delete ?? false)) return;
74
+    setState(() {
75
+      data?.codeUseMedicineList?.remove(item);
76
+    });
75 77
   }
76 78
 
79
+  /// 校验数据
80
+  bool verifyData() {
81
+    return true;
82
+  }
83
+
84
+  @override
85
+  bool get wantKeepAlive => true;
86
+
77 87
   @override
78 88
   void onInit() {
79 89
     data = widget.data;
80 90
     isDetail = widget.detail;
91
+    widget.ctrl.verifyData = verifyData;
81 92
   }
82 93
 
83 94
   @override
84
-  bool get wantKeepAlive => true;
85
-
86
-  @override
87 95
   Widget build(BuildContext context) {
88 96
     super.build(context);
89 97
     return SingleChildScrollView(child: buildList());

+ 16 - 7
lib/page/sample_task/reap_sample_detail/reap_sample_org_detail_page.dart

@@ -3,17 +3,20 @@ import 'package:lszlgl/base/base_lifecycle_state.dart';
3 3
 import 'package:lszlgl/widget/card_item.dart';
4 4
 
5 5
 import '../../../model/rsp/sample_task_rsp.dart';
6
+import 'reap_sample_task_page.dart';
6 7
 
7 8
 /// 收获扦样-检验机构
8 9
 class ReapSampleOrgDetailPage extends StatefulWidget {
9 10
   final SampleTaskItem? data;
10 11
   final bool detail;
12
+  final ReapSampleTaskController ctrl;
11 13
 
12 14
   const ReapSampleOrgDetailPage(
13
-      this.data, {
14
-        super.key,
15
-        this.detail = true,
16
-      });
15
+    this.data, {
16
+    super.key,
17
+    this.detail = true,
18
+    required this.ctrl,
19
+  });
17 20
 
18 21
   @override
19 22
   State<ReapSampleOrgDetailPage> createState() => _ReapSampleOrgDetailPageState();
@@ -27,9 +30,18 @@ class _ReapSampleOrgDetailPageState extends BaseLifecycleState<ReapSampleOrgDeta
27 30
   String? aqjg;
28 31
   String? aqdz;
29 32
 
33
+  /// 校验数据
34
+  bool verifyData() {
35
+    return true;
36
+  }
37
+
38
+  @override
39
+  bool get wantKeepAlive => true;
40
+
30 41
   @override
31 42
   void onInit() {
32 43
     data = widget.data;
44
+    widget.ctrl.verifyData = verifyData;
33 45
     var list = data?.jyjgxxRespVOList;
34 46
     if (list != null && list.isNotEmpty) {
35 47
       for (JyjgxxItem item in list) {
@@ -45,9 +57,6 @@ class _ReapSampleOrgDetailPageState extends BaseLifecycleState<ReapSampleOrgDeta
45 57
   }
46 58
 
47 59
   @override
48
-  bool get wantKeepAlive => true;
49
-
50
-  @override
51 60
   Widget build(BuildContext context) {
52 61
     super.build(context);
53 62
     return SingleChildScrollView(child: buildList());

+ 32 - 25
lib/page/sample_task/reap_sample_detail/reap_sample_task_page.dart

@@ -19,11 +19,9 @@ import 'package:lszlgl/page/signature/signature_page.dart';
19 19
 import '../../../base/base_vm.dart';
20 20
 import '../../../main.dart';
21 21
 import '../../../network/my_api.dart';
22
-import '../../../plugin/bluetooth_plugin.dart';
23 22
 import '../../../utils/file_utils.dart';
24 23
 import '../../../widget/button.dart';
25 24
 import '../../../widget/page_widget.dart';
26
-import 'dart:ui' as ui;
27 25
 
28 26
 class ReapSampleTaskPageArgs {
29 27
   final bool detail;
@@ -40,6 +38,10 @@ class ReapSampleTaskPageArgs {
40 38
   }
41 39
 }
42 40
 
41
+class ReapSampleTaskController {
42
+  bool Function()? verifyData;
43
+}
44
+
43 45
 /// 收获扦样任务
44 46
 class ReapSampleTaskPage extends StatefulWidget {
45 47
   final ReapSampleTaskPageArgs args;
@@ -63,6 +65,7 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
63 65
   late PageController pageCtrl;
64 66
 
65 67
   late List<String> tabTextList;
68
+  late List<ReapSampleTaskController> ctrlList;
66 69
   late List<Widget> pageList;
67 70
 
68 71
   ValueNotifier<int> tabIndex = ValueNotifier(0);
@@ -86,7 +89,14 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
86 89
   }
87 90
 
88 91
   void submit() async {
89
-    SampleTaskItem req = (pageStatus.value.data ?? SampleTaskItem());
92
+    // 空值判断
93
+    for (int i = 0; i < ctrlList.length; i++) {
94
+      if (!(ctrlList[i].verifyData?.call() ?? true)) {
95
+        pageCtrl.jumpToPage(i);
96
+        return;
97
+      }
98
+    }
99
+    SampleTaskItem req = pageStatus.value.data!;
90 100
     // 去签名
91 101
     var args = SignaturePageArgs(count: req.dgryName?.split(',').length ?? 0);
92 102
     List<Uint8List?>? list = await MyRouter.startSignature(args: args);
@@ -132,17 +142,18 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
132 142
         pageStatus.update(pageStatus.value.success(data: data));
133 143
       }
134 144
     } catch (e) {
145
+      logger.e(e);
135 146
       pageStatus.update(pageStatus.value.error());
136 147
     }
137 148
   }
138 149
 
139 150
   void cratePageList(SampleTaskItem data) {
140 151
     pageList = [
141
-      ReapSampleBasicDetailPage(data, detail: args.detail),
142
-      ReapSampleVarietyDetailPage(data, detail: args.detail),
143
-      ReapSampleDisasterDetailPage(data, detail: args.detail),
144
-      ReapSampleMedicineDetailPage(data, detail: args.detail),
145
-      ReapSampleOrgDetailPage(data, detail: args.detail),
152
+      ReapSampleBasicDetailPage(data, detail: args.detail, ctrl: ctrlList[0]),
153
+      ReapSampleVarietyDetailPage(data, detail: args.detail, ctrl: ctrlList[1]),
154
+      ReapSampleDisasterDetailPage(data, detail: args.detail, ctrl: ctrlList[2]),
155
+      ReapSampleMedicineDetailPage(data, detail: args.detail, ctrl: ctrlList[3]),
156
+      ReapSampleOrgDetailPage(data, detail: args.detail, ctrl: ctrlList[4]),
146 157
     ];
147 158
   }
148 159
 
@@ -150,6 +161,10 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
150 161
 
151 162
   /// 查看二维码
152 163
   void showQRCode() {
164
+    if (pageStatus.value.data?.ewmfilePictureList?.isEmpty ?? true) {
165
+      MyNavigator.showToast('没有二维码');
166
+      return;
167
+    }
153 168
     UrlItem picInfo = pageStatus.value.data!.ewmfilePictureList!.first;
154 169
     MyNavigator.showDialog(
155 170
       builder: (_) => Container(
@@ -229,6 +244,7 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
229 244
     super.initState();
230 245
     args = widget.args;
231 246
     tabTextList = ['基础信息', '品种信息', '灾害污染', '用药情况', '检验机构'];
247
+    ctrlList = tabTextList.map((e) => ReapSampleTaskController()).toList();
232 248
     pageCtrl = PageController();
233 249
   }
234 250
 
@@ -307,9 +323,8 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
307 323
       child: GestureDetector(
308 324
         behavior: HitTestBehavior.opaque,
309 325
         onTap: () {
310
-          tabIndex.value = index;
311 326
           if ((pageCtrl.page?.toInt() ?? 0) == index) return;
312
-          pageCtrl.jumpToPage(index);
327
+          pageCtrl.animateToPage(index, duration: const Duration(milliseconds: 200), curve: Curves.linear);
313 328
         },
314 329
         child: Container(
315 330
           alignment: Alignment.center,
@@ -362,15 +377,12 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
362 377
   }
363 378
 
364 379
   Widget buildButton() {
365
-    Widget child;
380
+    if (args.detail) return const SizedBox.shrink();
366 381
     EdgeInsets margin = EdgeInsets.only(left: 4, right: 4, top: 12, bottom: getBottomPadding(12));
367
-    Widget ewmWidget = (pageStatus.value.data?.ewmfilePictureList ?? []).isEmpty
368
-        ? const SizedBox.shrink()
369
-        : Expanded(child: MyButton('查看二维码', onTap: showQRCode, margin: margin));
370
-    if (args.detail) {
371
-      child = Row(children: [ewmWidget]);
372
-    } else {
373
-      child = tabIndex.builder((v) {
382
+    return Container(
383
+      color: const Color(0xFFF1F7F6),
384
+      padding: const EdgeInsets.symmetric(horizontal: 8),
385
+      child: tabIndex.builder((v) {
374 386
         // 第一页
375 387
         if (v == 0) return MyButton('下一步', onTap: next, margin: margin);
376 388
         // 最后一页
@@ -378,7 +390,7 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
378 390
           return Row(
379 391
             children: [
380 392
               Expanded(child: MyButton('上一步', onTap: previous, margin: margin)),
381
-              ewmWidget,
393
+              Expanded(child: MyButton('查看二维码', onTap: showQRCode, margin: margin)),
382 394
               Expanded(child: MyButton('提交', onTap: submit, margin: margin)),
383 395
             ],
384 396
           );
@@ -389,12 +401,7 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
389 401
             Expanded(child: MyButton('下一步', onTap: next, margin: margin)),
390 402
           ],
391 403
         );
392
-      });
393
-    }
394
-    return Container(
395
-      color: const Color(0xFFF1F7F6),
396
-      padding: const EdgeInsets.symmetric(horizontal: 8),
397
-      child: child,
404
+      }),
398 405
     );
399 406
   }
400 407
 }

+ 90 - 16
lib/page/sample_task/reap_sample_detail/reap_sample_variety_detail_page.dart

@@ -1,5 +1,6 @@
1 1
 import 'package:flutter/material.dart';
2 2
 import 'package:lszlgl/base/base_lifecycle_state.dart';
3
+import 'package:lszlgl/main.dart';
3 4
 import 'package:lszlgl/service/dict_service.dart';
4 5
 import 'package:lszlgl/utils/string_utils.dart';
5 6
 import 'package:lszlgl/widget/card_item.dart';
@@ -10,24 +11,26 @@ import '../../../network/my_api.dart';
10 11
 import '../../../utils/date_time_utils.dart';
11 12
 import '../../../utils/input_formatter.dart';
12 13
 import '../../../widget/button.dart';
14
+import 'reap_sample_task_page.dart';
13 15
 
14 16
 /// 收获扦样-品种信息
15 17
 class ReapSampleVarietyDetailPage extends StatefulWidget {
16 18
   final SampleTaskItem? data;
17 19
   final bool detail;
20
+  final ReapSampleTaskController ctrl;
18 21
 
19 22
   const ReapSampleVarietyDetailPage(
20 23
     this.data, {
21 24
     super.key,
22 25
     this.detail = true,
26
+    required this.ctrl,
23 27
   });
24 28
 
25 29
   @override
26 30
   State<ReapSampleVarietyDetailPage> createState() => _ReapSampleVarietyDetailPageState();
27 31
 }
28 32
 
29
-class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVarietyDetailPage>
30
-    with AutomaticKeepAliveClientMixin {
33
+class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVarietyDetailPage> with AutomaticKeepAliveClientMixin {
31 34
   SampleTaskItem? data;
32 35
   late bool isDetail;
33 36
   late Widget arrowDown;
@@ -57,7 +60,6 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
57 60
 
58 61
   /// 获取粮食信息列表
59 62
   Future<void> getLsxxList() async {
60
-    MyNavigator.showLoading();
61 63
     try {
62 64
       var rsp = await MyApi.get().lsxxList(data?.cypzName ?? '');
63 65
       List<CardMenuData> list = [];
@@ -70,7 +72,9 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
70 72
         }
71 73
       }
72 74
       lspzList.value = list;
73
-    } catch (e) {}
75
+    } catch (e) {
76
+      logger.e(e);
77
+    }
74 78
     MyNavigator.dismissLoading();
75 79
   }
76 80
 
@@ -112,32 +116,98 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
112 116
   }
113 117
 
114 118
   void onRemove(int index, NonghuItem item) async {
115
-    var delete = await showDialog(
116
-      context: context,
119
+    var delete = await MyNavigator.showDialog(
120
+      tag: 'delete',
117 121
       builder: (_) => AlertDialog(
118
-        title: const Text('是否删除扦样农户信息?'),
122
+        title: const Text('系统提示'),
123
+        content: const Text('是否删除扦样农户信息?'),
119 124
         actions: [
120 125
           MyButton(
121 126
             '删除',
122 127
             alignment: null,
123 128
             backgroundColor: const Color(0xFFCE615A),
124
-            onTap: () => MyNavigator.pop(true),
129
+            onTap: () {
130
+              if (data!.codeSamplingNonghuList!.length > 1) {
131
+                MyNavigator.dismiss(tag: 'delete', result: true);
132
+              } else {
133
+                MyNavigator.showToast('必须有一条扦样农户信息');
134
+                MyNavigator.dismiss(tag: 'delete');
135
+              }
136
+            },
125 137
           ),
126
-          MyButton('取消', alignment: null, onTap: () => MyNavigator.pop()),
138
+          MyButton('取消', alignment: null, onTap: () => MyNavigator.dismiss(tag: 'delete')),
127 139
         ],
128 140
       ),
129 141
     );
130
-    if (delete ?? false) {
131
-      setState(() {
132
-        data?.codeSamplingNonghuList?.remove(item);
133
-      });
142
+    if (!(delete ?? false)) return;
143
+    setState(() {
144
+      data?.codeSamplingNonghuList?.remove(item);
145
+    });
146
+  }
147
+
148
+  /// 校验数据
149
+  bool verifyData() {
150
+    // 粮食品类
151
+    if ((data?.lspz ?? '').isEmpty) {
152
+      MyNavigator.showToast('粮食品类不能为空');
153
+      return false;
154
+    }
155
+    // 是否优质品种
156
+    if (data?.sfyzpz == null) {
157
+      MyNavigator.showToast('是否优质品种不能为空');
158
+      return false;
159
+    }
160
+    // 品种优质类型
161
+    if (data?.sfyzpz == 0 && data?.yzpzlx == null) {
162
+      MyNavigator.showToast('品种优质类型不能为空');
163
+      return false;
164
+    }
165
+    debugPrint('天气情况: ${data?.tqqk}');
166
+    // 天气情况
167
+    if ((data?.tqqk ?? 0) == 0) {
168
+      MyNavigator.showToast('天气情况不能为空');
169
+      return false;
170
+    }
171
+    // 收获时间
172
+    if ((data?.shsj ?? '').isEmpty) {
173
+      MyNavigator.showToast('收获时间不能为空');
174
+      return false;
175
+    }
176
+    // 扦样时间
177
+    if ((data?.qysj ?? '').isEmpty) {
178
+      MyNavigator.showToast('扦样时间不能为空');
179
+      return false;
134 180
     }
181
+    // 农户信息
182
+    for (var item in data?.codeSamplingNonghuList ?? <NonghuItem>[]) {
183
+      if (item.qysl == null) {
184
+        MyNavigator.showToast('扦样数量不能为空');
185
+        return false;
186
+      }
187
+      if (item.qydbsl == null) {
188
+        MyNavigator.showToast('扦样代表数量不能为空');
189
+        return false;
190
+      }
191
+      if ((item.lxfs ?? '').isEmpty) {
192
+        MyNavigator.showToast('联系方式不能为空');
193
+        return false;
194
+      }
195
+      if ((item.bdcnhhhzs ?? '').isEmpty) {
196
+        MyNavigator.showToast('被调查农户或合作社不能为空');
197
+        return false;
198
+      }
199
+    }
200
+    return true;
135 201
   }
136 202
 
137 203
   @override
204
+  bool get wantKeepAlive => true;
205
+
206
+  @override
138 207
   void onInit() {
139 208
     data = widget.data;
140 209
     isDetail = widget.detail;
210
+    widget.ctrl.verifyData = verifyData;
141 211
     arrowDown = Image.asset(imgItemArrowDown, width: 20, color: const Color(0xFF01B2C8));
142 212
 
143 213
     // 粮食品类菜单数据
@@ -164,12 +234,16 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
164 234
       return menu;
165 235
     }).toList();
166 236
     if (!isDetail && (data?.codeSamplingNonghuList ?? []).isEmpty) {
167
-      data?.codeSamplingNonghuList = [NonghuItem()];
237
+      setState(() {
238
+        data?.codeSamplingNonghuList = [NonghuItem()];
239
+      });
168 240
     }
169 241
   }
170 242
 
171 243
   @override
172
-  bool get wantKeepAlive => true;
244
+  void onFirstShow(Duration timeStamp) {
245
+    MyNavigator.showLoading();
246
+  }
173 247
 
174 248
   @override
175 249
   Widget build(BuildContext context) {
@@ -181,7 +255,7 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
181 255
     return Column(
182 256
       children: [
183 257
         CardItemWidget('采样品种', rightText: data?.cypzName, bottomLine: true),
184
-        CardItemWidget('样品级', rightText: DictService.getLabel(DictType.ypdj, value: data?.ypdj), bottomLine: true),
258
+        CardItemWidget('样品级', rightText: DictService.getLabel(DictType.ypdj, value: data?.ypdj), bottomLine: true),
185 259
         CardWidgets.buildMenu(
186 260
           isDetail,
187 261
           '粮食品类',

+ 20 - 0
lib/page/sample_task/sample_task_list_page.dart

@@ -1,5 +1,6 @@
1 1
 import 'package:easy_refresh/easy_refresh.dart';
2 2
 import 'package:flutter/material.dart';
3
+import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
3 4
 import 'package:lszlgl/base/base_lifecycle_state.dart';
4 5
 import 'package:lszlgl/base/base_vm.dart';
5 6
 import 'package:lszlgl/config/colors.dart';
@@ -13,6 +14,7 @@ import 'package:lszlgl/utils/inject.dart';
13 14
 import 'package:lszlgl/widget/button.dart';
14 15
 import 'package:lszlgl/widget/page_widget.dart';
15 16
 
17
+import '../../main.dart';
16 18
 import 'reap_sample_detail/reap_sample_task_page.dart';
17 19
 import 'stock_sample_detail/stock_sample_task_page.dart';
18 20
 
@@ -52,6 +54,23 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage> wi
52 54
 
53 55
   /// 领取扦样任务
54 56
   void receiveTask(SampleTaskItem data) async {
57
+    var delete = await MyNavigator.showDialog(
58
+      builder: (_) => AlertDialog(
59
+        title: const Text('系统提示'),
60
+        content: const Text('任务认领后不可撤销,请确认是否认领任务!'),
61
+        actions: [
62
+          MyButton(
63
+            '领取',
64
+            alignment: null,
65
+            backgroundColor: const Color(0xFFCE615A),
66
+            onTap: () => MyNavigator.dismiss(status: SmartStatus.dialog, result: true),
67
+          ),
68
+          MyButton('取消', alignment: null, onTap: () => MyNavigator.dismiss()),
69
+        ],
70
+      ),
71
+    );
72
+    if (!(delete ?? false)) return;
73
+
55 74
     MyNavigator.showLoading();
56 75
     try {
57 76
       var rsp = await MyApi.get().receiveSampleTaskSgjc(data.id ?? 0);
@@ -61,6 +80,7 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage> wi
61 80
         vm.refreshAll();
62 81
       }
63 82
     } catch (e) {
83
+      logger.e(e);
64 84
       MyNavigator.dismissLoading();
65 85
     }
66 86
   }

+ 5 - 1
lib/page/sample_task/stock_sample_detail/stock_sample_task_page.dart

@@ -5,6 +5,7 @@ import 'package:lszlgl/config/colors.dart';
5 5
 import 'package:lszlgl/model/rsp/sample_task_rsp.dart';
6 6
 
7 7
 import '../../../base/base_vm.dart';
8
+import '../../../main.dart';
8 9
 import '../../../network/my_api.dart';
9 10
 import '../../../widget/button.dart';
10 11
 import '../../../widget/page_widget.dart';
@@ -83,7 +84,9 @@ class _StockSampleTaskPageState extends BaseLifecycleState<StockSampleTaskPage>
83 84
       } else {
84 85
         MyNavigator.showToast('提交失败');
85 86
       }
86
-    } catch (e) {}
87
+    } catch (e) {
88
+      logger.e(e);
89
+    }
87 90
     MyNavigator.dismissLoading();
88 91
   }
89 92
 
@@ -100,6 +103,7 @@ class _StockSampleTaskPageState extends BaseLifecycleState<StockSampleTaskPage>
100 103
         pageStatus.update(pageStatus.value.success(data: data));
101 104
       }
102 105
     } catch (e) {
106
+      logger.e(e);
103 107
       pageStatus.update(pageStatus.value.error());
104 108
     }
105 109
   }

+ 4 - 1
lib/page/user_center/user_center_page.dart

@@ -7,6 +7,7 @@ import 'package:lszlgl/model/rsp/user_rsp.dart';
7 7
 import 'package:lszlgl/service/user_service.dart';
8 8
 import 'package:lszlgl/widget/card_item.dart';
9 9
 
10
+import '../../main.dart';
10 11
 import '../../network/my_api.dart';
11 12
 
12 13
 /// 用户中心
@@ -33,7 +34,9 @@ class _UserCenterPageState extends BaseLifecycleState<UserCenterPage> with Autom
33 34
       var value = await MyApi.get().userProfile();
34 35
       if (value.data != null) userNotify.value = value.data;
35 36
       await UserService.get().saveUser(value.data);
36
-    } catch (err) {}
37
+    } catch (e) {
38
+      logger.e(e);
39
+    }
37 40
   }
38 41
 
39 42
   @override

+ 1 - 1
lib/router/my_navigator.dart

@@ -355,7 +355,7 @@ class MyNavigator {
355 355
         msg,
356 356
         controller: controller,
357 357
         displayTime: displayTime,
358
-        alignment: alignment,
358
+        alignment: alignment ?? Alignment.center,
359 359
         clickMaskDismiss: clickMaskDismiss,
360 360
         animationType: null,
361 361
         nonAnimationTypes: null,

+ 1 - 0
lib/service/upgrade_service.dart

@@ -80,6 +80,7 @@ class UpgradeService {
80 80
         }
81 81
       }
82 82
     } catch (e) {
83
+      logger.e(e);
83 84
       if (showLoading) MyNavigator.dismissLoading();
84 85
     }
85 86
     checking = false;

+ 1 - 1
lib/widget/card_item.dart

@@ -308,7 +308,7 @@ class CardWidgets {
308 308
       title,
309 309
       rightChild: TextFormField(
310 310
         controller: ctrl,
311
-        initialValue: value,
311
+        initialValue: ctrl == null ? value : null,
312 312
         keyboardType: inputType,
313 313
         textAlign: TextAlign.right,
314 314
         decoration: InputDecoration(

+ 2 - 2
pubspec.yaml

@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
16 16
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17 17
 # In Windows, build-name is used as the major, minor, and patch parts
18 18
 # of the product and file versions while build-number is used as the build suffix.
19
-version: 0.0.15+15
19
+version: 0.0.17+17
20 20
 
21 21
 environment:
22 22
   sdk: '>=3.1.5 <4.0.0'
@@ -39,7 +39,7 @@ dependencies:
39 39
   cupertino_icons: ^1.0.2
40 40
 
41 41
   # 弹框
42
-  flutter_smart_dialog: ^4.9.6
42
+  flutter_smart_dialog: 4.9.6
43 43
   # 轮播图
44 44
   card_swiper: ^3.0.1
45 45
   # 缓存网络图片