Browse Source

新增扫码,跳转仓库详情。

liujq 6 months ago
parent
commit
f8f9ca11ed

+ 82 - 0
assets/json/storehouse.json

@@ -0,0 +1,82 @@
1
+{
2
+  "code": 0,
3
+  "data": [
4
+    {
5
+      "kqmc": "英吉沙县金麦粮食收储有限公司中心粮站",
6
+      "tycfbm": "3291653123710827520U01001",
7
+      "cfmc": "001",
8
+      "ajmc": "1廒",
9
+      "hwmc": "P1",
10
+      "tyhwbm": null,
11
+      "bgr": "热依罕古丽艾散",
12
+      "jfsyrq": "2010-06-01",
13
+      "cnzlxg": "4.5",
14
+      "cmsl": null,
15
+      "clgx": null,
16
+      "lspzmc": null,
17
+      "lsxzmc": null,
18
+      "lsdjmc": null,
19
+      "lqgsdw": null,
20
+      "rcsj": null,
21
+      "shnd": null,
22
+      "cd": null,
23
+      "cfzt": "完好",
24
+      "cflx": "高大平房仓(仓房跨度21米及以上,堆粮高度6米及以上)",
25
+      "ajsjcr": "2500",
26
+      "jjsl": null,
27
+      "sjsynx": "70",
28
+      "zjbgdh": null,
29
+      "jysj": null,
30
+      "jyr": null,
31
+      "jylb": null,
32
+      "spaqzb": null,
33
+      "rkrq": null,
34
+      "jyxm": null,
35
+      "jyxmz": null,
36
+      "ckg": "51.74*14.28*7.1",
37
+      "zjsjList": null,
38
+      "isUnanimous": null,
39
+      "reason": null,
40
+      "itemList": [
41
+        {
42
+          "kqmc": "英吉沙县金麦粮食收储有限公司中心粮站",
43
+          "tycfbm": "3291653123710827520U01001",
44
+          "cfmc": "001",
45
+          "tyhwbm": null,
46
+          "bgr": "热依罕古丽艾散",
47
+          "jfsyrq": "2010-06-01",
48
+          "cnzlxg": "4.5",
49
+          "cmsl": null,
50
+          "clgx": null,
51
+          "lspzmc": "小麦",
52
+          "lsxzmc": "市级地方储备粮",
53
+          "lsdjmc": "二等",
54
+          "lqgsdw": "英吉沙县金麦粮油购销有限责任公司",
55
+          "rcsj": "2021-07-1518:20:50.000000",
56
+          "shnd": "2021",
57
+          "cd": "英吉沙县",
58
+          "cfzt": "1",
59
+          "cflx": "10101",
60
+          "ajsjcr": "2500",
61
+          "jjsl": "2500000",
62
+          "sjsynx": "70",
63
+          "zjbgdh": null,
64
+          "jysj": null,
65
+          "jyr": null,
66
+          "jylb": null,
67
+          "spaqzb": null,
68
+          "rkrq": null,
69
+          "jyxm": null,
70
+          "jyxmz": null,
71
+          "ckg": "51.74*14.28*7.1",
72
+          "zjsjList": null,
73
+          "isUnanimous": null,
74
+          "reason": null,
75
+          "ajmc": "1廒",
76
+          "hwmc": "P1"
77
+        }
78
+      ]
79
+    }
80
+  ],
81
+  "msg": ""
82
+}

+ 25 - 0
lib/config/borders.dart

@@ -0,0 +1,25 @@
1
+import 'dart:ui';
2
+
3
+import 'package:flutter/material.dart';
4
+
5
+class Borders {
6
+
7
+  /// 输入框 底部 边框样式 灰色
8
+  static const UnderlineInputBorder underBorder = UnderlineInputBorder(
9
+      borderSide: BorderSide(color: Color(0xFFD6D6D6), width: 0.44));
10
+
11
+
12
+  static const OutlineInputBorder borderA = OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(120)));
13
+  static const OutlineInputBorder borderB = OutlineInputBorder(
14
+    borderSide: BorderSide(color: Color(0xFFE6E6E6), width: 1),
15
+    borderRadius: BorderRadius.all(Radius.circular(120)),
16
+  );
17
+
18
+}
19
+
20
+class TextStyles {
21
+  static const TextStyle titA = TextStyle(fontSize: 15,fontWeight: FontWeight.bold);
22
+  static const TextStyle titB = TextStyle(color: Colors.grey,fontSize: 15);
23
+  static const TextStyle titC = TextStyle(fontSize: 15);
24
+}
25
+

+ 176 - 0
lib/model/rsp/storehouse_rsp.dart

@@ -0,0 +1,176 @@
1
+import 'package:json_annotation/json_annotation.dart';
2
+
3
+import '../num_converter.dart';
4
+import '../string_converter.dart';
5
+
6
+part 'storehouse_rsp.g.dart';
7
+
8
+@JsonSerializable(converters: [NumConverter(), StringConverter()])
9
+class storehouseRspItemList {
10
+  String? kqmc;
11
+  String? tycfbm;
12
+  String? cfmc;
13
+  String? tyhwbm;
14
+  String? bgr;
15
+  String? jfsyrq;
16
+  String? cnzlxg;
17
+  String? cmsl;
18
+  String? clgx;
19
+  String? lspzmc;
20
+  String? lsxzmc;
21
+  String? lsdjmc;
22
+  String? lqgsdw;
23
+  String? rcsj;
24
+  String? shnd;
25
+  String? cd;
26
+  String? cfzt;
27
+  String? cflx;
28
+  String? ajsjcr;
29
+  String? jjsl;
30
+  String? sjsynx;
31
+  String? zjbgdh;
32
+  String? jysj;
33
+  String? jyr;
34
+  String? jylb;
35
+  String? spaqzb;
36
+  String? rkrq;
37
+  String? jyxm;
38
+  String? jyxmz;
39
+  String? ckg;
40
+  String? zjsjList;
41
+  String? isUnanimous;
42
+  String? reason;
43
+  String? ajmc;
44
+  String? hwmc;
45
+
46
+  storehouseRspItemList({
47
+    this.kqmc,
48
+    this.tycfbm,
49
+    this.cfmc,
50
+    this.tyhwbm,
51
+    this.bgr,
52
+    this.jfsyrq,
53
+    this.cnzlxg,
54
+    this.cmsl,
55
+    this.clgx,
56
+    this.lspzmc,
57
+    this.lsxzmc,
58
+    this.lsdjmc,
59
+    this.lqgsdw,
60
+    this.rcsj,
61
+    this.shnd,
62
+    this.cd,
63
+    this.cfzt,
64
+    this.cflx,
65
+    this.ajsjcr,
66
+    this.jjsl,
67
+    this.sjsynx,
68
+    this.zjbgdh,
69
+    this.jysj,
70
+    this.jyr,
71
+    this.jylb,
72
+    this.spaqzb,
73
+    this.rkrq,
74
+    this.jyxm,
75
+    this.jyxmz,
76
+    this.ckg,
77
+    this.zjsjList,
78
+    this.isUnanimous,
79
+    this.reason,
80
+    this.ajmc,
81
+    this.hwmc,
82
+  });
83
+
84
+  factory storehouseRspItemList.fromJson(Map<String, dynamic> json) => _$storehouseRspItemListFromJson(json);
85
+  Map<String, dynamic> toJson()=> _$storehouseRspItemListToJson(this);
86
+
87
+  // 2021-07-1518:20:50.000000
88
+  String? timeStr(){
89
+    if (rcsj == null) return null;
90
+    var time = rcsj!.substring(0, 10);
91
+    return time;
92
+  }
93
+
94
+}
95
+
96
+@JsonSerializable(converters: [NumConverter(), StringConverter()])
97
+class storehouseRsp {
98
+  String? kqmc;
99
+  String? tycfbm;
100
+  String? cfmc;
101
+  String? ajmc;
102
+  String? hwmc;
103
+  String? tyhwbm;
104
+  String? bgr;
105
+  String? jfsyrq;
106
+  String? cnzlxg;
107
+  String? cmsl;
108
+  String? clgx;
109
+  String? lspzmc;
110
+  String? lsxzmc;
111
+  String? lsdjmc;
112
+  String? lqgsdw;
113
+  String? rcsj;
114
+  String? shnd;
115
+  String? cd;
116
+  String? cfzt;
117
+  String? cflx;
118
+  String? ajsjcr;
119
+  String? jjsl;
120
+  String? sjsynx;
121
+  String? zjbgdh;
122
+  String? jysj;
123
+  String? jyr;
124
+  String? jylb;
125
+  String? spaqzb;
126
+  String? rkrq;
127
+  String? jyxm;
128
+  String? jyxmz;
129
+  String? ckg;
130
+  String? zjsjList;
131
+  String? isUnanimous;
132
+  String? reason;
133
+  List<storehouseRspItemList?>? itemList;
134
+
135
+  storehouseRsp({
136
+    this.kqmc,
137
+    this.tycfbm,
138
+    this.cfmc,
139
+    this.ajmc,
140
+    this.hwmc,
141
+    this.tyhwbm,
142
+    this.bgr,
143
+    this.jfsyrq,
144
+    this.cnzlxg,
145
+    this.cmsl,
146
+    this.clgx,
147
+    this.lspzmc,
148
+    this.lsxzmc,
149
+    this.lsdjmc,
150
+    this.lqgsdw,
151
+    this.rcsj,
152
+    this.shnd,
153
+    this.cd,
154
+    this.cfzt,
155
+    this.cflx,
156
+    this.ajsjcr,
157
+    this.jjsl,
158
+    this.sjsynx,
159
+    this.zjbgdh,
160
+    this.jysj,
161
+    this.jyr,
162
+    this.jylb,
163
+    this.spaqzb,
164
+    this.rkrq,
165
+    this.jyxm,
166
+    this.jyxmz,
167
+    this.ckg,
168
+    this.zjsjList,
169
+    this.isUnanimous,
170
+    this.reason,
171
+    this.itemList,
172
+  });
173
+  factory storehouseRsp.fromJson(Map<String, dynamic> json) => _$storehouseRspFromJson(json);
174
+  Map<String, dynamic> toJson() => _$storehouseRspToJson(this);
175
+}
176
+

+ 171 - 0
lib/model/rsp/storehouse_rsp.g.dart

@@ -0,0 +1,171 @@
1
+// GENERATED CODE - DO NOT MODIFY BY HAND
2
+
3
+part of 'storehouse_rsp.dart';
4
+
5
+// **************************************************************************
6
+// JsonSerializableGenerator
7
+// **************************************************************************
8
+
9
+storehouseRspItemList _$storehouseRspItemListFromJson(
10
+        Map<String, dynamic> json) =>
11
+    storehouseRspItemList(
12
+      kqmc: const StringConverter().fromJson(json['kqmc']),
13
+      tycfbm: const StringConverter().fromJson(json['tycfbm']),
14
+      cfmc: const StringConverter().fromJson(json['cfmc']),
15
+      tyhwbm: const StringConverter().fromJson(json['tyhwbm']),
16
+      bgr: const StringConverter().fromJson(json['bgr']),
17
+      jfsyrq: const StringConverter().fromJson(json['jfsyrq']),
18
+      cnzlxg: const StringConverter().fromJson(json['cnzlxg']),
19
+      cmsl: const StringConverter().fromJson(json['cmsl']),
20
+      clgx: const StringConverter().fromJson(json['clgx']),
21
+      lspzmc: const StringConverter().fromJson(json['lspzmc']),
22
+      lsxzmc: const StringConverter().fromJson(json['lsxzmc']),
23
+      lsdjmc: const StringConverter().fromJson(json['lsdjmc']),
24
+      lqgsdw: const StringConverter().fromJson(json['lqgsdw']),
25
+      rcsj: const StringConverter().fromJson(json['rcsj']),
26
+      shnd: const StringConverter().fromJson(json['shnd']),
27
+      cd: const StringConverter().fromJson(json['cd']),
28
+      cfzt: const StringConverter().fromJson(json['cfzt']),
29
+      cflx: const StringConverter().fromJson(json['cflx']),
30
+      ajsjcr: const StringConverter().fromJson(json['ajsjcr']),
31
+      jjsl: const StringConverter().fromJson(json['jjsl']),
32
+      sjsynx: const StringConverter().fromJson(json['sjsynx']),
33
+      zjbgdh: const StringConverter().fromJson(json['zjbgdh']),
34
+      jysj: const StringConverter().fromJson(json['jysj']),
35
+      jyr: const StringConverter().fromJson(json['jyr']),
36
+      jylb: const StringConverter().fromJson(json['jylb']),
37
+      spaqzb: const StringConverter().fromJson(json['spaqzb']),
38
+      rkrq: const StringConverter().fromJson(json['rkrq']),
39
+      jyxm: const StringConverter().fromJson(json['jyxm']),
40
+      jyxmz: const StringConverter().fromJson(json['jyxmz']),
41
+      ckg: const StringConverter().fromJson(json['ckg']),
42
+      zjsjList: const StringConverter().fromJson(json['zjsjList']),
43
+      isUnanimous: const StringConverter().fromJson(json['isUnanimous']),
44
+      reason: const StringConverter().fromJson(json['reason']),
45
+      ajmc: const StringConverter().fromJson(json['ajmc']),
46
+      hwmc: const StringConverter().fromJson(json['hwmc']),
47
+    );
48
+
49
+Map<String, dynamic> _$storehouseRspItemListToJson(
50
+        storehouseRspItemList instance) =>
51
+    <String, dynamic>{
52
+      'kqmc': const StringConverter().toJson(instance.kqmc),
53
+      'tycfbm': const StringConverter().toJson(instance.tycfbm),
54
+      'cfmc': const StringConverter().toJson(instance.cfmc),
55
+      'tyhwbm': const StringConverter().toJson(instance.tyhwbm),
56
+      'bgr': const StringConverter().toJson(instance.bgr),
57
+      'jfsyrq': const StringConverter().toJson(instance.jfsyrq),
58
+      'cnzlxg': const StringConverter().toJson(instance.cnzlxg),
59
+      'cmsl': const StringConverter().toJson(instance.cmsl),
60
+      'clgx': const StringConverter().toJson(instance.clgx),
61
+      'lspzmc': const StringConverter().toJson(instance.lspzmc),
62
+      'lsxzmc': const StringConverter().toJson(instance.lsxzmc),
63
+      'lsdjmc': const StringConverter().toJson(instance.lsdjmc),
64
+      'lqgsdw': const StringConverter().toJson(instance.lqgsdw),
65
+      'rcsj': const StringConverter().toJson(instance.rcsj),
66
+      'shnd': const StringConverter().toJson(instance.shnd),
67
+      'cd': const StringConverter().toJson(instance.cd),
68
+      'cfzt': const StringConverter().toJson(instance.cfzt),
69
+      'cflx': const StringConverter().toJson(instance.cflx),
70
+      'ajsjcr': const StringConverter().toJson(instance.ajsjcr),
71
+      'jjsl': const StringConverter().toJson(instance.jjsl),
72
+      'sjsynx': const StringConverter().toJson(instance.sjsynx),
73
+      'zjbgdh': const StringConverter().toJson(instance.zjbgdh),
74
+      'jysj': const StringConverter().toJson(instance.jysj),
75
+      'jyr': const StringConverter().toJson(instance.jyr),
76
+      'jylb': const StringConverter().toJson(instance.jylb),
77
+      'spaqzb': const StringConverter().toJson(instance.spaqzb),
78
+      'rkrq': const StringConverter().toJson(instance.rkrq),
79
+      'jyxm': const StringConverter().toJson(instance.jyxm),
80
+      'jyxmz': const StringConverter().toJson(instance.jyxmz),
81
+      'ckg': const StringConverter().toJson(instance.ckg),
82
+      'zjsjList': const StringConverter().toJson(instance.zjsjList),
83
+      'isUnanimous': const StringConverter().toJson(instance.isUnanimous),
84
+      'reason': const StringConverter().toJson(instance.reason),
85
+      'ajmc': const StringConverter().toJson(instance.ajmc),
86
+      'hwmc': const StringConverter().toJson(instance.hwmc),
87
+    };
88
+
89
+storehouseRsp _$storehouseRspFromJson(Map<String, dynamic> json) =>
90
+    storehouseRsp(
91
+      kqmc: const StringConverter().fromJson(json['kqmc']),
92
+      tycfbm: const StringConverter().fromJson(json['tycfbm']),
93
+      cfmc: const StringConverter().fromJson(json['cfmc']),
94
+      ajmc: const StringConverter().fromJson(json['ajmc']),
95
+      hwmc: const StringConverter().fromJson(json['hwmc']),
96
+      tyhwbm: const StringConverter().fromJson(json['tyhwbm']),
97
+      bgr: const StringConverter().fromJson(json['bgr']),
98
+      jfsyrq: const StringConverter().fromJson(json['jfsyrq']),
99
+      cnzlxg: const StringConverter().fromJson(json['cnzlxg']),
100
+      cmsl: const StringConverter().fromJson(json['cmsl']),
101
+      clgx: const StringConverter().fromJson(json['clgx']),
102
+      lspzmc: const StringConverter().fromJson(json['lspzmc']),
103
+      lsxzmc: const StringConverter().fromJson(json['lsxzmc']),
104
+      lsdjmc: const StringConverter().fromJson(json['lsdjmc']),
105
+      lqgsdw: const StringConverter().fromJson(json['lqgsdw']),
106
+      rcsj: const StringConverter().fromJson(json['rcsj']),
107
+      shnd: const StringConverter().fromJson(json['shnd']),
108
+      cd: const StringConverter().fromJson(json['cd']),
109
+      cfzt: const StringConverter().fromJson(json['cfzt']),
110
+      cflx: const StringConverter().fromJson(json['cflx']),
111
+      ajsjcr: const StringConverter().fromJson(json['ajsjcr']),
112
+      jjsl: const StringConverter().fromJson(json['jjsl']),
113
+      sjsynx: const StringConverter().fromJson(json['sjsynx']),
114
+      zjbgdh: const StringConverter().fromJson(json['zjbgdh']),
115
+      jysj: const StringConverter().fromJson(json['jysj']),
116
+      jyr: const StringConverter().fromJson(json['jyr']),
117
+      jylb: const StringConverter().fromJson(json['jylb']),
118
+      spaqzb: const StringConverter().fromJson(json['spaqzb']),
119
+      rkrq: const StringConverter().fromJson(json['rkrq']),
120
+      jyxm: const StringConverter().fromJson(json['jyxm']),
121
+      jyxmz: const StringConverter().fromJson(json['jyxmz']),
122
+      ckg: const StringConverter().fromJson(json['ckg']),
123
+      zjsjList: const StringConverter().fromJson(json['zjsjList']),
124
+      isUnanimous: const StringConverter().fromJson(json['isUnanimous']),
125
+      reason: const StringConverter().fromJson(json['reason']),
126
+      itemList: (json['itemList'] as List<dynamic>?)
127
+          ?.map((e) => e == null
128
+              ? null
129
+              : storehouseRspItemList.fromJson(e as Map<String, dynamic>))
130
+          .toList(),
131
+    );
132
+
133
+Map<String, dynamic> _$storehouseRspToJson(storehouseRsp instance) =>
134
+    <String, dynamic>{
135
+      'kqmc': const StringConverter().toJson(instance.kqmc),
136
+      'tycfbm': const StringConverter().toJson(instance.tycfbm),
137
+      'cfmc': const StringConverter().toJson(instance.cfmc),
138
+      'ajmc': const StringConverter().toJson(instance.ajmc),
139
+      'hwmc': const StringConverter().toJson(instance.hwmc),
140
+      'tyhwbm': const StringConverter().toJson(instance.tyhwbm),
141
+      'bgr': const StringConverter().toJson(instance.bgr),
142
+      'jfsyrq': const StringConverter().toJson(instance.jfsyrq),
143
+      'cnzlxg': const StringConverter().toJson(instance.cnzlxg),
144
+      'cmsl': const StringConverter().toJson(instance.cmsl),
145
+      'clgx': const StringConverter().toJson(instance.clgx),
146
+      'lspzmc': const StringConverter().toJson(instance.lspzmc),
147
+      'lsxzmc': const StringConverter().toJson(instance.lsxzmc),
148
+      'lsdjmc': const StringConverter().toJson(instance.lsdjmc),
149
+      'lqgsdw': const StringConverter().toJson(instance.lqgsdw),
150
+      'rcsj': const StringConverter().toJson(instance.rcsj),
151
+      'shnd': const StringConverter().toJson(instance.shnd),
152
+      'cd': const StringConverter().toJson(instance.cd),
153
+      'cfzt': const StringConverter().toJson(instance.cfzt),
154
+      'cflx': const StringConverter().toJson(instance.cflx),
155
+      'ajsjcr': const StringConverter().toJson(instance.ajsjcr),
156
+      'jjsl': const StringConverter().toJson(instance.jjsl),
157
+      'sjsynx': const StringConverter().toJson(instance.sjsynx),
158
+      'zjbgdh': const StringConverter().toJson(instance.zjbgdh),
159
+      'jysj': const StringConverter().toJson(instance.jysj),
160
+      'jyr': const StringConverter().toJson(instance.jyr),
161
+      'jylb': const StringConverter().toJson(instance.jylb),
162
+      'spaqzb': const StringConverter().toJson(instance.spaqzb),
163
+      'rkrq': const StringConverter().toJson(instance.rkrq),
164
+      'jyxm': const StringConverter().toJson(instance.jyxm),
165
+      'jyxmz': const StringConverter().toJson(instance.jyxmz),
166
+      'ckg': const StringConverter().toJson(instance.ckg),
167
+      'zjsjList': const StringConverter().toJson(instance.zjsjList),
168
+      'isUnanimous': const StringConverter().toJson(instance.isUnanimous),
169
+      'reason': const StringConverter().toJson(instance.reason),
170
+      'itemList': instance.itemList,
171
+    };

+ 5 - 5
lib/network/my_api.dart

@@ -6,14 +6,14 @@ import 'api.dart';
6 6
 class MyApi {
7 7
   MyApi._();
8 8
 
9
-  /// 生产url
10
-  static String productUrl = 'http://121.36.17.6:39099';
9
+  /// 华为 生产url
10
+  //static String productUrl = 'http://121.36.17.6:39099';
11 11
 
12
-  /// 紫光正式
13
-  //static String productUrl = 'http://101.36.160.117:39099';
12
+  /// 紫光 生产正式 url
13
+  static String productUrl = 'http://101.36.160.117:39099';
14 14
 
15 15
   /// 测试url
16
-  static String testUrl = 'http://121.36.17.6:19090';
16
+  static String testUrl = 'http://101.36.160.117:31070';
17 17
 
18 18
   static late String globalUrl;
19 19
 

+ 171 - 0
lib/page/home/store_house_page.dart

@@ -0,0 +1,171 @@
1
+import 'dart:convert';
2
+
3
+import 'package:dotted_border/dotted_border.dart';
4
+import 'package:flutter/material.dart';
5
+import 'package:flutter/services.dart';
6
+import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
7
+import 'package:lszlgl/base/base_lifecycle_state.dart';
8
+import 'package:lszlgl/base/base_vm.dart';
9
+import 'package:lszlgl/config/borders.dart';
10
+import 'package:lszlgl/main.dart';
11
+import 'package:lszlgl/model/api_rsp.dart';
12
+import 'package:lszlgl/model/rsp/storehouse_rsp.dart';
13
+import 'package:lszlgl/widget/page_widget.dart';
14
+import 'package:lszlgl/widget/storehouse_item.dart';
15
+
16
+
17
+class StoreHousePage extends StatefulWidget {
18
+  final String houseNum;
19
+
20
+  const StoreHousePage({super.key, required this.houseNum});
21
+
22
+  @override
23
+  State<StoreHousePage> createState() => _StoreHousePageState();
24
+}
25
+
26
+class _StoreHousePageState extends BaseLifecycleState<StoreHousePage> {
27
+  final pageState = DataStatusModel<storehouseRsp?>().notifier<DataStatusModel<storehouseRsp?>>();
28
+  storehouseRsp? data;
29
+  final ValueNotifier<String> _title = ValueNotifier<String>('仓房信息');
30
+
31
+  @override
32
+  void onFirstShow(Duration timeStamp) {
33
+    loadData();
34
+  }
35
+
36
+  @override
37
+  void onDestroy() {
38
+    pageState.dispose();
39
+  }
40
+
41
+  void loadData() async{
42
+    pageState.update(pageState.value.loading());
43
+    try{
44
+      String jsonStr = await Future.delayed(const Duration(seconds: 3),()async{
45
+        return rootBundle.loadString('assets/json/storehouse.json');
46
+      });
47
+      Map<String,dynamic> val = json.decode(jsonStr);
48
+      ApiRsp<List<storehouseRsp?>> res= ApiRsp<List<storehouseRsp>>.fromJson(
49
+        val,
50
+            (json) => json is List<dynamic>
51
+            ? json
52
+            .map<storehouseRsp>((i) => storehouseRsp.fromJson(i as Map<String, dynamic>))
53
+            .toList()
54
+            : List.empty(),
55
+      );
56
+      if(res.data == null ){
57
+        pageState.update(pageState.value.empty());
58
+      }else{
59
+        data = res.data!.first;
60
+        _title.value = data?.kqmc ?? '仓房信息' ;
61
+        pageState.update(pageState.value.success(data: res.data!.first));
62
+      }
63
+    }catch(e){
64
+      logger.e(e);
65
+      pageState.update(pageState.value.error());
66
+    }
67
+  }
68
+
69
+
70
+  @override
71
+  Widget build(BuildContext context) {
72
+    return myScaffold(
73
+        child: KeyboardDismissOnTap(
74
+          dismissOnCapturedTaps: true,
75
+            child: Column(
76
+              children: [
77
+                ValueListenableBuilder(
78
+                  valueListenable: _title,
79
+                  builder: (_,String title,__){
80
+                    return myAppBar(title: title);
81
+                  },
82
+                ),
83
+                Expanded(
84
+                    child:Container(
85
+                      color: Colors.white,
86
+                      child: SingleChildScrollView(
87
+                        child: pageState.builder((v){
88
+                          if(v.status == DataStatus.error){
89
+                            return PageLoadingWidget.error(onTap: loadData);
90
+                          }
91
+
92
+                          if(v.status == DataStatus.empty){
93
+                            return const PageLoadingWidget.empty();
94
+                          }
95
+
96
+                          if(v.status == DataStatus.loading){
97
+                            return const PageLoadingWidget.loading();
98
+                          }
99
+
100
+                          return Column(
101
+                            //crossAxisAlignment: CrossAxisAlignment.stretch,
102
+                            children: [
103
+                              Padding(padding: const EdgeInsets.fromLTRB(22, 20, 22, 4),
104
+                              child: Column(
105
+                                crossAxisAlignment: CrossAxisAlignment.stretch,
106
+                                children: [
107
+                                  Text(data?.cfmc ?? '',style: TextStyles.titA,),
108
+                                  const SizedBox(height: 12),
109
+                                  Text('仓房编号:${data?.tycfbm}',style: TextStyles.titA),
110
+                                  const SizedBox(height: 12),
111
+                                  const Divider(thickness: 0.6,),
112
+                                  const SizedBox(height: 6),
113
+                                  StorehouseItem(special: true,left: data?.cflx,right: data?.cfzt),
114
+                                  StorehouseItem(left: '保管员',right: data?.bgr),
115
+                                  StorehouseItem(left: '交付使用日期', right: data?.jfsyrq),
116
+                                  const SizedBox(height: 10),
117
+                                  const Divider(thickness: 0.6,),
118
+                                ],
119
+                              ),
120
+                              ),
121
+                              const StoreHouseTit(tit: '仓房信息'),
122
+                              Padding(padding: const EdgeInsets.fromLTRB(22, 8, 22, 4),
123
+                              child:Column(
124
+                                crossAxisAlignment: CrossAxisAlignment.stretch,
125
+                                children: [
126
+                                  StorehouseItem(left: '设计仓容',right: '${data?.ajsjcr}吨',),
127
+                                  StorehouseItem(left: '设计使用年限',right: '${data?.sjsynx}年',),
128
+                                  StorehouseItem(left: '装粮线高',right: '${data?.cnzlxg}米',),
129
+                                  StorehouseItem(left: '长*宽*高',right: data?.ckg,),
130
+                                  const SizedBox(height: 10),
131
+                                  const Divider(thickness: 0.6,),
132
+                                ],
133
+                              )
134
+                              ),
135
+                              const StoreHouseTit(tit: '粮食库存'),
136
+                              Container(
137
+                                padding: const EdgeInsets.symmetric(horizontal:22,vertical: 12),
138
+                                child: DottedBorder(
139
+                                  strokeWidth: 0.8,
140
+                                  color: Colors.grey,
141
+                                  dashPattern:const[3,4],
142
+                                  padding: const EdgeInsets.all(8),
143
+                                  child: Column(
144
+                                    crossAxisAlignment: CrossAxisAlignment.stretch,
145
+                                    children: [
146
+                                      StorehouseItem(left: '粮食品种',right: data?.itemList?.first?.lspzmc),
147
+                                      StorehouseItem(left: '粮食等级',right: data?.itemList?.first?.lsdjmc),
148
+                                      StorehouseItem(left: '库存',right: '${data?.itemList?.first?.jjsl}吨'),
149
+                                      StorehouseItem(left: '储存性质',right: data?.itemList?.first?.lsxzmc),
150
+                                      StorehouseItem(left: '粮权归属单位',right: data?.itemList?.first?.lqgsdw),
151
+                                      StorehouseItem(left: '入仓时间',right: data?.itemList?.first?.timeStr()),
152
+                                      StorehouseItem(left: '产地',right: data?.itemList?.first?.cd),
153
+                                      StorehouseItem(left: '收货年度',right: '${data?.itemList?.first?.shnd}年'),
154
+                                    ],
155
+                                  ),
156
+                                ),
157
+                              )
158
+                            ],
159
+                          );
160
+                        }
161
+                        ),
162
+                      ),
163
+                    )
164
+
165
+                ),
166
+              ],
167
+            )
168
+        ),
169
+    );
170
+  }
171
+}

+ 180 - 0
lib/page/login/forget_password_page.dart

@@ -0,0 +1,180 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
3
+import 'package:lszlgl/base/base_state.dart';
4
+import 'package:lszlgl/config/borders.dart';
5
+import 'package:lszlgl/main.dart';
6
+import 'package:lszlgl/network/my_api.dart';
7
+import 'package:lszlgl/utils/string_utils.dart';
8
+import 'package:lszlgl/widget/button.dart';
9
+import 'package:lszlgl/widget/countdown_button_widget.dart';
10
+
11
+class ForgetPasswordPage extends StatefulWidget {
12
+  const ForgetPasswordPage({super.key});
13
+
14
+  @override
15
+  State<ForgetPasswordPage> createState() => _ForgetPasswordPageState();
16
+}
17
+
18
+class _ForgetPasswordPageState extends BaseState<ForgetPasswordPage> {
19
+  late GlobalKey<FormState> textFormKey;
20
+  late TextEditingController phoneCtrl;
21
+  late TextEditingController msgCtrl;
22
+  late TextEditingController pwdCtrl;
23
+
24
+  @override
25
+  void initState() {
26
+    super.initState();
27
+    textFormKey = GlobalKey<FormState>();
28
+    phoneCtrl = TextEditingController();
29
+    msgCtrl = TextEditingController();
30
+    pwdCtrl = TextEditingController();
31
+  }
32
+
33
+  /// 重置密码
34
+  void resetPwd() async{
35
+    MyNavigator.showLoading(msg: '密码设置中...');
36
+    try{
37
+      var res = await MyApi.get().resetPassword({
38
+        'username': phoneCtrl.text,
39
+        'password': pwdCtrl.text,
40
+        'code':msgCtrl.text,
41
+      });
42
+      if(res.data ?? false){
43
+        MyNavigator.showToast('密码设置成功');
44
+        MyNavigator.pop();
45
+      }
46
+    }catch(e){
47
+      logger.e(e);
48
+    }
49
+    MyNavigator.dismissLoading();
50
+  }
51
+
52
+  @override
53
+  Widget build(BuildContext context) {
54
+    return myScaffold(
55
+        child: KeyboardDismissOnTap(
56
+            dismissOnCapturedTaps: true,
57
+            child: Column(
58
+              children: [
59
+                myAppBar(title: '忘记密码'),
60
+                Expanded(
61
+                    child: Container(
62
+                  color: Colors.white,
63
+                  child: SingleChildScrollView(
64
+                    padding: const EdgeInsets.fromLTRB(22, 40, 22, 20),
65
+                    child: Form(
66
+                      key: textFormKey,
67
+                      child: Column(
68
+                        children: [
69
+                          TextFormField(
70
+                            controller: phoneCtrl,
71
+                            keyboardType: TextInputType.number,
72
+                            decoration: const InputDecoration(
73
+                              hintText: '手机号',
74
+                              contentPadding: EdgeInsets.symmetric(horizontal: 20,vertical: 6),
75
+                              border: Borders.borderA,
76
+                              enabledBorder: Borders.borderB,
77
+                            ),
78
+                            validator: (val){
79
+                              return StringUtils.isPhoneNum(val) ? null : '请输入手机号';
80
+                            },
81
+                          ),
82
+                          const SizedBox(height: 16),
83
+
84
+                          TextFormField(
85
+                            controller: msgCtrl,
86
+                            keyboardType: TextInputType.number,
87
+                            decoration: InputDecoration(
88
+                              hintText: '验证码',
89
+                              contentPadding: const EdgeInsets.symmetric(horizontal: 20,vertical: 6),
90
+                              border: Borders.borderA,
91
+                              enabledBorder: Borders.borderB,
92
+                              suffixIconConstraints: const BoxConstraints(maxHeight: 26),
93
+                              suffixIcon: Padding(
94
+                                padding: const EdgeInsets.only(right: 20),
95
+                                child: CountdownButtonWidget(
96
+                                  phoneController: phoneCtrl,
97
+                                ),
98
+                              ),
99
+                            ),
100
+                            validator: (value){
101
+                              return value!.trim().isEmpty ? '请输入验证码' : null;
102
+                            },
103
+                          ),
104
+                          const SizedBox(height: 16),
105
+
106
+                          TextFormField(
107
+                            controller: pwdCtrl,
108
+                            obscureText: true,
109
+                            decoration: const InputDecoration(
110
+                              hintText: '新密码',
111
+                              contentPadding: EdgeInsets.symmetric(horizontal: 20,vertical: 6),
112
+                              border: Borders.borderA,
113
+                              enabledBorder: Borders.borderB,
114
+                            ),
115
+                            validator: (val){
116
+                              if(val!.length < 8){
117
+                                return '密码长度要大于8位';
118
+                              }
119
+                              var regex = RegExp(r'\d');
120
+                              if (!regex.hasMatch(val)) {
121
+                                return '密码要包含数字';
122
+                              }
123
+                              regex = RegExp(r'[a-zA-Z]');
124
+                              if (!regex.hasMatch(val)) {
125
+                                return '密码要包含大写字母或小写字母';
126
+                              }
127
+                              regex = RegExp(r'[!\"#$%&()*+,-./:;<=>?@\]\[^_`{|}~]');
128
+                              if (!regex.hasMatch(val)) {
129
+                                return '密码要包含特殊字符';
130
+                              }
131
+                              return null;
132
+                            },
133
+                          ),
134
+                          const SizedBox(height: 16),
135
+
136
+                          TextFormField(
137
+                            obscureText: true,
138
+                            decoration: const InputDecoration(
139
+                                hintText: '再次输入新密码',
140
+                                contentPadding: EdgeInsets.symmetric(horizontal: 20,vertical: 6),
141
+                                border: Borders.borderA,
142
+                                enabledBorder: Borders.borderB,
143
+                            ),
144
+                            validator: (val){
145
+                              if(val!.trim().isEmpty){
146
+                                return '请再次输入新密码';
147
+                              }
148
+                              if(val != pwdCtrl.text){
149
+                                return '两次输入密码不一致';
150
+                              }
151
+                              return null;
152
+                            },
153
+                          ),
154
+                          const SizedBox(height: 20),
155
+
156
+                          const Text(
157
+                            '*密码长度大于8位,包含数字、字母和特殊字符。',
158
+                            style: TextStyle(color: Colors.black54),
159
+                          ),
160
+                          const SizedBox(height: 36),
161
+
162
+                          MyButton(
163
+                            '确定',
164
+                            gradient: const LinearGradient(colors: [Color(0xFF3BD2E5), Color(0xFF247AF8)]),
165
+                            minHeight: 40,
166
+                            onTap: () {
167
+                              if (textFormKey.currentState!.validate()) {
168
+                                resetPwd();
169
+                              }
170
+                            },
171
+                          ),
172
+                        ],
173
+                      ),
174
+                    ),
175
+                  ),
176
+                )),
177
+              ],
178
+            )));
179
+  }
180
+}

+ 13 - 0
lib/page/qrcode_scan/qrcode_scan_page.dart

@@ -39,6 +39,19 @@ class _QrCodeScanPageState extends BaseLifecycleState<QrCodeScanPage> with Singl
39 39
       showErrorDialog('内容为空,请扫描正确二维码');
40 40
       return;
41 41
     }
42
+
43
+    // 库房详情  http://121.36.17.6:18089/?ajbm=3291653123710827520U010011
44
+    if(code.contains('?ajbm=')){
45
+      List<String> list = code.split('ajbm=');
46
+      if(list.last.isEmpty){
47
+        showErrorDialog(code);
48
+        return;
49
+      }else{
50
+        MyRouter.startStoreHouse(list.last);
51
+        return;
52
+      }
53
+    }
54
+
42 55
     // 121.36.17.6:19090/admin-api/zj/code-sampling-task-details-sgjc/getSamplingTaskDetails?id=47106
43 56
     List<String> split = code.split('?');
44 57
     if (!code.contains('?') || split.length <= 1 || !split[0].contains('/')) {

+ 9 - 0
lib/router/my_router.dart

@@ -1,4 +1,5 @@
1 1
 import 'package:lszlgl/base/base_lifecycle_state.dart';
2
+import 'package:lszlgl/page/home/store_house_page.dart';
2 3
 import 'package:lszlgl/page/login/forget_password_page.dart';
3 4
 import 'package:lszlgl/page/login/login_page.dart';
4 5
 import 'package:lszlgl/page/main_tab_page.dart';
@@ -41,6 +42,8 @@ const rConnectPrintPage = '/ConnectPrintPage';
41 42
 const rQrCodeScanPage = '/QrCodeScanPage';
42 43
 // 忘记密码
43 44
 const rForgetPasswordPage = '/ForgetPasswordPage';
45
+// 仓库信息
46
+const rStoreHousePage = '/StoreHousePage';
44 47
 
45 48
 final Map<String, MyNavigatorBuilder> rRouteMap = {
46 49
   // 根页面
@@ -57,6 +60,7 @@ final Map<String, MyNavigatorBuilder> rRouteMap = {
57 60
   rConnectPrintPage: (context, args) => ConnectPrintPage(args: args as ConnectPrintPageArgs),
58 61
   rQrCodeScanPage: (context, args) => const QrCodeScanPage(),
59 62
   rForgetPasswordPage:(context,args) => const ForgetPasswordPage(),
63
+  rStoreHousePage:(context,args) => StoreHousePage(houseNum: args as String),
60 64
 };
61 65
 
62 66
 class MyRouter {
@@ -115,6 +119,11 @@ class MyRouter {
115 119
     }
116 120
   }
117 121
 
122
+  /// 仓库详情
123
+  static void startStoreHouse(String num) {
124
+    MyNavigator.pushReplace(rStoreHousePage, args: num);
125
+  }
126
+
118 127
   /// 库存扦样任务
119 128
   static Future<dynamic> startStockSampleTask({StockSampleTaskPageArgs? args}) {
120 129
     return MyNavigator.push(rStockSampleTaskPage, args: args ?? StockSampleTaskPageArgs());

+ 33 - 0
lib/service/jgpush_service.dart

@@ -0,0 +1,33 @@
1
+
2
+import 'package:jpush_flutter/jpush_flutter.dart';
3
+import 'package:lszlgl/config/app_config.dart';
4
+
5
+class JGPushService{
6
+  static final JPush jPush = JPush();
7
+
8
+
9
+  static Future<void> jgInit(AppEnvironment env) async{
10
+    jPush.setup(
11
+      // 极光推送 正式环境appkey需要再申请
12
+      appKey: env == AppEnvironment.product ? '???' : '2f42e3db4d0083b0bc5a3f6c',
13
+      channel: 'developer-default',
14
+      production: env == AppEnvironment.product ? true : false,
15
+      debug: env == AppEnvironment.develop ? true : false
16
+    );
17
+
18
+    jPush.addEventHandler(
19
+      // 接收通知回调方法。
20
+      onReceiveNotification: (Map<String, dynamic> message) async {
21
+        print("flutter onReceiveNotification: $message");
22
+      },
23
+      // 点击通知回调方法。
24
+      onOpenNotification: (Map<String, dynamic> message) async {
25
+        print("flutter onOpenNotification: $message");
26
+      },
27
+      // 接收自定义消息回调方法。
28
+      onReceiveMessage: (Map<String, dynamic> message) async {
29
+        print("flutter onReceiveMessage: $message");
30
+      },
31
+    );
32
+  }
33
+}

+ 112 - 0
lib/widget/countdown_button_widget.dart

@@ -0,0 +1,112 @@
1
+import 'dart:async';
2
+
3
+import 'package:flutter/material.dart';
4
+import 'package:lszlgl/base/base_lifecycle_state.dart';
5
+import 'package:lszlgl/config/colors.dart';
6
+import 'package:lszlgl/main.dart';
7
+import 'package:lszlgl/network/my_api.dart';
8
+import 'package:lszlgl/utils/string_utils.dart';
9
+
10
+
11
+/// 倒计时按钮
12
+class CountdownButtonWidget extends StatefulWidget {
13
+  /// 倒计时总秒数
14
+  final int timeCount;
15
+  /// 手机号
16
+  final TextEditingController phoneController;
17
+
18
+  const CountdownButtonWidget({
19
+    Key? key,
20
+    this.timeCount = 60,
21
+    required this.phoneController,
22
+  }) : super(key: key);
23
+
24
+  @override
25
+  State<CountdownButtonWidget> createState() => _CountdownButtonWidgetState();
26
+}
27
+
28
+class _CountdownButtonWidgetState extends State<CountdownButtonWidget> {
29
+  Timer? _timer;
30
+  //倒计时数值
31
+  var _countdownTime = 0;
32
+  @override
33
+  Widget build(BuildContext context) {
34
+    return GestureDetector(
35
+      child: Text(
36
+        _handleBtnText(),
37
+        style: const TextStyle(
38
+            color: MyColor.c_25A6EE, fontSize: 14),
39
+      ),
40
+      onTap: () async{
41
+        if (_countdownTime == 0) {
42
+          if (!StringUtils.isPhoneNum(widget.phoneController.text)) {
43
+            MyNavigator.showToast('请输入正确的手机号');
44
+            return;
45
+          }
46
+
47
+          bool isPost = await getPhoneMsg();
48
+          if(!isPost){
49
+            return;
50
+          }
51
+         // print('可以发送了');
52
+          _startCountdown();
53
+        }
54
+      },
55
+    );
56
+  }
57
+
58
+  /// 获取验证码
59
+  Future<bool> getPhoneMsg() async{
60
+    try{
61
+      var res = await MyApi.get().postPhoneMsg({
62
+        'mobile': widget.phoneController.text,
63
+        'scene': 23,
64
+      });
65
+      //print('$res.data');
66
+      if( res.data ?? false){
67
+        MyNavigator.showToast('验证码已发送');
68
+        return true;
69
+      }else{
70
+        return false;
71
+      }
72
+    }catch(e){
73
+      logger.e(e);
74
+      return false;
75
+    }
76
+  }
77
+
78
+  String _handleBtnText() {
79
+    if (_countdownTime > 0) {
80
+      return '剩余$_countdownTime秒';
81
+    } else {
82
+      return '获取验证码';
83
+    }
84
+  }
85
+
86
+  //倒计时方法
87
+  void _startCountdown() {
88
+    //倒计时时间
89
+    _countdownTime = widget.timeCount;
90
+    if (_timer != null) {
91
+      // 如果timer已存在要先取消置空
92
+      _timer!.cancel();
93
+      _timer = null;
94
+    }
95
+    _timer = Timer.periodic(const Duration(seconds: 1), (timer) {
96
+      if (_countdownTime < 1) {
97
+        _timer?.cancel();
98
+      } else {
99
+        setState(() {
100
+          _countdownTime -= 1;
101
+        });
102
+      }
103
+    });
104
+  }
105
+
106
+  @override
107
+  void dispose() {
108
+    _timer?.cancel();
109
+    _timer = null;
110
+    super.dispose();
111
+  }
112
+}

+ 89 - 0
lib/widget/storehouse_item.dart

@@ -0,0 +1,89 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/config/borders.dart';
3
+
4
+class StorehouseItem extends StatelessWidget {
5
+  final String? left;
6
+  final String? right;
7
+  final bool special;
8
+  const StorehouseItem({
9
+    super.key,
10
+    this.left,
11
+    this.right,
12
+    this.special = false,
13
+  });
14
+
15
+  @override
16
+  Widget build(BuildContext context) {
17
+    return Padding(
18
+      padding: const EdgeInsets.symmetric(vertical: 4),
19
+      child: Row(
20
+        crossAxisAlignment: CrossAxisAlignment.start,
21
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
22
+        children: [
23
+          Expanded(
24
+            child: Text(
25
+              left ?? '',
26
+              style: special ? TextStyles.titA : TextStyles.titB,
27
+              maxLines: null,
28
+            ),
29
+          ),
30
+
31
+          const SizedBox(width: 20),
32
+
33
+          Expanded(
34
+            child: special
35
+                ? Padding(
36
+                    padding: const EdgeInsets.only(left: 40),
37
+                    child: Container(
38
+                        alignment: Alignment.center,
39
+                        decoration: BoxDecoration(
40
+                            color: const Color(0xFFE0F2F1),
41
+                            border: Border.all(color: const Color(0xFF4DB6AC), width: 1.0),
42
+                            borderRadius: BorderRadius.circular(12) // 设置边框样式
43
+                            ),
44
+                        child: Text(right ?? '',
45
+                            style: const TextStyle(fontSize: 14, color: Color(0xFF4DB6AC)))),
46
+                  )
47
+                : Text(
48
+                    right ?? '',
49
+                    style: TextStyles.titC,
50
+                    maxLines: null,
51
+                    textAlign: TextAlign.right,
52
+                  ),
53
+          ),
54
+        ],
55
+      ),
56
+    );
57
+  }
58
+}
59
+
60
+// 绿色圆点加标题
61
+class StoreHouseTit extends StatelessWidget {
62
+  final String tit;
63
+  const StoreHouseTit({super.key, required this.tit});
64
+
65
+  @override
66
+  Widget build(BuildContext context) {
67
+    return Padding(
68
+      padding: const EdgeInsets.only(left: 6),
69
+      child: Row(
70
+        children: [
71
+          Container(
72
+            width: 10,
73
+            height: 10,
74
+            decoration:const BoxDecoration(
75
+              color:  Color(0xFF4DB6AC),
76
+              shape: BoxShape.circle,
77
+            ),
78
+          ),
79
+          const SizedBox(width: 4),
80
+          Text(tit,style: TextStyles.titA)
81
+        ],
82
+      ),
83
+    );
84
+  }
85
+}
86
+
87
+
88
+// const Color(0xFFE0F2F1)   const Color(0xFF4DB6AC)
89
+//  Text(right ?? '',style:const TextStyle(fontSize: 15,color: Color(0xFF4DB6AC

+ 2 - 0
pubspec.yaml

@@ -97,6 +97,8 @@ dependencies:
97 97
   app_settings: ^5.1.1
98 98
   # 极光推送
99 99
   jpush_flutter: 3.0.3
100
+  # 虚线边框
101
+  dotted_border: ^2.1.0
100 102
 
101 103
 dev_dependencies:
102 104
   flutter_test: