Selaa lähdekoodia

修改扦样单列表、扦样单详情内容;

mq 1 vuosi sitten
vanhempi
commit
5b8f6973bb

+ 8 - 8
README.md

@@ -28,15 +28,15 @@ samples, guidance on mobile development, and a full API reference.
28 28
 ### 2024.04.18 app改动点:
29 29
 1. 收获环节<扦样任务单列表>的筛选页面及功能.
30 30
 2. 扦样单列表:
31
-   1. <扦样人员>字段未显示的问题.
32
-   2. <检验指标>和<扦样地区>位置互换.
33
-   3. <检验指标>和<样品等级>为空时不展示.
31
+   1. <扦样人员>字段未显示的问题.
32
+   2. <检验指标>和<扦样地区>位置互换.
33
+   3. <检验指标>和<样品等级>为空时不展示.
34 34
 3. 扦样单详情:
35
-   1. 扦样单位、监测类别、样品编号都去掉.
36
-   2. 高德定位结果填入乡镇和村.
37
-   3. 用药情况删除改为长按弹框确认删除.
38
-   4. 用药情况的施药时间字段有数据时下拉箭头不显示.
39
-   5. 下拉箭头颜色都改为高亮文本颜色.
35
+   1. 扦样单位、监测类别、样品编号都去掉.
36
+   2. 高德定位结果填入乡镇和村.
37
+   3. 用药情况删除改为长按弹框确认删除.
38
+   4. 用药情况的施药时间字段有数据时下拉箭头不显示.
39
+   5. 下拉箭头颜色都改为高亮文本颜色.
40 40
 4. 新增内容:
41 41
    1. 电子签名:点击扦样单提交时跳出签名弹窗,根据扦样人数签名,按钮:重写、上一位、下一位、提交。
42 42
    2. 电子签名图片上传接口:/infra/file/upload

+ 1 - 1
android/app/build.gradle

@@ -36,7 +36,7 @@ android {
36 36
         applicationId "com.szls.lszlgl"
37 37
         // You can update the following values to match your application needs.
38 38
         // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
39
-        minSdkVersion flutter.minSdkVersion
39
+        minSdkVersion 21
40 40
         targetSdkVersion flutter.targetSdkVersion
41 41
         versionCode flutterVersionCode.toInteger()
42 42
         versionName flutterVersionName

+ 1 - 1
android/build.gradle

@@ -1,5 +1,5 @@
1 1
 buildscript {
2
-    ext.kotlin_version = '1.7.10'
2
+    ext.kotlin_version = '1.8.22'
3 3
     repositories {
4 4
         google()
5 5
         mavenCentral()

+ 88 - 7
lib/model/rsp/sample_task_rsp.dart

@@ -2,6 +2,8 @@ import 'package:json_annotation/json_annotation.dart';
2 2
 import 'package:lszlgl/model/num_converter.dart';
3 3
 import 'package:lszlgl/model/string_converter.dart';
4 4
 
5
+import '../../service/dict_service.dart';
6
+
5 7
 part 'sample_task_rsp.g.dart';
6 8
 
7 9
 @JsonSerializable(genericArgumentFactories: true)
@@ -108,6 +110,8 @@ class SampleTaskItem {
108 110
   List<JyjgxxItem>? jyjgxxRespVOList; // 检验机构信息
109 111
   num? jypzStatus; // 检验品质按钮0显示1不显示
110 112
   num? tqqk; // 天气情况
113
+  List<NonghuItem>? codeSamplingNonghuList; // 扦样农户信息
114
+
111 115
 
112 116
   SampleTaskItem({
113 117
     this.id,
@@ -197,7 +201,35 @@ class SampleTaskItem {
197 201
     this.tqqk,
198 202
   });
199 203
 
200
-  factory SampleTaskItem.fromJson(Map<String, dynamic> json) => _$SampleTaskItemFromJson(json);
204
+  SampleTaskItem createUI() {
205
+    // 工厂排污
206
+    zztdzwsfygcpw ??= false;
207
+    // 工厂排污类型
208
+    gcpwlx ??= DictService.getDictFirstNum(DictType.gcpwlx);
209
+    // 水源、土壤污染
210
+    zztdzwsysytrsfywr ??= false;
211
+    // 污染物类型
212
+    wrwlx ??= DictService.getDictFirstNum(DictType.wrwlx);
213
+    // 病虫害
214
+    scgczsffsbjyzdbch ??= false;
215
+    // 病虫害类型
216
+    bchlx ??= DictService.getDictFirstNum(DictType.bchlx);
217
+    // 收获期间是否发生连阴雨天气
218
+    shqjsffslyytq ??= 1;
219
+    // 收获粮食水分是否偏高
220
+    shlssfsfpg ??= 1;
221
+    // 近年来本地是否发生真菌毒素污染
222
+    jnlbdsffszmwr ??= 1;
223
+    // 真菌毒素污染类型
224
+    zjdswrlx ??= DictService.getDictFirstNum(DictType.zjdswrlx);
225
+    // 近年来本地是否发生重金属污染
226
+    jnlbdsfzjswr ??= 1;
227
+    // 重金属污染类型
228
+    zjswrlx ??= DictService.getDictFirstNum(DictType.zjswrlx);
229
+    return this;
230
+  }
231
+
232
+  factory SampleTaskItem.fromJson(Map<String, dynamic> json) => _$SampleTaskItemFromJson(json)..createUI();
201 233
 
202 234
   Map<String, dynamic> toJson() => _$SampleTaskItemToJson(this);
203 235
 
@@ -211,11 +243,11 @@ class SampleTaskItem {
211 243
     map['state'] = state;
212 244
     map['id'] = id;
213 245
 
214
-    map['shengXzqh'] = shengXzqh;
215
-    map['shiXzqh'] = shiXzqh;
216
-    map['quXzqh'] = quXzqh;
217
-    map['xiangXzqh'] = xiangXzqh;
218
-    map['cunXzqh'] = cunXzqh;
246
+    map['shengXzqhName'] = shengXzqhName;
247
+    map['shiXzqhName'] = shiXzqhName;
248
+    map['quXzqhName'] = quXzqhName;
249
+    map['xiangXzqhName'] = xiangXzqhName;
250
+    map['cunXzqhName'] = cunXzqhName;
219 251
 
220 252
     map['qyddjwd'] = qyddjwd;
221 253
     map['zzmj'] = zzmj;
@@ -244,9 +276,16 @@ class SampleTaskItem {
244 276
     map['zjdswrlx'] = zjdswrlx;
245 277
     map['jnlbdsfzjswr'] = jnlbdsfzjswr;
246 278
     map['zjswrlx'] = zjswrlx;
247
-    map['codeUseMedicineList'] = codeUseMedicineList?.map((e) => e.toReqJson()).toList();
279
+    List<UseMedicineItem>? medicineList = codeUseMedicineList?.where((e) => e.id == null).toList();
280
+    if (medicineList != null && medicineList.isNotEmpty) {
281
+      map['codeUseMedicineList'] = medicineList.map((e) => e.toReqJson()).toList();
282
+    }
248 283
     map['dgryName'] = dgryName;
249 284
     map['tqqk'] = tqqk;
285
+    List<NonghuItem>? nonghuList = codeSamplingNonghuList?.where((e) => e.id == null).toList();
286
+    if (nonghuList != null && nonghuList.isNotEmpty) {
287
+      map['codeSamplingNonghuList'] = nonghuList.map((e) => e.toReqJson()).toList();
288
+    }
250 289
 
251 290
     return map;
252 291
   }
@@ -390,6 +429,48 @@ class UseMedicineItem {
390 429
     return map;
391 430
   }
392 431
 }
432
+@JsonSerializable(converters: [NumConverter(), StringConverter()])
433
+class NonghuItem {
434
+  /// ID
435
+  num? id;
436
+  /// 被调查农户或合作社
437
+  String? bdcnhhhzs;
438
+  /// 扦样数量(公斤)
439
+  num? qysl;
440
+  /// 联系方式
441
+  String? lxfs;
442
+  /// 扦样代表数量(公斤)
443
+  num? qydbsl;
444
+  /// 收购扦样任务单ID
445
+  num? zjCodeSamplingTaskDetailsSgjcId;
446
+  /// 库存扦样任务单ID
447
+  num? zjCodeSamplingTaskDetailsKcjcId;
448
+
449
+  NonghuItem({
450
+    this.id,
451
+    this.bdcnhhhzs,
452
+    this.qysl,
453
+    this.lxfs,
454
+    this.qydbsl,
455
+    this.zjCodeSamplingTaskDetailsKcjcId,
456
+    this.zjCodeSamplingTaskDetailsSgjcId,
457
+  });
458
+
459
+  factory NonghuItem.fromJson(Map<String, dynamic> json) => _$NonghuItemFromJson(json);
460
+
461
+  Map<String, dynamic> toJson() => _$NonghuItemToJson(this);
462
+
463
+  Map<String, dynamic> toReqJson() {
464
+    Map<String, dynamic> map = {};
465
+    map['id'] = id;
466
+    map['bdcnhhhzs'] = bdcnhhhzs;
467
+    map['qysl'] = qysl;
468
+    map['lxfs'] = lxfs;
469
+    map['qydbsl'] = qydbsl;
470
+    return map;
471
+  }
472
+}
473
+
393 474
 
394 475
 @JsonSerializable(converters: [NumConverter(), StringConverter()])
395 476
 class SamplingTaskAllotSgjcItem {

+ 30 - 1
lib/model/rsp/sample_task_rsp.g.dart

@@ -122,7 +122,10 @@ SampleTaskItem _$SampleTaskItemFromJson(Map<String, dynamic> json) =>
122 122
           .toList(),
123 123
       jypzStatus: const NumConverter().fromJson(json['jypzStatus']),
124 124
       tqqk: const NumConverter().fromJson(json['tqqk']),
125
-    );
125
+    )..codeSamplingNonghuList =
126
+        (json['codeSamplingNonghuList'] as List<dynamic>?)
127
+            ?.map((e) => NonghuItem.fromJson(e as Map<String, dynamic>))
128
+            .toList();
126 129
 
127 130
 Map<String, dynamic> _$SampleTaskItemToJson(SampleTaskItem instance) =>
128 131
     <String, dynamic>{
@@ -217,6 +220,7 @@ Map<String, dynamic> _$SampleTaskItemToJson(SampleTaskItem instance) =>
217 220
       'jyjgxxRespVOList': instance.jyjgxxRespVOList,
218 221
       'jypzStatus': const NumConverter().toJson(instance.jypzStatus),
219 222
       'tqqk': const NumConverter().toJson(instance.tqqk),
223
+      'codeSamplingNonghuList': instance.codeSamplingNonghuList,
220 224
     };
221 225
 
222 226
 EnterpriseItem _$EnterpriseItemFromJson(Map<String, dynamic> json) =>
@@ -337,6 +341,31 @@ Map<String, dynamic> _$UseMedicineItemToJson(UseMedicineItem instance) =>
337 341
       'zczfw': const StringConverter().toJson(instance.zczfw),
338 342
     };
339 343
 
344
+NonghuItem _$NonghuItemFromJson(Map<String, dynamic> json) => NonghuItem(
345
+      id: const NumConverter().fromJson(json['id']),
346
+      bdcnhhhzs: const StringConverter().fromJson(json['bdcnhhhzs']),
347
+      qysl: const NumConverter().fromJson(json['qysl']),
348
+      lxfs: const StringConverter().fromJson(json['lxfs']),
349
+      qydbsl: const NumConverter().fromJson(json['qydbsl']),
350
+      zjCodeSamplingTaskDetailsKcjcId: const NumConverter()
351
+          .fromJson(json['zjCodeSamplingTaskDetailsKcjcId']),
352
+      zjCodeSamplingTaskDetailsSgjcId: const NumConverter()
353
+          .fromJson(json['zjCodeSamplingTaskDetailsSgjcId']),
354
+    );
355
+
356
+Map<String, dynamic> _$NonghuItemToJson(NonghuItem instance) =>
357
+    <String, dynamic>{
358
+      'id': const NumConverter().toJson(instance.id),
359
+      'bdcnhhhzs': const StringConverter().toJson(instance.bdcnhhhzs),
360
+      'qysl': const NumConverter().toJson(instance.qysl),
361
+      'lxfs': const StringConverter().toJson(instance.lxfs),
362
+      'qydbsl': const NumConverter().toJson(instance.qydbsl),
363
+      'zjCodeSamplingTaskDetailsSgjcId':
364
+          const NumConverter().toJson(instance.zjCodeSamplingTaskDetailsSgjcId),
365
+      'zjCodeSamplingTaskDetailsKcjcId':
366
+          const NumConverter().toJson(instance.zjCodeSamplingTaskDetailsKcjcId),
367
+    };
368
+
340 369
 SamplingTaskAllotSgjcItem _$SamplingTaskAllotSgjcItemFromJson(
341 370
         Map<String, dynamic> json) =>
342 371
     SamplingTaskAllotSgjcItem(

+ 57 - 39
lib/page/sample_task/reap_sample_detail/reap_sample_basic_detail_page.dart

@@ -10,7 +10,6 @@ import '../../../base/base_lifecycle_state.dart';
10 10
 import '../../../model/rsp/dict_rsp.dart';
11 11
 import '../../../model/rsp/sample_task_rsp.dart';
12 12
 import '../../../network/my_api.dart';
13
-import '../../../service/dict_service.dart';
14 13
 import '../../../widget/card_item.dart';
15 14
 
16 15
 /// 收获扦样-基础信息
@@ -28,7 +27,8 @@ class ReapSampleBasicDetailPage extends StatefulWidget {
28 27
   State<ReapSampleBasicDetailPage> createState() => _ReapSampleBasicDetailPageState();
29 28
 }
30 29
 
31
-class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasicDetailPage> with AutomaticKeepAliveClientMixin {
30
+class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasicDetailPage>
31
+    with AutomaticKeepAliveClientMixin {
32 32
   SampleTaskItem? data;
33 33
   late bool isDetail;
34 34
 
@@ -133,7 +133,7 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
133 133
         ..clear()
134 134
         ..addAll((rsp.data ?? []).map((e) => CardMenuData(e.name, e.id)).toList());
135 135
       // 选中扦样人员
136
-      var nameList = data?.name?.split(',');
136
+      var nameList = data?.dgryName?.split(',');
137 137
       if (nameList != null) {
138 138
         for (var person in personList) {
139 139
           for (var name in nameList) {
@@ -164,9 +164,15 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
164 164
       logger.d('LocationChanged:${jsonEncode(value)}');
165 165
       var lon = (value['longitude'] as double).toStringAsFixed(2);
166 166
       var lat = (value['latitude'] as double).toStringAsFixed(2);
167
-      var province = value['province'];
168
-      var city = value['city'] == province ? '市辖区' : value['city'];
169
-      var district = value['district'];
167
+      String province = value['province'] as String;
168
+      String city = value['city'] as String;
169
+      String district = value['district'] as String;
170
+      String street = value['street'] as String;
171
+      String streetNumber = value['streetNumber'] as String;
172
+      if (province == city) {
173
+        city = district;
174
+        district = '';
175
+      }
170 176
       // if (value['province'] != data?.sheng) {
171 177
       //   MyNavigator.showToast('扦样地点有误,请检查扦样人员所在地点。');
172 178
       //   return;
@@ -178,13 +184,11 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
178 184
       data?.quXzqh = null;
179 185
       qu.value = null;
180 186
 
181
-      data?.xiangXzqh = null;
187
+      data?.xiangXzqhName = null;
182 188
       xian.value = null;
183
-      xianList.value = [];
184 189
 
185
-      data?.cunXzqh = null;
190
+      data?.cunXzqhName = null;
186 191
       cun.value = null;
187
-      cunList.value = [];
188 192
 
189 193
       MyNavigator.showLoading();
190 194
       bool stepSuccess = false;
@@ -212,18 +216,34 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
212 216
               break;
213 217
             }
214 218
           }
219
+
215 220
           if (stepSuccess) {
216 221
             stepSuccess = false;
217 222
             // 区
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;
223
+            if (district.isNotEmpty) {
224
+              var districtList = await getDistrictList(3, id: data?.shiXzqh, showLoading: false);
225
+              if (districtList == null) return;
226
+              for (CardMenuData item in districtList) {
227
+                if (item.name == district) {
228
+                  data?.quXzqh = item.value;
229
+                  qu.value = item;
230
+                  getDistrictList(4, id: item.value, showLoading: false);
231
+                  stepSuccess = true;
232
+                  break;
233
+                }
226 234
               }
235
+            } else {
236
+              data?.quXzqh = null;
237
+              qu.value = CardMenuData('', null);
238
+              stepSuccess = true;
239
+            }
240
+
241
+            if (stepSuccess) {
242
+              // 乡、村
243
+              data?.xiangXzqhName = street;
244
+              data?.cunXzqhName = streetNumber;
245
+              xian.value = CardMenuData(street, null);
246
+              cun.value = CardMenuData(streetNumber, null);
227 247
             }
228 248
           }
229 249
         }
@@ -276,10 +296,9 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
276 296
     if (data?.xian != null) xian.value = CardMenuData(data?.xian, data?.xiangXzqh);
277 297
     if (data?.cun != null) cun.value = CardMenuData(data?.cun, data?.cunXzqh);
278 298
     qyddjwd.value = data?.qyddjwd;
279
-    name.value = data?.name;
299
+    name.value = data?.dgryName;
280 300
     // 编辑数据
281 301
     if (!isDetail) {
282
-      getEditData();
283 302
       initLocation();
284 303
       getPersonData();
285 304
     }
@@ -301,15 +320,14 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
301 320
   Widget buildList() {
302 321
     return Column(
303 322
       children: [
304
-        CardItemWidget('扦样任务单号', rightText: data?.qyrwdh, bottomLine: true),
305
-        CardItemWidget('扦样单位', rightText: data?.dwmc, bottomLine: true),
306
-        name.builder((v) => CardWidgets.buildMenuDialog(isDetail, '扦样人员', v, personList, personSelCallback, multiple: true)),
307
-        CardItemWidget('监测类别', rightText: DictService.getLabel(DictType.jclb, value: data?.jclb), bottomLine: true),
323
+        CardItemWidget('样品单号', rightText: data?.qyrwdh, bottomLine: true),
324
+        name.builder(
325
+            (v) => CardWidgets.buildMenuDialog(isDetail, '扦样/陪同人员', v, personList, personSelCallback, multiple: true)),
308 326
         sheng.builder((v) => CardItemWidget('省份', rightText: v?.name, bottomLine: true)),
309
-        shi.builder((v) => CardItemWidget('市', rightText: v?.name, bottomLine: true)),
327
+        shi.builder((v) => CardItemWidget('市/州', rightText: v?.name, bottomLine: true)),
310 328
         qu.builder((v) => CardItemWidget('区县', rightText: v?.name, bottomLine: true)),
311
-        CardWidgets.buildMenu(isDetail, '乡镇', xianList, xian, onSelectXzqh),
312
-        CardWidgets.buildMenu(isDetail, '村', cunList, cun, onSelectXzqh),
329
+        xian.builder((v) => CardItemWidget('乡镇', rightText: v?.name, bottomLine: true)),
330
+        cun.builder((v) => CardItemWidget('村', rightText: v?.name, bottomLine: true)),
313 331
         qyddjwd.builder(
314 332
           (v) => CardItemWidget(
315 333
             '扦样地点经纬度',
@@ -334,18 +352,18 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
334 352
           trxx,
335 353
           (_, sel) => data?.trdllx = sel.value,
336 354
         ),
337
-        CardWidgets.buildEdit(
338
-          isDetail,
339
-          '被调查农户或合作社',
340
-          data?.bdcnhhhzs,
341
-          onChanged: (value) => data?.bdcnhhhzs = value,
342
-        ),
343
-        CardWidgets.buildEdit(
344
-          isDetail,
345
-          '联系方式',
346
-          data?.lxfs,
347
-          onChanged: (value) => data?.lxfs = value,
348
-        ),
355
+        // CardWidgets.buildEdit(
356
+        //   isDetail,
357
+        //   '被调查农户或合作社',
358
+        //   data?.bdcnhhhzs,
359
+        //   onChanged: (value) => data?.bdcnhhhzs = value,
360
+        // ),
361
+        // CardWidgets.buildEdit(
362
+        //   isDetail,
363
+        //   '联系方式',
364
+        //   data?.lxfs,
365
+        //   onChanged: (value) => data?.lxfs = value,
366
+        // ),
349 367
       ],
350 368
     );
351 369
   }

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

@@ -89,60 +89,29 @@ class _ReapSampleDisasterDetailPageState extends BaseLifecycleState<ReapSampleDi
89 89
     isDetail = widget.detail;
90 90
 
91 91
     // 工厂排污
92
-    setBoolMenuSelNotifier(zztdzwsfygcpw, data?.zztdzwsfygcpw ?? false);
93
-
92
+    setBoolMenuSelNotifier(zztdzwsfygcpw, data?.zztdzwsfygcpw);
94 93
     // 工厂排污类型
95 94
     setDictMenuNotifier(gcpwlxList, gcpwlx, DictType.gcpwlx, data?.gcpwlx);
96
-    if (data?.gcpwlx == null) {
97
-      gcpwlx.value = gcpwlxList.value.first;
98
-      data?.gcpwlx = gcpwlxList.value.first.value;
99
-    }
100
-
101 95
     // 水源、土壤污染
102
-    setBoolMenuSelNotifier(zztdzwsysytrsfywr, data?.zztdzwsysytrsfywr ?? false);
103
-
96
+    setBoolMenuSelNotifier(zztdzwsysytrsfywr, data?.zztdzwsysytrsfywr);
104 97
     // 污染物类型
105 98
     setDictMenuNotifier(wrwlxList, wrwlx, DictType.wrwlx, data?.wrwlx);
106
-    if (data?.wrwlx == null) {
107
-      wrwlx.value = wrwlxList.value.first;
108
-      data?.wrwlx = wrwlxList.value.first.value;
109
-    }
110
-
111 99
     // 病虫害
112
-    setBoolMenuSelNotifier(scgczsffsbjyzdbch, data?.scgczsffsbjyzdbch ?? false);
113
-
100
+    setBoolMenuSelNotifier(scgczsffsbjyzdbch, data?.scgczsffsbjyzdbch);
114 101
     // 病虫害类型
115 102
     setDictMenuNotifier(bchlxList, bchlx, DictType.bchlx, data?.bchlx);
116
-    if (data?.bchlx == null) {
117
-      bchlx.value = bchlxList.value.first;
118
-      data?.bchlx = bchlxList.value.first.value;
119
-    }
120
-
121 103
     // 收获期间是否发生连阴雨天气
122
-    setNumBoolMenuSelNotifier(shqjsffslyytq, data?.shqjsffslyytq ?? 1);
123
-
104
+    setNumBoolMenuSelNotifier(shqjsffslyytq, data?.shqjsffslyytq);
124 105
     // 收获粮食水分是否偏高
125
-    setNumBoolMenuSelNotifier(shlssfsfpg, data?.shlssfsfpg ?? 1);
126
-
106
+    setNumBoolMenuSelNotifier(shlssfsfpg, data?.shlssfsfpg);
127 107
     // 近年来本地是否发生真菌毒素污染
128
-    setNumBoolMenuSelNotifier(jnlbdsffszmwr, data?.jnlbdsffszmwr ?? 1);
129
-
108
+    setNumBoolMenuSelNotifier(jnlbdsffszmwr, data?.jnlbdsffszmwr);
130 109
     // 真菌毒素污染类型
131 110
     setDictMenuNotifier(zjdswrlxList, zjdswrlx, DictType.zjdswrlx, data?.zjdswrlx);
132
-    if (data?.zjdswrlx == null) {
133
-      zjdswrlx.value = zjdswrlxList.value.first;
134
-      data?.zjdswrlx = zjdswrlxList.value.first.value;
135
-    }
136
-
137 111
     // 近年来本地是否发生重金属污染
138
-    setNumBoolMenuSelNotifier(jnlbdsfzjswr, data?.jnlbdsfzjswr ?? 1);
139
-
112
+    setNumBoolMenuSelNotifier(jnlbdsfzjswr, data?.jnlbdsfzjswr);
140 113
     // 重金属污染类型
141 114
     setDictMenuNotifier(zjswrlxList, zjswrlx, DictType.zjswrlx, data?.zjswrlx);
142
-    if (data?.zjswrlx == null) {
143
-      zjswrlx.value = zjswrlxList.value.first;
144
-      data?.zjswrlx = zjswrlxList.value.first.value;
145
-    }
146 115
   }
147 116
 
148 117
   @override

+ 69 - 66
lib/page/sample_task/reap_sample_detail/reap_sample_medicine_detail_page.dart

@@ -22,7 +22,8 @@ class ReapSampleMedicineDetailPage extends StatefulWidget {
22 22
   State<ReapSampleMedicineDetailPage> createState() => _ReapSampleMedicineDetailPageState();
23 23
 }
24 24
 
25
-class _ReapSampleMedicineDetailPageState extends BaseLifecycleState<ReapSampleMedicineDetailPage> with AutomaticKeepAliveClientMixin {
25
+class _ReapSampleMedicineDetailPageState extends BaseLifecycleState<ReapSampleMedicineDetailPage>
26
+    with AutomaticKeepAliveClientMixin {
26 27
   SampleTaskItem? data;
27 28
   late bool isDetail;
28 29
 
@@ -102,73 +103,75 @@ class _ReapSampleMedicineDetailPageState extends BaseLifecycleState<ReapSampleMe
102 103
 
103 104
   Widget buildItem(int index, UseMedicineItem item) {
104 105
     bool detail = item.id != null;
105
-    return Container(
106
-      clipBehavior: Clip.hardEdge,
107
-      decoration: const BoxDecoration(
108
-        color: Color(0xFFF5FFFD),
109
-        borderRadius: BorderRadius.all(Radius.circular(8)),
110
-      ),
111
-      margin: const EdgeInsets.only(left: 12, right: 12, top: 8),
112
-      child: IntrinsicHeight(
113
-        child: Row(
114
-          mainAxisSize: MainAxisSize.min,
115
-          children: [
116
-            Container(
117
-              color: const Color(0xFF3ACEE6),
118
-              alignment: Alignment.center,
119
-              padding: const EdgeInsets.symmetric(horizontal: 2),
120
-              child: Text(
121
-                '${index + 1}',
122
-                style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700),
106
+    return GestureDetector(
107
+      onLongPress: detail ? null : () => onRemove(item),
108
+      child: Container(
109
+        clipBehavior: Clip.hardEdge,
110
+        decoration: const BoxDecoration(
111
+          color: Color(0xFFF5FFFD),
112
+          borderRadius: BorderRadius.all(Radius.circular(8)),
113
+        ),
114
+        margin: const EdgeInsets.only(left: 12, right: 12, top: 8),
115
+        child: IntrinsicHeight(
116
+          child: Row(
117
+            mainAxisSize: MainAxisSize.min,
118
+            children: [
119
+              Container(
120
+                color: const Color(0xFF3ACEE6),
121
+                alignment: Alignment.center,
122
+                padding: const EdgeInsets.symmetric(horizontal: 2),
123
+                child: Text(
124
+                  '${index + 1}',
125
+                  style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700),
126
+                ),
123 127
               ),
124
-            ),
125
-            Expanded(
126
-              child: Column(
127
-                mainAxisSize: MainAxisSize.min,
128
-                children: [
129
-                  CardWidgets.buildEdit(
130
-                    detail,
131
-                    '使用农药品种',
132
-                    item.synypz,
133
-                    backgroundColor: null,
134
-                    onChanged: (value) => item.synypz = value,
135
-                  ),
136
-                  CardWidgets.buildEdit(
137
-                    detail,
138
-                    '使用农药的数量(公斤或毫升/每亩地)',
139
-                    item.synysl?.toString(),
140
-                    backgroundColor: null,
141
-                    inputType: const TextInputType.numberWithOptions(decimal: true),
142
-                    formatters: [XNumberTextInputFormatter()],
143
-                    onChanged: (value) => item.synysl = value.isEmpty ? null : num.parse(value),
144
-                  ),
145
-                  CardItemWidget(
146
-                    '施药时间',
147
-                    rightText: item.sysj,
148
-                    trailing: detail ? null : Image.asset(imgItemArrowDown, width: 20),
149
-                    bottomLine: true,
150
-                    backgroundColor: null,
151
-                    onTap: detail ? null : () => showDate(item),
152
-                  ),
153
-                  CardWidgets.buildEdit(
154
-                    detail,
155
-                    '施药方法',
156
-                    item.syff,
157
-                    backgroundColor: null,
158
-                    onChanged: (value) => item.syff = value,
159
-                  ),
160
-                  detail
161
-                      ? const SizedBox.shrink()
162
-                      : MyButton(
163
-                          '删除',
164
-                          backgroundColor: const Color(0xFFCE615A),
165
-                          margin: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
166
-                          onTap: () => onRemove(item),
167
-                        ),
168
-                ],
128
+              Expanded(
129
+                child: Column(
130
+                  mainAxisSize: MainAxisSize.min,
131
+                  children: [
132
+                    CardWidgets.buildEdit(
133
+                      detail,
134
+                      '使用农药品种',
135
+                      item.synypz,
136
+                      backgroundColor: null,
137
+                      onChanged: (value) => item.synypz = value,
138
+                    ),
139
+                    CardWidgets.buildEdit(
140
+                      detail,
141
+                      '使用农药的数量(公斤或毫升/每亩地)',
142
+                      item.synysl?.toString(),
143
+                      backgroundColor: null,
144
+                      inputType: const TextInputType.numberWithOptions(decimal: true),
145
+                      formatters: [XNumberTextInputFormatter()],
146
+                      onChanged: (value) => item.synysl = value.isEmpty ? null : num.parse(value),
147
+                    ),
148
+                    CardItemWidget(
149
+                      '施药时间',
150
+                      rightText: item.sysj,
151
+                      trailing: detail || item.sysj != null
152
+                          ? null
153
+                          : Image.asset(
154
+                              imgItemArrowDown,
155
+                              width: 20,
156
+                              color: const Color(0xFF01B2C8),
157
+                            ),
158
+                      bottomLine: true,
159
+                      backgroundColor: null,
160
+                      onTap: detail ? null : () => showDate(item),
161
+                    ),
162
+                    CardWidgets.buildEdit(
163
+                      detail,
164
+                      '施药方法',
165
+                      item.syff,
166
+                      backgroundColor: null,
167
+                      onChanged: (value) => item.syff = value,
168
+                      bottomLine: false,
169
+                    ),
170
+                  ],
171
+                ),
169 172
               ),
170
-            ),
171
-          ],
173
+            ],
174
+          ),
172 175
         ),
173 176
       ),
174 177
     );

+ 120 - 27
lib/page/sample_task/reap_sample_detail/reap_sample_variety_detail_page.dart

@@ -9,6 +9,7 @@ import '../../../model/rsp/sample_task_rsp.dart';
9 9
 import '../../../network/my_api.dart';
10 10
 import '../../../utils/date_time_utils.dart';
11 11
 import '../../../utils/input_formatter.dart';
12
+import '../../../widget/button.dart';
12 13
 
13 14
 /// 收获扦样-品种信息
14 15
 class ReapSampleVarietyDetailPage extends StatefulWidget {
@@ -99,11 +100,45 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
99 100
     if (dict != null) yzpzlx.value = CardMenuData(dict.label, dict.value);
100 101
   }
101 102
 
103
+  void onAdd() {
104
+    if (data == null) return;
105
+    setState(() {
106
+      if (data!.codeSamplingNonghuList == null) {
107
+        data!.codeSamplingNonghuList = [NonghuItem()];
108
+      } else {
109
+        data!.codeSamplingNonghuList!.add(NonghuItem());
110
+      }
111
+    });
112
+  }
113
+
114
+  void onRemove(NonghuItem item) async {
115
+    var delete = await showDialog(
116
+      context: context,
117
+      builder: (_) => AlertDialog(
118
+        title: const Text('是否删除扦样农户信息?'),
119
+        actions: [
120
+          MyButton(
121
+            '删除',
122
+            alignment: null,
123
+            backgroundColor: const Color(0xFFCE615A),
124
+            onTap: () => MyNavigator.pop(true),
125
+          ),
126
+          MyButton('取消', alignment: null, onTap: () => MyNavigator.pop()),
127
+        ],
128
+      ),
129
+    );
130
+    if (delete ?? false) {
131
+      setState(() {
132
+        data?.codeSamplingNonghuList?.remove(item);
133
+      });
134
+    }
135
+  }
136
+
102 137
   @override
103 138
   void onInit() {
104 139
     data = widget.data;
105 140
     isDetail = widget.detail;
106
-    arrowDown = Image.asset(imgItemArrowDown, width: 20);
141
+    arrowDown = Image.asset(imgItemArrowDown, width: 20, color: const Color(0xFF01B2C8));
107 142
 
108 143
     // 粮食品类菜单数据
109 144
     getLsxxList();
@@ -151,7 +186,6 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
151 186
           lspz,
152 187
           (_, sel) => data?.lspz = sel.value?.toString(),
153 188
         ),
154
-        CardItemWidget('样品编号', rightText: data?.ypbh, bottomLine: true),
155 189
         CardWidgets.buildEdit(
156 190
           isDetail,
157 191
           '种植品种',
@@ -169,11 +203,18 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
169 203
         ),
170 204
         CardWidgets.buildMenu(
171 205
           isDetail,
172
-          '优质品种类型',
206
+          '品种优质类型',
173 207
           yzpzlxList,
174 208
           yzpzlx,
175 209
           (_, sel) => data?.yzpzlx = num.parse(sel.value),
176 210
         ),
211
+        CardWidgets.buildMenu(
212
+          isDetail,
213
+          '天气情况',
214
+          tqqkList,
215
+          tqqk,
216
+          (_, sel) => data?.tqqk = sel.value,
217
+        ),
177 218
         CardWidgets.buildDate(
178 219
           isDetail,
179 220
           '收获时间',
@@ -186,32 +227,84 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
186 227
           qysj,
187 228
           onResult: (value) => data?.qysj = DateTimeUtils.yyyymmdd(date: value),
188 229
         ),
189
-        CardWidgets.buildEdit(
190
-          isDetail,
191
-          '扦样数量(公斤)',
192
-          data?.qysl?.toString(),
193
-          inputType: const TextInputType.numberWithOptions(decimal: true),
194
-          formatters: [XNumberTextInputFormatter()],
195
-          onChanged: (value) => data?.qysl = value.isEmpty ? null : num.parse(value),
196
-        ),
197
-        CardWidgets.buildEdit(
198
-          isDetail,
199
-          '扦样代表数量(公斤)',
200
-          data?.qydbsl?.toString(),
201
-          inputType: const TextInputType.numberWithOptions(decimal: true),
202
-          formatters: [XNumberTextInputFormatter()],
203
-          onChanged: (value) => data?.qydbsl = value.isEmpty ? null : num.parse(value),
230
+        ...List.generate(
231
+          data?.codeSamplingNonghuList?.length ?? 0,
232
+          (index) => buildNonghu(index, data!.codeSamplingNonghuList![index]),
233
+        ).toList(),
234
+        isDetail ? const SizedBox.shrink() : MyButton('添加扦样农户信息', onTap: onAdd, margin: const EdgeInsets.all(10))
235
+      ],
236
+    );
237
+  }
238
+
239
+  Widget buildNonghu(int index, NonghuItem item) {
240
+    bool detail = item.id != null;
241
+    return GestureDetector(
242
+      onLongPress: detail ? null : () => onRemove(item),
243
+      child: Container(
244
+        clipBehavior: Clip.hardEdge,
245
+        decoration: const BoxDecoration(
246
+          color: Color(0xFFF5FFFD),
247
+          borderRadius: BorderRadius.all(Radius.circular(8)),
204 248
         ),
205
-        CardWidgets.buildMenu(
206
-          isDetail,
207
-          '天气情况',
208
-          tqqkList,
209
-          tqqk,
210
-          (_, sel) {
211
-            // data?.tqqk = sel.value?.toString();
212
-          },
249
+        margin: const EdgeInsets.only(left: 12, right: 12, top: 8),
250
+        child: IntrinsicHeight(
251
+          child: Row(
252
+            mainAxisSize: MainAxisSize.min,
253
+            children: [
254
+              Container(
255
+                color: const Color(0xFF3ACEE6),
256
+                alignment: Alignment.center,
257
+                padding: const EdgeInsets.symmetric(horizontal: 2),
258
+                child: Text(
259
+                  '${index + 1}',
260
+                  style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w700),
261
+                ),
262
+              ),
263
+              Expanded(
264
+                child: Column(
265
+                  mainAxisSize: MainAxisSize.min,
266
+                  children: [
267
+                    CardWidgets.buildEdit(
268
+                      detail,
269
+                      '扦样数量(公斤)',
270
+                      item.qysl?.toString(),
271
+                      inputType: const TextInputType.numberWithOptions(decimal: true),
272
+                      formatters: [XNumberTextInputFormatter()],
273
+                      onChanged: (value) => item.qysl = value.isEmpty ? null : num.parse(value),
274
+                      backgroundColor: null,
275
+                    ),
276
+                    CardWidgets.buildEdit(
277
+                      detail,
278
+                      '扦样代表数量(公斤)',
279
+                      item.qydbsl?.toString(),
280
+                      inputType: const TextInputType.numberWithOptions(decimal: true),
281
+                      formatters: [XNumberTextInputFormatter()],
282
+                      onChanged: (value) => item.qydbsl = value.isEmpty ? null : num.parse(value),
283
+                      backgroundColor: null,
284
+                    ),
285
+                    CardWidgets.buildEdit(
286
+                      detail,
287
+                      '被调查农户或合作社',
288
+                      item.bdcnhhhzs,
289
+                      onChanged: (value) => item.bdcnhhhzs = value,
290
+                      backgroundColor: null,
291
+                    ),
292
+                    CardWidgets.buildEdit(
293
+                      detail,
294
+                      '联系方式',
295
+                      inputType: TextInputType.number,
296
+                      item.lxfs,
297
+                      onChanged: (value) => item.lxfs = value,
298
+                      backgroundColor: null,
299
+                      bottomLine: false,
300
+                    ),
301
+                  ],
302
+                ),
303
+              ),
304
+            ],
305
+          ),
213 306
         ),
214
-      ],
307
+      ),
215 308
     );
216 309
   }
217 310
 }

+ 1 - 0
lib/page/sample_task/sample_list_vm.dart

@@ -56,6 +56,7 @@ class SampleListVM extends BaseVM {
56 56
     }
57 57
     try {
58 58
       var value = await MyApi.get().sampleTaskList(req.toJson());
59
+      if (isDispose) return;
59 60
       List<SampleTaskItem> data = value.data?.list ?? [];
60 61
       var list = pageState.value.data ?? [];
61 62
       if (refresh) {

+ 14 - 8
lib/page/sample_task/sample_task_list_page.dart

@@ -200,25 +200,31 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage> wi
200 200
   }
201 201
 
202 202
   Widget buildGrid(SampleTaskItem item) {
203
-    List<Map<String, String?>> infoList;
203
+    List<Map<String, String?>> infoList = [];
204 204
     if (item.deliveryStatus != 2) {
205 205
       // 未扦样
206
-      infoList = [
206
+      infoList.addAll([
207 207
         {'采样品种': item.cypzName},
208 208
         {'检验指标': item.jyzb},
209 209
         {'样品等级': DictService.getDict(DictType.ypdj, value: item.ypdj)?.label},
210 210
         {'扦样地区': item.qydq},
211
-      ];
211
+      ]);
212 212
     } else {
213 213
       // 已扦样
214
-      infoList = [
214
+      infoList.addAll([
215 215
         {'采样品种': item.cypzName},
216
-        {'检验指标': item.jyzb},
217
-        {'样品等级': DictService.getDict(DictType.ypdj, value: item.ypdj)?.label},
218 216
         {'扦样地区': item.qydq},
219
-        {'扦样人员': item.qyryName},
217
+      ]);
218
+      if (item.ypdj != null) {
219
+        infoList.add({'样品等级': DictService.getDict(DictType.ypdj, value: item.ypdj)?.label});
220
+      }
221
+      if (item.jyzb != null) {
222
+        infoList.add({'检验指标': item.jyzb});
223
+      }
224
+      infoList.addAll([
225
+        {'扦样人员': item.dgryName},
220 226
         {'扦样时间': item.qysj},
221
-      ];
227
+      ]);
222 228
     }
223 229
     return Padding(
224 230
       padding: const EdgeInsets.symmetric(horizontal: 8),

+ 2 - 0
lib/page/sample_task/sample_task_list_tab_page.dart

@@ -78,6 +78,8 @@ class _SampleTaskListTabPageState extends BaseLifecycleState<SampleTaskListTabPa
78 78
   @override
79 79
   void onDestroy() {
80 80
     Inject.remove<SampleListVM>();
81
+    tabCtrl.dispose();
82
+    pageCtrl.dispose();
81 83
   }
82 84
 
83 85
   @override

+ 51 - 0
lib/page/signature/signature_page.dart

@@ -0,0 +1,51 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:flutter/services.dart';
3
+import 'package:lszlgl/base/base_lifecycle_state.dart';
4
+
5
+class SignaturePageArgs {
6
+  /// 签名数量
7
+  int count;
8
+
9
+  SignaturePageArgs({this.count = 1});
10
+
11
+  @override
12
+  String toString() {
13
+    return {'count': count}.toString();
14
+  }
15
+}
16
+
17
+/// 电子签名
18
+class SignaturePage extends StatefulWidget {
19
+  final SignaturePageArgs args;
20
+
21
+  const SignaturePage({
22
+    super.key,
23
+    required this.args,
24
+  });
25
+
26
+  @override
27
+  State<SignaturePage> createState() => _SignaturePageState();
28
+}
29
+
30
+class _SignaturePageState extends BaseLifecycleState<SignaturePage> {
31
+  @override
32
+  void onInit() {
33
+    SystemChrome.setPreferredOrientations([
34
+      DeviceOrientation.landscapeLeft,
35
+      DeviceOrientation.landscapeRight,
36
+    ]);
37
+  }
38
+
39
+  @override
40
+  void onDestroy() {
41
+    SystemChrome.setPreferredOrientations([
42
+      DeviceOrientation.portraitUp,
43
+      DeviceOrientation.portraitDown,
44
+    ]);
45
+  }
46
+
47
+  @override
48
+  Widget build(BuildContext context) {
49
+    return const Placeholder();
50
+  }
51
+}

+ 9 - 0
lib/router/my_router.dart

@@ -8,6 +8,7 @@ import 'package:lszlgl/page/user_center/setting_page.dart';
8 8
 import 'package:lszlgl/router/my_navigator.dart';
9 9
 
10 10
 import '../page/sample_task/stock_sample_detail/stock_sample_task_page.dart';
11
+import '../page/signature/signature_page.dart';
11 12
 
12 13
 // 根页面
13 14
 const rLoginPage = '/';
@@ -25,6 +26,8 @@ const rSampleTaskListTabPage = '/SampleTaskListTabPage';
25 26
 const rReapSampleTaskPage = '/ReapSampleTaskPage';
26 27
 // 库存扦样任务
27 28
 const rStockSampleTaskPage = '/StockSampleTaskPage';
29
+// 电子签名
30
+const rSignaturePage = '/SignaturePage';
28 31
 
29 32
 final Map<String, MyNavigatorBuilder> rRouteMap = {
30 33
   // 根页面
@@ -36,6 +39,7 @@ final Map<String, MyNavigatorBuilder> rRouteMap = {
36 39
   rSampleTaskListTabPage: (context, args) => SampleTaskListTabPage(args: args as SampleTaskListTabPageArgs?),
37 40
   rReapSampleTaskPage: (context, args) => ReapSampleTaskPage(args: args as ReapSampleTaskPageArgs),
38 41
   rStockSampleTaskPage: (context, args) => StockSampleTaskPage(args: args as StockSampleTaskPageArgs),
42
+  rSignaturePage: (context, args) => SignaturePage(args: args as SignaturePageArgs),
39 43
 };
40 44
 
41 45
 class MyRouter {
@@ -88,4 +92,9 @@ class MyRouter {
88 92
   static Future<dynamic> startStockSampleTask({StockSampleTaskPageArgs? args}) {
89 93
     return MyNavigator.push(rStockSampleTaskPage, args: args ?? StockSampleTaskPageArgs());
90 94
   }
95
+
96
+  /// 电子签名
97
+  static Future<dynamic> startSignature({SignaturePageArgs? args}) {
98
+    return MyNavigator.push(rSignaturePage, args: args ?? SignaturePageArgs());
99
+  }
91 100
 }

+ 5 - 0
lib/service/dict_service.dart

@@ -72,4 +72,9 @@ class DictService {
72 72
     if (type == null) return null;
73 73
     return _dictMap[type.type]?.values.toList();
74 74
   }
75
+
76
+  static num? getDictFirstNum(DictType type) {
77
+    var list = getDictList(type);
78
+    return list?.first.value != null ? num.parse(list!.first.value!) : null;
79
+  }
75 80
 }

+ 19 - 5
lib/widget/card_item.dart

@@ -239,7 +239,7 @@ class CardItemMenuWidget extends StatelessWidget {
239 239
           selData == null
240 240
               ? Padding(
241 241
                   padding: const EdgeInsets.only(left: 8),
242
-                  child: Image.asset(imgItemArrowDown, width: 20),
242
+                  child: Image.asset(imgItemArrowDown, width: 20, color: const Color(0xFF01B2C8)),
243 243
                 )
244 244
               : const SizedBox.shrink(),
245 245
         ],
@@ -292,12 +292,13 @@ class CardWidgets {
292 292
     ValueChanged<String>? onChanged,
293 293
     List<TextInputFormatter>? formatters,
294 294
     Color? backgroundColor = Colors.white,
295
+    bool bottomLine = true,
295 296
   }) {
296 297
     if (isDetail) {
297 298
       return CardItemWidget(
298 299
         title,
299 300
         rightText: value,
300
-        bottomLine: true,
301
+        bottomLine: bottomLine,
301 302
         backgroundColor: backgroundColor,
302 303
       );
303 304
     }
@@ -320,7 +321,7 @@ class CardWidgets {
320 321
         onChanged: onChanged,
321 322
       ),
322 323
       backgroundColor: backgroundColor,
323
-      bottomLine: true,
324
+      bottomLine: bottomLine,
324 325
     );
325 326
   }
326 327
 
@@ -339,7 +340,13 @@ class CardWidgets {
339 340
       return CardItemWidget(
340 341
         title,
341 342
         rightText: v,
342
-        trailing: v == null ? Image.asset(imgItemArrowDown, width: 20) : const SizedBox.shrink(),
343
+        trailing: v == null
344
+            ? Image.asset(
345
+                imgItemArrowDown,
346
+                width: 20,
347
+                color: const Color(0xFF01B2C8),
348
+              )
349
+            : const SizedBox.shrink(),
343 350
         bottomLine: true,
344 351
         onTap: () async {
345 352
           var date = await showDatePicker(
@@ -370,7 +377,14 @@ class CardWidgets {
370 377
       rightText: value,
371 378
       bottomLine: true,
372 379
       hint: hint,
373
-      trailing: isDetail || value != null ? null : trailing ?? Image.asset(imgItemArrowDown, width: 20),
380
+      trailing: isDetail || value != null
381
+          ? null
382
+          : trailing ??
383
+              Image.asset(
384
+                imgItemArrowDown,
385
+                width: 20,
386
+                color: const Color(0xFF01B2C8),
387
+              ),
374 388
       onTap: isDetail
375 389
           ? null
376 390
           : () async {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 241 - 193
pubspec.lock


+ 5 - 0
pubspec.yaml

@@ -80,6 +80,11 @@ dependencies:
80 80
   permission_handler: ^11.3.0
81 81
   # 高德定位
82 82
   amap_flutter_location: ^3.0.0
83
+  # 二维码扫描
84
+#  mobile_scanner: ^5.0.0-beta.3
85
+  qr_code_scanner: ^1.0.1
86
+  # 手写签名
87
+  hand_signature: ^3.0.2
83 88
 
84 89
 dev_dependencies:
85 90
   flutter_test: