Browse Source

联调收获扦样基础信息、品种信息提交

mq 1 year ago
parent
commit
65b5619108

+ 51 - 1
lib/model/rsp/dict_rsp.dart

@@ -1,8 +1,12 @@
1 1
 import 'package:json_annotation/json_annotation.dart';
2 2
 
3
+import '../num_converter.dart';
4
+import '../string_converter.dart';
5
+
3 6
 part 'dict_rsp.g.dart';
4 7
 
5
-@JsonSerializable(genericArgumentFactories: true)
8
+/// 字典
9
+@JsonSerializable(converters: [NumConverter(), StringConverter()])
6 10
 class DictRsp {
7 11
   final String? dictType; //字典类型
8 12
   final String? value; //字典键值
@@ -17,3 +21,49 @@ class DictRsp {
17 21
 
18 22
   Map<String, dynamic> toJson() => _$DictRspToJson(this);
19 23
 }
24
+
25
+/// 土壤信息
26
+@JsonSerializable(converters: [NumConverter(), StringConverter()])
27
+class TrxxRsp {
28
+  /// ID
29
+  final num? id;
30
+
31
+  /// 土类名称
32
+  final String? tlmc;
33
+
34
+  /// 土类编码
35
+  final String? tlbmCode;
36
+
37
+  const TrxxRsp({
38
+    this.id,
39
+    this.tlmc,
40
+    this.tlbmCode,
41
+  });
42
+
43
+  factory TrxxRsp.fromJson(Map<String, dynamic> json) => _$TrxxRspFromJson(json);
44
+
45
+  Map<String, dynamic> toJson() => _$TrxxRspToJson(this);
46
+}
47
+
48
+/// 粮食信息
49
+@JsonSerializable(converters: [NumConverter(), StringConverter()])
50
+class LsxxRsp {
51
+  /// ID
52
+  final num? id;
53
+
54
+  /// 细类名称
55
+  final String? xilmc;
56
+
57
+  /// 细类编码
58
+  final String? xilbmCode;
59
+
60
+  const LsxxRsp({
61
+    this.id,
62
+    this.xilmc,
63
+    this.xilbmCode,
64
+  });
65
+
66
+  factory LsxxRsp.fromJson(Map<String, dynamic> json) => _$LsxxRspFromJson(json);
67
+
68
+  Map<String, dynamic> toJson() => _$LsxxRspToJson(this);
69
+}

+ 13 - 3
lib/network/api.dart

@@ -15,7 +15,9 @@ part 'api.g.dart';
15 15
 @RestApi(baseUrl: 'http://121.36.17.6:49099')
16 16
 abstract class Api {
17 17
   factory Api({Dio? dio, String? baseUrl}) {
18
-    dio ??= BaseDio.get().dio;
18
+    dio ??= BaseDio
19
+        .get()
20
+        .dio;
19 21
     return _Api(dio, baseUrl: baseUrl);
20 22
   }
21 23
 
@@ -47,10 +49,18 @@ abstract class Api {
47 49
   @GET('/admin-api/zj/code-sampling-task-details-sgjc/getSamplingTaskDetails')
48 50
   Future<ApiRsp<SampleTaskItem?>> sampleTaskDetailSgjc(@Query('id') num id);
49 51
 
52
+
53
+  /// 土壤信息列表
54
+  @GET('/admin-api/zj/base-soil-information/trxxxz')
55
+  Future<ApiRsp<List<TrxxRsp>?>> trxxList();
56
+
57
+  /// 粮食信息列表
58
+  @GET('/admin-api/zj/base-grain-information/lsxxfl')
59
+  Future<ApiRsp<List<LsxxRsp>?>> lsxxList();
60
+
50 61
   /// 省市县
51 62
   @GET('/admin-api/zj/base-administrative-division/list')
52
-  Future<ApiRsp<List<DistrictRsp>?>> districtList(
53
-    @Query('uLevel') num uLevel, {
63
+  Future<ApiRsp<List<DistrictRsp>?>> districtList(@Query('uLevel') num uLevel, {
54 64
     @Query('id') num? id,
55 65
   });
56 66
 }

+ 102 - 25
lib/page/sample_task/reap_sample_detail/reap_sample_basic_detail_page.dart

@@ -1,5 +1,9 @@
1 1
 import 'package:flutter/material.dart';
2
+import 'package:flutter/services.dart';
3
+import 'package:lszlgl/config/colors.dart';
4
+import 'package:lszlgl/utils/input_formatter.dart';
2 5
 import '../../../base/base_lifecycle_state.dart';
6
+import '../../../model/rsp/dict_rsp.dart';
3 7
 import '../../../model/rsp/sample_task_rsp.dart';
4 8
 import '../../../network/my_api.dart';
5 9
 import '../../../service/dict_service.dart';
@@ -9,20 +13,19 @@ import '../../../widget/card_item.dart';
9 13
 class ReapSampleBasicDetailPage extends StatefulWidget {
10 14
   final SampleTaskItem? data;
11 15
   final bool detail;
12
-  final VoidCallback? nextCallback;
13 16
 
14 17
   const ReapSampleBasicDetailPage(
15 18
     this.data, {
16 19
     super.key,
17 20
     this.detail = true,
18
-    this.nextCallback,
19 21
   });
20 22
 
21 23
   @override
22 24
   State<ReapSampleBasicDetailPage> createState() => _ReapSampleBasicDetailPageState();
23 25
 }
24 26
 
25
-class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasicDetailPage> with AutomaticKeepAliveClientMixin {
27
+class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasicDetailPage>
28
+    with AutomaticKeepAliveClientMixin {
26 29
   SampleTaskItem? data;
27 30
   late bool isDetail;
28 31
 
@@ -37,9 +40,11 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
37 40
   final xian = null.notifier<CardMenuData?>();
38 41
   final cun = null.notifier<CardMenuData?>();
39 42
 
40
-  final dllx = null.notifier<CardMenuData?>();
43
+  final trxxList = <CardMenuData>[].notifier<List<CardMenuData>>();
44
+  final trxx = null.notifier<CardMenuData?>();
41 45
 
42
-  Future<void> districtList(num level, {num? id}) async {
46
+  /// 获取行政区划列表
47
+  Future<void> getDistrictList(num level, {num? id}) async {
43 48
     MyNavigator.showLoading();
44 49
     try {
45 50
       var rsp = await MyApi.get().districtList(level, id: id);
@@ -59,7 +64,32 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
59 64
     MyNavigator.dismissLoading();
60 65
   }
61 66
 
62
-  void onSelect(ValueNotifier<CardMenuData?> selNotifier, CardMenuData selData) {
67
+  /// 获取土壤信息列表
68
+  Future<void> getTrxxList() async {
69
+    MyNavigator.showLoading();
70
+    try {
71
+      var rsp = await MyApi.get().trxxList();
72
+      List<CardMenuData> list = [];
73
+      if (rsp.data != null) {
74
+        for (TrxxRsp item in rsp.data!) {
75
+          var menuData = CardMenuData(item.tlmc, item.id);
76
+          list.add(menuData);
77
+          // 选中
78
+          if (item.id == data?.trdllx) trxx.value = menuData;
79
+        }
80
+      }
81
+      trxxList.value = list;
82
+    } catch (e) {}
83
+    MyNavigator.dismissLoading();
84
+  }
85
+
86
+  /// 选中土壤信息
87
+  void onSelectTrxx(ValueNotifier<CardMenuData?> selNotifier, CardMenuData selData) {
88
+    data?.trdllx = selData.value;
89
+  }
90
+
91
+  /// 选中行政区划
92
+  void onSelectXzqh(ValueNotifier<CardMenuData?> selNotifier, CardMenuData selData) {
63 93
     num level = 100;
64 94
     if (selNotifier == sheng) {
65 95
       level = 1;
@@ -124,7 +154,7 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
124 154
     }
125 155
     if (level < 5) {
126 156
       // 获取下一个等级的菜单数据
127
-      districtList(level + 1, id: selData.value ?? 0);
157
+      getDistrictList(level + 1, id: selData.value ?? 0);
128 158
     }
129 159
   }
130 160
 
@@ -137,22 +167,22 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
137 167
     if (data?.cun != null) cun.value = CardMenuData(data?.cun, data?.cunXzqh);
138 168
 
139 169
     // 省
140
-    districtList(1);
170
+    getDistrictList(1);
141 171
     // 市
142 172
     if (data?.shengXzqh != null) {
143
-      districtList(2, id: data?.shengXzqh);
173
+      getDistrictList(2, id: data?.shengXzqh);
144 174
     }
145 175
     // 区
146 176
     if (data?.shiXzqh != null) {
147
-      districtList(3, id: data?.shiXzqh);
177
+      getDistrictList(3, id: data?.shiXzqh);
148 178
     }
149 179
     // 县
150 180
     if (data?.quXzqh != null) {
151
-      districtList(4, id: data?.quXzqh);
181
+      getDistrictList(4, id: data?.quXzqh);
152 182
     }
153 183
     // 村
154 184
     if (data?.xiangXzqh != null) {
155
-      districtList(5, id: data?.xiangXzqh);
185
+      getDistrictList(5, id: data?.xiangXzqh);
156 186
     }
157 187
   }
158 188
 
@@ -163,6 +193,10 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
163 193
   void onInit() {
164 194
     data = widget.data;
165 195
     isDetail = widget.detail;
196
+    // 土壤信息
197
+    getTrxxList();
198
+
199
+    // 编辑数据
166 200
     if (!isDetail) {
167 201
       getEditData();
168 202
     }
@@ -199,19 +233,19 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
199 233
         ),
200 234
         isDetail
201 235
             ? CardItemWidget('省份', rightText: data?.sheng, bottomLine: true)
202
-            : CardItemMenuWidget('省份', shengList, sheng, onSelectTap: onSelect, bottomLine: true),
236
+            : CardItemMenuWidget('省份', shengList, sheng, onSelectTap: onSelectXzqh, bottomLine: true),
203 237
         isDetail
204 238
             ? CardItemWidget('市区', rightText: data?.shi, bottomLine: true)
205
-            : CardItemMenuWidget('市区', shiList, shi, onSelectTap: onSelect, bottomLine: true),
239
+            : CardItemMenuWidget('市区', shiList, shi, onSelectTap: onSelectXzqh, bottomLine: true),
206 240
         isDetail
207 241
             ? CardItemWidget('区县', rightText: data?.qu, bottomLine: true)
208
-            : CardItemMenuWidget('区县', quList, qu, onSelectTap: onSelect, bottomLine: true),
242
+            : CardItemMenuWidget('区县', quList, qu, onSelectTap: onSelectXzqh, bottomLine: true),
209 243
         isDetail
210 244
             ? CardItemWidget('乡镇', rightText: data?.xian, bottomLine: true)
211
-            : CardItemMenuWidget('乡镇', xianList, xian, onSelectTap: onSelect, bottomLine: true),
245
+            : CardItemMenuWidget('乡镇', xianList, xian, onSelectTap: onSelectXzqh, bottomLine: true),
212 246
         isDetail
213 247
             ? CardItemWidget('村', rightText: data?.cun, bottomLine: true)
214
-            : CardItemMenuWidget('村', cunList, cun, onSelectTap: onSelect, bottomLine: true),
248
+            : CardItemMenuWidget('村', cunList, cun, onSelectTap: onSelectXzqh, bottomLine: true),
215 249
         CardItemWidget(
216 250
           '扦样地点经纬度',
217 251
           rightText: data?.qyddjwd,
@@ -219,25 +253,68 @@ class _ReapSampleBasicDetailPageState extends BaseLifecycleState<ReapSampleBasic
219 253
         ),
220 254
         CardItemWidget(
221 255
           '种植面积(亩地)',
222
-          rightText: data?.zzmj?.toString(),
223
-          bottomLine: true,
224
-        ),
225
-        CardItemWidget(
226
-          '土壤地理类型',
227
-          rightText: DictService.getLabel(DictType.jclb, value: data?.trdllx),
256
+          rightText: isDetail ? data?.zzmj?.toString() : null,
257
+          rightChild: isDetail
258
+              ? null
259
+              : buildField(
260
+                  text: data?.zzmj?.toString(),
261
+                  inputType: const TextInputType.numberWithOptions(decimal: true),
262
+                  formatters: [XNumberTextInputFormatter()],
263
+                  onChanged: (value) => data?.zzmj = value.isEmpty ? null : num.parse(value),
264
+                ),
228 265
           bottomLine: true,
229 266
         ),
267
+        isDetail
268
+            ? trxx.builder((v) => CardItemWidget('土壤地理类型', rightText: v?.name ?? '', bottomLine: true))
269
+            : CardItemMenuWidget('土壤地理类型', trxxList, trxx, onSelectTap: onSelectTrxx, bottomLine: true),
230 270
         CardItemWidget(
231 271
           '被调查农户或合作社',
232
-          rightText: data?.bdcnhhhzs,
272
+          rightText: isDetail ? data?.bdcnhhhzs : null,
273
+          rightChild: isDetail
274
+              ? null
275
+              : buildField(
276
+                  text: data?.bdcnhhhzs,
277
+                  onChanged: (value) => data?.bdcnhhhzs = value,
278
+                ),
233 279
           bottomLine: true,
234 280
         ),
235 281
         CardItemWidget(
236 282
           '联系方式',
237
-          rightText: data?.lxfs,
283
+          rightText: isDetail ? data?.lxfs : null,
284
+          rightChild: isDetail
285
+              ? null
286
+              : buildField(
287
+                  text: data?.lxfs,
288
+                  onChanged: (value) => data?.lxfs = value,
289
+                ),
238 290
           bottomLine: true,
239 291
         ),
240 292
       ],
241 293
     );
242 294
   }
295
+
296
+  Widget buildField({
297
+    String? text,
298
+    String? hint = '点击填写',
299
+    TextInputType? inputType,
300
+    ValueChanged<String>? onChanged,
301
+    List<TextInputFormatter>? formatters,
302
+  }) {
303
+    return TextField(
304
+      controller: TextEditingController(text: text),
305
+      keyboardType: inputType,
306
+      textAlign: TextAlign.right,
307
+      decoration: InputDecoration(
308
+        hintText: hint,
309
+        hintStyle: const TextStyle(color: MyColor.c_666666, fontSize: 14),
310
+        border: InputBorder.none,
311
+        contentPadding: EdgeInsets.zero,
312
+        isDense: true,
313
+      ),
314
+      style: const TextStyle(color: Color(0xFF01B2C8), fontSize: 14, fontWeight: FontWeight.w500),
315
+      textInputAction: TextInputAction.next,
316
+      inputFormatters: formatters,
317
+      onChanged: onChanged,
318
+    );
319
+  }
243 320
 }

+ 182 - 13
lib/page/sample_task/reap_sample_detail/reap_sample_variety_detail_page.dart

@@ -1,25 +1,83 @@
1 1
 import 'package:flutter/material.dart';
2
+import 'package:flutter/services.dart';
2 3
 import 'package:lszlgl/base/base_lifecycle_state.dart';
4
+import 'package:lszlgl/utils/string_utils.dart';
3 5
 import 'package:lszlgl/widget/card_item.dart';
4 6
 
7
+import '../../../config/colors.dart';
5 8
 import '../../../model/rsp/sample_task_rsp.dart';
9
+import '../../../network/my_api.dart';
10
+import '../../../utils/date_time_utils.dart';
11
+import '../../../utils/input_formatter.dart';
6 12
 
7 13
 /// 收获扦样-品种信息
8 14
 class ReapSampleVarietyDetailPage extends StatefulWidget {
9 15
   final SampleTaskItem? data;
16
+  final bool detail;
10 17
 
11
-  const ReapSampleVarietyDetailPage(this.data, {super.key});
18
+  const ReapSampleVarietyDetailPage(
19
+    this.data, {
20
+    super.key,
21
+    this.detail = true,
22
+  });
12 23
 
13 24
   @override
14 25
   State<ReapSampleVarietyDetailPage> createState() => _ReapSampleVarietyDetailPageState();
15 26
 }
16 27
 
17
-class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVarietyDetailPage> with AutomaticKeepAliveClientMixin {
28
+class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVarietyDetailPage>
29
+    with AutomaticKeepAliveClientMixin {
18 30
   SampleTaskItem? data;
31
+  late bool isDetail;
32
+  late Widget arrowDown;
33
+
34
+  final lspzList = <CardMenuData>[].notifier<List<CardMenuData>>();
35
+  final lspz = null.notifier<CardMenuData?>();
36
+
37
+  final sfList = [CardMenuData('是', 0), CardMenuData('否', 1)].notifier<List<CardMenuData>>();
38
+
39
+  final sfyzpz = null.notifier<CardMenuData?>();
40
+
41
+  final shsj = null.notifier<String?>();
42
+  final qysj = null.notifier<String?>();
43
+
44
+  /// 选中土壤信息
45
+  void onSelectlspz(ValueNotifier<CardMenuData?> selNotifier, CardMenuData selData) {
46
+    data?.lspz = selData.name;
47
+  }
48
+
49
+  /// 选中是否优质品种
50
+  void onSelectSfyzpz(ValueNotifier<CardMenuData?> selNotifier, CardMenuData selData) {
51
+    data?.sfyzpz = selData.value;
52
+  }
53
+
54
+  /// 获取粮食信息列表
55
+  Future<void> getLsxxList() async {
56
+    MyNavigator.showLoading();
57
+    try {
58
+      var rsp = await MyApi.get().lsxxList();
59
+      lspzList.value = (rsp.data ?? []).map((e) => CardMenuData(e.xilmc, e.id)).toList();
60
+    } catch (e) {}
61
+    MyNavigator.dismissLoading();
62
+  }
63
+
64
+  void showDate(ValueNotifier<String?> notifier) async {
65
+    var date = await showDatePicker(
66
+      context: context,
67
+      firstDate: DateTime(2020),
68
+      lastDate: DateTime.now(),
69
+    );
70
+    if (date == null) return;
71
+    notifier.value = DateTimeUtils.yyyymmdd(date: date);
72
+  }
19 73
 
20 74
   @override
21 75
   void onInit() {
22 76
     data = widget.data;
77
+    isDetail = widget.detail;
78
+    arrowDown = Image.asset(imgItemArrowDown, width: 20);
79
+
80
+    if (data?.sfyzpz != null) sfyzpz.value = CardMenuData(StringUtils.boolStrByNum(data?.sfyzpz), data?.sfyzpz);
23 81
   }
24 82
 
25 83
   @override
@@ -35,18 +93,129 @@ class _ReapSampleVarietyDetailPageState extends BaseLifecycleState<ReapSampleVar
35 93
     return Column(
36 94
       children: [
37 95
         CardItemWidget('采样品种', rightText: data?.cypzName, bottomLine: true),
38
-        CardItemWidget('粮食品类', rightText: data?.lspz, bottomLine: true),
39
-        CardItemWidget('样品编号', rightText: data?.ypbh, bottomLine: true),
40
-        CardItemWidget('种植品种', rightText: data?.zzpz, bottomLine: true),
41
-        CardItemWidget('是否优质品种', rightText: data?.sfyzpz?.toString(), bottomLine: true),
42
-        CardItemWidget('优质品种类型', rightText: data?.yzpzlx?.toString(), bottomLine: true),
43
-        CardItemWidget('收获时间', rightText: data?.shsj, bottomLine: true),
44
-        CardItemWidget('扦样时间', rightText: data?.qysj, bottomLine: true),
45
-        CardItemWidget('扦样数量(公斤)', rightText: data?.qysl?.toString(), bottomLine: true),
46
-        CardItemWidget('扦样代表数量(公斤)', rightText: data?.qydbsl?.toString(), bottomLine: true),
47
-        CardItemWidget('温度(℃)', rightText: data?.wendu?.toString(), bottomLine: true),
48
-        CardItemWidget('湿度(%)', rightText: data?.shidu?.toString()),
96
+        isDetail
97
+            ? CardItemWidget('粮食品类', rightText: data?.lspz, bottomLine: true)
98
+            : CardItemMenuWidget('粮食品类', lspzList, lspz, onSelectTap: onSelectlspz, bottomLine: true),
99
+        CardItemWidget(
100
+          '样品编号',
101
+          rightText: data?.ypbh,
102
+          bottomLine: true,
103
+        ),
104
+        CardItemWidget(
105
+          '种植品种',
106
+          rightText: isDetail ? data?.zzpz : null,
107
+          rightChild: isDetail
108
+              ? null
109
+              : buildField(
110
+                  text: data?.zzpz,
111
+                  onChanged: (value) => data?.zzpz = value,
112
+                ),
113
+          bottomLine: true,
114
+        ),
115
+        isDetail
116
+            ? CardItemWidget('是否优质品种', rightText: sfyzpz.value?.name, bottomLine: true)
117
+            : CardItemMenuWidget('是否优质品种', sfList, sfyzpz, onSelectTap: onSelectSfyzpz, bottomLine: true),
118
+        CardItemWidget(
119
+          '优质品种类型',
120
+          rightText: data?.yzpzlx?.toString(),
121
+          bottomLine: true,
122
+        ),
123
+        shsj.builder(
124
+          (value) => CardItemWidget(
125
+            '收获时间',
126
+            rightText: value ?? data?.shsj ?? '',
127
+            trailing: isDetail ? null : arrowDown,
128
+            bottomLine: true,
129
+            onTap: isDetail ? null : () => showDate(shsj),
130
+          ),
131
+        ),
132
+        qysj.builder(
133
+          (value) => CardItemWidget(
134
+            '扦样时间',
135
+            rightText: value ?? data?.qysj ?? '',
136
+            trailing: isDetail ? null : arrowDown,
137
+            bottomLine: true,
138
+            onTap: isDetail ? null : () => showDate(qysj),
139
+          ),
140
+        ),
141
+        CardItemWidget(
142
+          '扦样数量(公斤)',
143
+          rightText: isDetail ? data?.qysl?.toString() : null,
144
+          rightChild: isDetail
145
+              ? null
146
+              : buildField(
147
+                  text: data?.qysl?.toString(),
148
+                  inputType: const TextInputType.numberWithOptions(decimal: true),
149
+                  formatters: [XNumberTextInputFormatter()],
150
+                  onChanged: (value) => data?.qysl = value.isEmpty ? null : num.parse(value),
151
+                ),
152
+          bottomLine: true,
153
+        ),
154
+        CardItemWidget(
155
+          '扦样代表数量(公斤)',
156
+          rightText: isDetail ? data?.qydbsl?.toString() : null,
157
+          rightChild: isDetail
158
+              ? null
159
+              : buildField(
160
+                  text: data?.qydbsl?.toString(),
161
+                  inputType: const TextInputType.numberWithOptions(decimal: true),
162
+                  formatters: [XNumberTextInputFormatter()],
163
+                  onChanged: (value) => data?.qydbsl = value.isEmpty ? null : num.parse(value),
164
+                ),
165
+          bottomLine: true,
166
+        ),
167
+        CardItemWidget(
168
+          '温度(℃)',
169
+          rightText: isDetail ? data?.wendu?.toString() : null,
170
+          rightChild: isDetail
171
+              ? null
172
+              : buildField(
173
+                  text: data?.wendu?.toString(),
174
+                  inputType: const TextInputType.numberWithOptions(decimal: true),
175
+                  formatters: [XNumberTextInputFormatter()],
176
+                  onChanged: (value) => data?.wendu = value.isEmpty ? null : num.parse(value),
177
+                ),
178
+          bottomLine: true,
179
+        ),
180
+        CardItemWidget(
181
+          '湿度(%)',
182
+          rightText: isDetail ? data?.shidu?.toString() : null,
183
+          rightChild: isDetail
184
+              ? null
185
+              : buildField(
186
+                  text: data?.shidu?.toString(),
187
+                  inputType: const TextInputType.numberWithOptions(decimal: true),
188
+                  formatters: [XNumberTextInputFormatter()],
189
+                  onChanged: (value) => data?.shidu = value.isEmpty ? null : num.parse(value),
190
+                ),
191
+          bottomLine: true,
192
+        ),
49 193
       ],
50 194
     );
51 195
   }
196
+
197
+  Widget buildField({
198
+    String? text,
199
+    String? hint = '点击填写',
200
+    TextInputType? inputType,
201
+    ValueChanged<String>? onChanged,
202
+    List<TextInputFormatter>? formatters,
203
+  }) {
204
+    return TextField(
205
+      controller: TextEditingController(text: text),
206
+      keyboardType: inputType,
207
+      textAlign: TextAlign.right,
208
+      decoration: InputDecoration(
209
+        hintText: hint,
210
+        hintStyle: const TextStyle(color: MyColor.c_666666, fontSize: 14),
211
+        border: InputBorder.none,
212
+        contentPadding: EdgeInsets.zero,
213
+        isDense: true,
214
+      ),
215
+      style: const TextStyle(color: Color(0xFF01B2C8), fontSize: 14, fontWeight: FontWeight.w500),
216
+      textInputAction: TextInputAction.next,
217
+      inputFormatters: formatters,
218
+      onChanged: onChanged,
219
+    );
220
+  }
52 221
 }

+ 4 - 4
lib/page/sample_task/reap_sample_task/reap_sample_task_page.dart

@@ -12,7 +12,6 @@ import 'package:lszlgl/page/sample_task/reap_sample_detail/reap_sample_variety_d
12 12
 import 'package:lszlgl/page/sample_task/reap_sample_task/reap_sample_disaster_page.dart';
13 13
 import 'package:lszlgl/page/sample_task/reap_sample_task/reap_sample_medicine_page.dart';
14 14
 import 'package:lszlgl/page/sample_task/reap_sample_task/reap_sample_org_page.dart';
15
-import 'package:lszlgl/page/sample_task/reap_sample_task/reap_sample_variety_page.dart';
16 15
 
17 16
 import '../../../base/base_vm.dart';
18 17
 import '../../../network/my_api.dart';
@@ -119,9 +118,10 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
119 118
       ];
120 119
     } else {
121 120
       pageList = [
122
-        ReapSampleBasicDetailPage(data, detail: false, nextCallback: next),
123 121
         // ReapSampleBasicPage(nextCallback: next),
124
-        ReapSampleVarietyPage(nextCallback: next, previousCallback: previous),
122
+        // ReapSampleVarietyPage(nextCallback: next, previousCallback: previous),
123
+        ReapSampleBasicDetailPage(data, detail: false),
124
+        ReapSampleVarietyDetailPage(data, detail: false),
125 125
         ReapSampleDisasterPage(nextCallback: next, previousCallback: previous),
126 126
         ReapSampleMedicinePage(nextCallback: next, previousCallback: previous),
127 127
         ReapSampleOrgPage(previousCallback: previous, submitCallback: submit),
@@ -256,7 +256,7 @@ class _ReapSampleTaskPageState extends BaseLifecycleState<ReapSampleTaskPage> wi
256 256
   Widget buildPage() {
257 257
     return PageView.builder(
258 258
       controller: pageCtrl,
259
-      // physics: const BouncingScrollPhysics(),
259
+      physics: const NeverScrollableScrollPhysics(),
260 260
       onPageChanged: (index) {
261 261
         if (index == tabIndex.value) return;
262 262
         tabIndex.value = index;

+ 93 - 0
lib/utils/input_formatter.dart

@@ -0,0 +1,93 @@
1
+import 'package:flutter/services.dart';
2
+
3
+class XNumberTextInputFormatter extends TextInputFormatter {
4
+  int? maxIntegerLength;
5
+  int? maxDecimalLength;
6
+  bool isAllowDecimal;
7
+
8
+  /// [maxIntegerLength]限定整数的最大位数,为null时不限
9
+  /// [maxDecimalLength]限定小数点的最大位数,为null时不限
10
+  /// [isAllowDecimal]是否可以为小数,默认是可以为小数,也就是可以输入小数点
11
+  XNumberTextInputFormatter({
12
+    this.maxIntegerLength,
13
+    this.maxDecimalLength,
14
+    this.isAllowDecimal = true,
15
+  });
16
+
17
+  @override
18
+  TextEditingValue formatEditUpdate(TextEditingValue oldValue, TextEditingValue newValue) {
19
+    String value = newValue.text.trim(); //去掉前后空格
20
+    int selectionIndex = newValue.selection.end;
21
+    if (isAllowDecimal) {
22
+      if (value == '.') {
23
+        value = '0.';
24
+        selectionIndex++;
25
+      } else if (value != '' && _isToDoubleError(value)) {
26
+        //不是double输入数据
27
+        return _oldTextEditingValue(oldValue);
28
+      }
29
+      //包含小数点
30
+      if (value.contains('.')) {
31
+        int pointIndex = value.indexOf('.');
32
+        String beforePoint = value.substring(0, pointIndex);
33
+//      print('$beforePoint');
34
+        String afterPoint = value.substring(pointIndex + 1, value.length);
35
+//      print('$afterPoint');
36
+        //小数点前面没内容补0
37
+        if (beforePoint.isEmpty) {
38
+          value = '0.$afterPoint';
39
+          selectionIndex++;
40
+        } else {
41
+          //限定整数位数
42
+          if (maxIntegerLength != null) {
43
+            if (beforePoint.length > maxIntegerLength!) {
44
+              return _oldTextEditingValue(oldValue);
45
+            }
46
+          }
47
+        }
48
+        //限定小数点位数
49
+        if (null != maxDecimalLength) {
50
+          if (afterPoint.length > maxDecimalLength!) {
51
+            return _oldTextEditingValue(oldValue);
52
+          }
53
+        }
54
+      } else {
55
+        //限定整数位数
56
+        if (null != maxIntegerLength) {
57
+          if (value.length > maxIntegerLength!) {
58
+            return _oldTextEditingValue(oldValue);
59
+          }
60
+        }
61
+      }
62
+    } else {
63
+      if (value.contains('.') ||
64
+          (value != '' && _isToDoubleError(value)) ||
65
+          (null != maxIntegerLength && value.length > maxIntegerLength!)) {
66
+        return _oldTextEditingValue(oldValue);
67
+      }
68
+    }
69
+
70
+    return TextEditingValue(
71
+      text: value,
72
+      selection: TextSelection.collapsed(offset: selectionIndex),
73
+    );
74
+  }
75
+
76
+  ///返回旧的输入内容
77
+  TextEditingValue _oldTextEditingValue(TextEditingValue oldValue) {
78
+    return TextEditingValue(
79
+      text: oldValue.text,
80
+      selection: TextSelection.collapsed(offset: oldValue.selection.end),
81
+    );
82
+  }
83
+
84
+  ///输入内容不能解析成double
85
+  bool _isToDoubleError(String value) {
86
+    try {
87
+      double.parse(value);
88
+    } catch (e) {
89
+      return true;
90
+    }
91
+    return false;
92
+  }
93
+}

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