Browse Source

btp型号打印机添加批量打印功能。发布28版本。

liujq 1 month ago
parent
commit
e57146565b

+ 12 - 10
android/app/src/main/java/io/flutter/plugins/BluetoothPlugin.java

@@ -175,9 +175,9 @@ public class BluetoothPlugin implements FlutterPlugin, MethodChannel.MethodCallH
175 175
                 Log.d("ble", "startBluetoothPrintText :" + methodCall.arguments);
176 176
                 startBluetoothPrintText(methodCall, result);
177 177
                 break;
178
-            case "startBluetoothPrintBarCode":
179
-                Log.d("ble", "startBluetoothPrintBarCode :" + methodCall.arguments);
180
-                startBluetoothPrintBarCode(methodCall, result);
178
+            case "startBluetoothPrintBarCodeWithText":
179
+                Log.d("ble", "startBluetoothPrintBarCodeWithText :" + methodCall.arguments);
180
+                startBluetoothPrintBarCodeWithText(methodCall, result);
181 181
                 break;
182 182
             case "startBluetoothPrintBitMapAndText":
183 183
                 Log.d("ble", "PrintBitMapAndText :" + methodCall.arguments);
@@ -376,12 +376,14 @@ public class BluetoothPlugin implements FlutterPlugin, MethodChannel.MethodCallH
376 376
     }
377 377
 
378 378
 
379
-    void startBluetoothPrintBarCode(@NonNull MethodCall methodCall, @NonNull MethodChannel.Result result) {
380
-
381
-        byte[] imageByte = (byte[]) methodCall.arguments;
379
+    void startBluetoothPrintBarCodeWithText(@NonNull MethodCall methodCall, @NonNull MethodChannel.Result result) {
380
+        HashMap map = (HashMap)methodCall.arguments;
381
+        String brCode = (String) map.get("barCode");
382
+        String text = (String) map.get("text");
383
+        ArrayList<String> textList = (ArrayList<String>) map.get("textList");
382 384
 
383
-        Log.d("ble", "imageByte:" + imageByte);
384
-        Bitmap bitmap = Bytes2Bimap(imageByte);
385
+        Log.d("ble", "~~~!!!@@@@@!!!brcode:" + brCode);
386
+//        Bitmap bitmap = Bytes2Bimap(imageByte);
385 387
 
386 388
         BluetoothDevice bluetoothDevice = mBluetoothAdapter.getRemoteDevice(itemPosition.getDeviceHardwareAddress());
387 389
         if (ActivityCompat.checkSelfPermission(_applicationContext, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
@@ -389,9 +391,9 @@ public class BluetoothPlugin implements FlutterPlugin, MethodChannel.MethodCallH
389 391
         }
390 392
         BlueDeviceInfo blueDeviceInfo = new BlueDeviceInfo(bluetoothDevice.getName(), bluetoothDevice.getAddress(), itemPosition.getConnectState());
391 393
         if(blueDeviceInfo.getDeviceName().contains("BTP")) {
392
-            BTPPrintUtil.printBitMap(bitmap, blueDeviceInfo.getDeviceName(), result);
394
+            BTPPrintUtil.printBarCodeWithText(brCode, text, textList, result);
393 395
         } else {
394
-            PrintUtil.printBitMap(bitmap, result);
396
+          //  PrintUtil.printBitMap(bitmap, result);
395 397
         }
396 398
     }
397 399
 

+ 71 - 0
android/app/src/main/java/io/flutter/plugins/utils/BTPPrintUtil.java

@@ -130,6 +130,77 @@ public class BTPPrintUtil {
130 130
         result.success(code == 0 ? true : false);
131 131
     }
132 132
 
133
+    public  static void printBarCodeWithText(String barCode, String text, ArrayList<String> textList,@NonNull MethodChannel.Result result) {
134
+        getInstance().SetLabelSize(560,640*2);
135
+        // 二维码
136
+        labelPrinter.PrintBarcodeQR(90, 40,  0, barCode, 'M', 8, 2);
137
+
138
+        //质量 品质 食安选项框
139
+        labelPrinter.PrintRectangle(100, 440, 20, 20, 1);
140
+        labelPrinter.PrintText(124, 440, "3", "质量", 0, 7, 0, 0);
141
+
142
+        labelPrinter.PrintRectangle(220, 440, 20, 20, 1);
143
+        labelPrinter.PrintText(244, 440, "3", "品质", 0, 7, 0, 0);
144
+
145
+        labelPrinter.PrintRectangle(340, 440, 20, 20, 1);
146
+        labelPrinter.PrintText(364, 440, "3", "食安", 0, 7, 0, 0);
147
+
148
+        // 编号 labelPrinter.PrintText(100, 500, "8", "SHXM2024007404", 0, 7, 3, 0);
149
+        labelPrinter.PrintText(120, 500, "5", text, 0, 0, 0, 0);
150
+
151
+        //
152
+        int width = 560;
153
+        int height = 640;
154
+
155
+        int marginX = 2;
156
+        int marginY = 80;
157
+        //矩形框类型
158
+        int rectangleWidth = width - marginX * 2;
159
+        int rectangleHeight = height - marginY * 2;
160
+        int lineWidth = 1;
161
+
162
+        int lineHeight = rectangleHeight / 6;
163
+
164
+        int titleWidth = rectangleWidth / 2;
165
+
166
+        float fontSize = 3;
167
+        // 设置初始偏移量
168
+        int offsetY = 680;
169
+        int offsetX = 0;
170
+        // 计算绘制线条的 y 坐标
171
+        int secondLineY = marginY + lineHeight * 2 - lineWidth + offsetY;
172
+        int thirdLineY = marginY + lineHeight * 3 - lineWidth + offsetY;
173
+        int fourthLineY = marginY + lineHeight * 4 - lineWidth + offsetY;
174
+        int fiveLineY = marginY + lineHeight * 5 - lineWidth + offsetY;
175
+
176
+        int textAlignHorizontal = 0; // 左对齐
177
+
178
+        labelPrinter.PrintText(marginX * 2 + offsetX, marginY + offsetY, "3", textList.get(0), 0, 7, 0, 0);
179
+        labelPrinter.PrintText(marginX * 2 + titleWidth + offsetX, marginY + offsetY, "3", textList.get(1), 0, 7, 0, 0);
180
+
181
+
182
+        labelPrinter.PrintText(marginX * 2 + offsetX, marginY + lineHeight - lineWidth + offsetY, "3", textList.get(2), 0, 7, 0, 0);
183
+
184
+
185
+        labelPrinter.PrintText(marginX * 2 + offsetX, secondLineY, "3", textList.get(3), 0, 7, 0, 0);
186
+
187
+
188
+        labelPrinter.PrintText(marginX * 2 + offsetX, thirdLineY, "3", textList.get(4), 0, 7, 0, 0);
189
+        labelPrinter.PrintText(marginX * 2 + titleWidth + offsetX, thirdLineY, "3", textList.get(5), 0, 7, 0, 0);
190
+
191
+
192
+        labelPrinter.PrintText(marginX * 2 + offsetX, fourthLineY, "3", textList.get(6), 0, 7, 0, 0);
193
+        labelPrinter.PrintText(marginX * 2 + titleWidth + offsetX, fourthLineY, "3", textList.get(7), 0, 7, 0, 0);
194
+
195
+
196
+        labelPrinter.PrintText(marginX * 2 + offsetX, fiveLineY, "3", textList.get(8), 0, 7, 0, 0);
197
+        labelPrinter.PrintText(marginX * 2 + titleWidth + offsetX, fiveLineY, "3", textList.get(9), 0, 7, 0, 0);
198
+        //
199
+
200
+        int code = getInstance().PrintLabel(1,1);
201
+        result.success(code == 0 ? true : false);
202
+    }
203
+
133 204
     // BTP打印机同时打印图标和标签只能调这个,依次printBitMap再printText会导致偶发printText不走。
134 205
     public  static  void PrintBitMapAndText(Bitmap bitmap, String deviceName, ArrayList<String> textList,@NonNull MethodChannel.Result result) {
135 206
         int x = 0;

+ 2 - 0
lib/model/rsp/sample_task_rsp.dart

@@ -115,6 +115,7 @@ class SampleTaskItem {
115 115
   String? xzqhCode; // 行政区划六位编码
116 116
   List<UrlItem>? filePictureList; // 签名图片url
117 117
   List<UrlItem>? ewmfilePictureList; // 二维码图片url
118
+  bool isSelect;
118 119
 
119 120
   SampleTaskItem({
120 121
     this.id,
@@ -206,6 +207,7 @@ class SampleTaskItem {
206 207
     this.xzqhCode,
207 208
     this.filePictureList,
208 209
     this.ewmfilePictureList,
210
+    this.isSelect = false,
209 211
   });
210 212
 
211 213
   SampleTaskItem createUI() {

+ 2 - 0
lib/model/rsp/sample_task_rsp.g.dart

@@ -132,6 +132,7 @@ SampleTaskItem _$SampleTaskItemFromJson(Map<String, dynamic> json) =>
132 132
       ewmfilePictureList: (json['ewmfilePictureList'] as List<dynamic>?)
133 133
           ?.map((e) => UrlItem.fromJson(e as Map<String, dynamic>))
134 134
           .toList(),
135
+      isSelect: json['isSelect'] as bool? ?? false,
135 136
     );
136 137
 
137 138
 Map<String, dynamic> _$SampleTaskItemToJson(SampleTaskItem instance) =>
@@ -231,6 +232,7 @@ Map<String, dynamic> _$SampleTaskItemToJson(SampleTaskItem instance) =>
231 232
       'xzqhCode': const StringConverter().toJson(instance.xzqhCode),
232 233
       'filePictureList': instance.filePictureList,
233 234
       'ewmfilePictureList': instance.ewmfilePictureList,
235
+      'isSelect': instance.isSelect,
234 236
     };
235 237
 
236 238
 UrlItem _$UrlItemFromJson(Map<String, dynamic> json) => UrlItem(

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

@@ -15,7 +15,7 @@ class HomePage extends StatefulWidget {
15 15
 
16 16
 class _HomePageState extends BaseState<HomePage> with AutomaticKeepAliveClientMixin {
17 17
   List<String> bannerList = [
18
-    'https://gd-hbimg.huaban.com/c7a22fb15d70a0a976e20fb810c048ec11c76fc31ac08-hajElf_fw658webp',
18
+    'http://121.36.17.6:19000/quality/app/zsys.png',
19 19
     'https://gd-hbimg.huaban.com/82e60fd3c61530d52ec1d01f80cfda11526c42e4495cb-6JwN1d_fw658webp',
20 20
   ];
21 21
 

+ 34 - 7
lib/page/print/print_page.dart

@@ -16,10 +16,14 @@ import 'dart:ui' as ui;
16 16
 
17 17
 class PrintPageArgs {
18 18
   /// 二维码数据
19
-  Uint8List bytes;
20
-  List<String> textList;
19
+  Uint8List? bytes;
20
+  List<String>? textList;
21
+  String? numCode ;
22
+  String? urlCode;
21 23
 
22
-  PrintPageArgs({required this.bytes, required this.textList});
24
+  List<PrintPageArgs>? printList; //  批量打印用
25
+
26
+  PrintPageArgs({ this.bytes, this.textList, this.numCode,this.urlCode,this.printList});
23 27
 
24 28
   @override
25 29
   String toString() {
@@ -60,7 +64,13 @@ class _PrintPageState extends BaseLifecycleState<PrintPage> {
60 64
     super.initState();
61 65
     serviceList = [
62 66
       ServiceModel(name: '搜索', icon: imgBleSearch, onTap: () => startScan()),
63
-      ServiceModel(name: '打印', icon: imgBlePrint, onTap: () => startPrint()),
67
+      ServiceModel(name: '打印', icon: imgBlePrint, onTap: (){
68
+        if(widget.args.printList !=null ){
69
+          startPrintList();
70
+        }else{
71
+          startPrint();
72
+        }
73
+      }),
64 74
     ];
65 75
     deviceList = [];
66 76
     deviceMacList = [];
@@ -75,6 +85,23 @@ class _PrintPageState extends BaseLifecycleState<PrintPage> {
75 85
     getLocation();
76 86
   }
77 87
 
88
+
89
+  void startPrintList() async{
90
+    if(PrintService.connectedDeviceList.last.deviceName.contains("BTP")) {
91
+      MyNavigator.showLoading(msg: '打印中...');
92
+      for (PrintPageArgs arg in widget.args.printList!) {
93
+        await PrintService.startBluetoothPrintBarCodeWithText(arg.urlCode!, arg.numCode!, arg.textList!);
94
+        await Future.delayed(const Duration(seconds: 6));
95
+      }
96
+      MyNavigator.dismissLoading();
97
+      MyNavigator.showToast('打印完成');
98
+    }else{
99
+      MyNavigator.showToast('暂时只支持BTP型号批量打印');
100
+    }
101
+
102
+  }
103
+
104
+
78 105
   /// 去打印
79 106
   Future<void> startPrint() async {
80 107
 
@@ -84,7 +111,7 @@ class _PrintPageState extends BaseLifecycleState<PrintPage> {
84 111
     }
85 112
 
86 113
     final codec = await ui.instantiateImageCodec(
87
-      widget.args.bytes,
114
+      widget.args.bytes!,
88 115
       targetHeight: 590,  // 640
89 116
       targetWidth: targetWidth, // 560
90 117
     );
@@ -96,10 +123,10 @@ class _PrintPageState extends BaseLifecycleState<PrintPage> {
96 123
 
97 124
     MyNavigator.showLoading(msg: '打印中...');
98 125
     if(PrintService.connectedDeviceList.last.deviceName.contains("BTP")) {
99
-      await PrintService.startBluetoothPrintBitMapAndText(smallUint8List!, widget.args.textList);
126
+      await PrintService.startBluetoothPrintBitMapAndText(smallUint8List!, widget.args.textList!);
100 127
     } else {
101 128
       await PrintService.startBluetoothPrintBitMap(smallUint8List!);
102
-      await PrintService.startBluetoothPrintText(widget.args.textList);
129
+      await PrintService.startBluetoothPrintText(widget.args.textList!);
103 130
     }
104 131
     MyNavigator.dismiss();
105 132
     MyNavigator.showToast('打印成功');

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

@@ -13,6 +13,8 @@ class SampleListVM extends BaseVM {
13 13
   late List<SampleTaskListReq> reqList;
14 14
   late List<ValueNotifier<DataStatusModel<List<SampleTaskItem>>>> pageStateList;
15 15
 
16
+  ValueNotifier<bool> showPrintBtn = ValueNotifier(false);
17
+
16 18
   SampleListVM() {
17 19
     pageStateList = [
18 20
       DataStatusModel<List<SampleTaskItem>>().notifier<DataStatusModel<List<SampleTaskItem>>>(),
@@ -31,6 +33,11 @@ class SampleListVM extends BaseVM {
31 33
     ];
32 34
   }
33 35
 
36
+  // 显示隐藏批量打印按钮
37
+  void showPrint(){
38
+    showPrintBtn.value = !showPrintBtn.value;
39
+  }
40
+
34 41
   /// 当前页面
35 42
   final bool currentComplete = false;
36 43
 

+ 130 - 10
lib/page/sample_task/sample_task_list_page.dart

@@ -1,3 +1,4 @@
1
+
1 2
 import 'package:easy_refresh/easy_refresh.dart';
2 3
 import 'package:flutter/material.dart';
3 4
 import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -6,13 +7,16 @@ import 'package:lszlgl/base/base_vm.dart';
6 7
 import 'package:lszlgl/config/colors.dart';
7 8
 import 'package:lszlgl/model/rsp/sample_task_rsp.dart';
8 9
 import 'package:lszlgl/network/my_api.dart';
10
+import 'package:lszlgl/page/print/print_page.dart';
9 11
 import 'package:lszlgl/page/sample_task/sample_list_vm.dart';
10 12
 import 'package:lszlgl/page/sample_task/sample_task_list_tab_page.dart';
11 13
 import 'package:lszlgl/service/dict_service.dart';
14
+import 'package:lszlgl/service/print_service.dart';
12 15
 import 'package:lszlgl/utils/date_time_utils.dart';
13 16
 import 'package:lszlgl/utils/inject.dart';
14 17
 import 'package:lszlgl/widget/button.dart';
15 18
 import 'package:lszlgl/widget/page_widget.dart';
19
+import 'package:lszlgl/widget/print_checkbox_widget.dart';
16 20
 
17 21
 import '../../main.dart';
18 22
 import 'reap_sample_detail/reap_sample_task_page.dart';
@@ -36,6 +40,7 @@ class SampleTaskListPage extends StatefulWidget {
36 40
 class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
37 41
     with AutomaticKeepAliveClientMixin {
38 42
   late SampleListVM vm;
43
+  List<num> selectList = [];
39 44
 
40 45
   /// 详情
41 46
   void startTaskDetail(bool detail, SampleTaskItem data, {num? deliveryStatus}) async {
@@ -43,7 +48,8 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
43 48
     switch (widget.type) {
44 49
       case StepType.reap:
45 50
         success = await MyRouter.startReapSampleTask(
46
-            args: ReapSampleTaskPageArgs(detail: detail, id: data.id,deliveryStatus: deliveryStatus));
51
+            args: ReapSampleTaskPageArgs(
52
+                detail: detail, id: data.id, deliveryStatus: deliveryStatus));
47 53
         break;
48 54
       case StepType.stock:
49 55
         success = await MyRouter.startStockSampleTask(
@@ -101,7 +107,12 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
101 107
   @override
102 108
   Widget build(BuildContext context) {
103 109
     super.build(context);
104
-    return buildBody();
110
+    return Stack(
111
+      children: [
112
+        buildBody(),
113
+        buildPrintBtn(),
114
+      ],
115
+    );
105 116
     //   Container(
106 117
     //   margin: const EdgeInsets.symmetric(horizontal: 8),
107 118
     //   clipBehavior: Clip.hardEdge,
@@ -114,6 +125,82 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
114 125
     // );
115 126
   }
116 127
 
128
+  // 批量打印前 获取数据
129
+  getPrintData() async{
130
+    if(selectList.isEmpty){
131
+      MyNavigator.showToast('请选择打印数据');
132
+      return;
133
+    }
134
+
135
+    MyNavigator.showLoading(msg: '数据处理中...');
136
+    var dataList = await Future.wait(selectList.map((id) => MyApi.get().sampleTaskDetailSgjc(id)));
137
+    List<SampleTaskItem?> data = dataList.map((e) => e.data).toList();
138
+    if(data.isEmpty){
139
+      MyNavigator.dismissLoading();
140
+      MyNavigator.showToast('打印数据获取有误');
141
+      return;
142
+    }
143
+  //  List<Uint8List?> imgList = await Future.wait(data.map((item)=>imageToBytes(item!.ewmfilePictureList!.first.url!)));
144
+    List<PrintPageArgs> printList = [];
145
+    for(int i = 0; i < data.length; i++){
146
+      List<String> textList = PrintService.getPrintTextListWithSampleTaskItem(data[i]);
147
+      PrintPageArgs arg = PrintPageArgs(
148
+        urlCode:'${MyApi.globalUrl}/admin-api/zj/code-sampling-task-details-sgjc/getSamplingTaskDetails?id=${data[i]!.id}' ,
149
+        numCode: data[i]!.ewmfilePictureList!.first.name,
150
+        textList: textList,
151
+      );
152
+      printList.add(arg);
153
+    }
154
+    MyNavigator.dismissLoading();
155
+
156
+    var args = PrintPageArgs(printList: printList);
157
+    await MyRouter.startPrint(args);
158
+
159
+  }
160
+
161
+  // 通过地址获取图片内容
162
+  // Future<Uint8List?> imageToBytes(String imageUrl) async {
163
+  //   try{
164
+  //     var response = await Dio().get(
165
+  //         imageUrl,
166
+  //         options: Options(responseType: ResponseType.bytes)
167
+  //     );
168
+  //     return Uint8List.fromList(response.data);
169
+  //   } catch(e){
170
+  //     logger.d(e);
171
+  //     return null;
172
+  //   }
173
+  // }
174
+
175
+  Widget buildPrintBtn() {
176
+    if (widget.type == StepType.reap && widget.tabIndex == 2) {
177
+      return ValueListenableBuilder(
178
+          valueListenable: vm.showPrintBtn,
179
+          builder: (context, show, child) {
180
+            if (show) {
181
+              return child!;
182
+            } else {
183
+              return const SizedBox.shrink();
184
+            }
185
+          },
186
+          child: Positioned(
187
+              bottom: 0,
188
+              left: 8,
189
+              right: 8,
190
+              child: MyButton(
191
+                '打 印',
192
+                radius: 8,
193
+                gradient: const LinearGradient(colors: [Color(0xFF3BD2E5), Color(0xFF247AF8)]),
194
+                onTap: () {
195
+                  getPrintData();
196
+                },
197
+              )),
198
+      );
199
+    } else {
200
+      return const SizedBox.shrink();
201
+    }
202
+  }
203
+
117 204
   Widget buildBody() {
118 205
     return EasyRefresh.builder(
119 206
       controller: vm.ctrlList[widget.tabIndex],
@@ -161,7 +248,6 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
161 248
           borderRadius: BorderRadius.all(Radius.circular(8)),
162 249
         ),
163 250
         child: Stack(
164
-          alignment: Alignment.topRight,
165 251
           children: [
166 252
             Column(
167 253
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -177,12 +263,42 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
177 263
               ],
178 264
             ),
179 265
             buildState(item.getDeliveryStatusText()),
266
+            buildSelectBtn(item),
180 267
           ],
181 268
         ),
182 269
       ),
183 270
     );
184 271
   }
185 272
 
273
+  buildSelectBtn(SampleTaskItem item){
274
+    if(widget.type == StepType.reap && item.deliveryStatus==2){
275
+      return ValueListenableBuilder(valueListenable: vm.showPrintBtn, builder: (_,show,__){
276
+        if(show){
277
+          return Positioned(
278
+            right: 0,
279
+            top: 60,
280
+            child: PrintCheckboxWidget(
281
+                list: selectList,
282
+                itemId: item.id!,
283
+                onChanged: (bool isSelect){
284
+                  item.isSelect = isSelect;
285
+                  if(isSelect){
286
+                    selectList.add(item.id!);
287
+                  }else{
288
+                    selectList.remove(item.id!);
289
+                  }
290
+                },
291
+            ),
292
+          );
293
+        }else{
294
+          return const SizedBox.shrink();
295
+        }
296
+      });
297
+    }else{
298
+      return const SizedBox.shrink();
299
+    }
300
+  }
301
+
186 302
   Widget buildTop() {
187 303
     return Row(
188 304
       children: [
@@ -208,12 +324,16 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
208 324
       img = imgQYStateOn;
209 325
       color = const Color(0xFFDEA70A);
210 326
     }
211
-    return Container(
212
-      padding: const EdgeInsets.fromLTRB(40, 4, 20, 16),
213
-      decoration: BoxDecoration(image: DecorationImage(image: AssetImage(img), fit: BoxFit.fill)),
214
-      child: Text(
215
-        state,
216
-        style: TextStyle(color: color, fontSize: 15),
327
+    return Positioned(
328
+      top: 0,
329
+      right: 0,
330
+      child: Container(
331
+        padding: const EdgeInsets.fromLTRB(40, 4, 20, 16),
332
+        decoration: BoxDecoration(image: DecorationImage(image: AssetImage(img), fit: BoxFit.fill)),
333
+        child: Text(
334
+          state,
335
+          style: TextStyle(color: color, fontSize: 15),
336
+        ),
217 337
       ),
218 338
     );
219 339
   }
@@ -320,7 +440,7 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
320 440
     } else {
321 441
       button = MyButton(
322 442
         '修改信息',
323
-        onTap: () => startTaskDetail(false, item,deliveryStatus: item.deliveryStatus),
443
+        onTap: () => startTaskDetail(false, item, deliveryStatus: item.deliveryStatus),
324 444
         fountSize: 13,
325 445
         radius: 6,
326 446
         alignment: null,

+ 18 - 3
lib/page/sample_task/sample_task_list_tab_page.dart

@@ -8,7 +8,9 @@ import 'package:lszlgl/utils/inject.dart';
8 8
 import '../filter/filter_page.dart';
9 9
 
10 10
 enum StepType {
11
+  /// 收获
11 12
   reap('收获环节', 1),
13
+  /// 库存
12 14
   stock('库存环节', 2);
13 15
 
14 16
   const StepType(this.title, this.value);
@@ -103,7 +105,11 @@ class _SampleTaskListTabPageState extends BaseLifecycleState<SampleTaskListTabPa
103 105
       children: [
104 106
         myAppBar(
105 107
           title: widget.args.type.title,
106
-          actions: [buildFilter()],
108
+          actions: [
109
+            if (widget.args.type == StepType.reap)
110
+              buildMultiplePrint(),
111
+            buildFilter(),
112
+          ],
107 113
           naviBarColor: Colors.white,
108 114
         ),
109 115
         buildTab(),
@@ -113,13 +119,22 @@ class _SampleTaskListTabPageState extends BaseLifecycleState<SampleTaskListTabPa
113 119
     );
114 120
   }
115 121
 
122
+  Widget buildMultiplePrint(){
123
+    return GestureDetector(
124
+      onTap: (){
125
+        vm.showPrint();
126
+      },
127
+      child:const Text('批量打印',style: TextStyle(fontSize: 16),),
128
+    );
129
+  }
130
+
116 131
   Widget buildFilter() {
117 132
     return GestureDetector(
118 133
       onTap: showFilter,
119 134
       behavior: HitTestBehavior.opaque,
120 135
       child: Padding(
121
-        padding: const EdgeInsets.symmetric(horizontal: 16),
122
-        child: Image.asset(imgSamFilter,width: 16),
136
+        padding: const EdgeInsets.only(left: 12,right: 16),
137
+        child: Image.asset(imgSamFilter,width: 14),
123 138
       ),
124 139
     );
125 140
   }

+ 0 - 1
lib/page/user_center/setting_page.dart

@@ -2,7 +2,6 @@ import 'package:flutter/cupertino.dart';
2 2
 import 'package:flutter/material.dart';
3 3
 import 'package:lszlgl/base/base_state.dart';
4 4
 import 'package:lszlgl/config/app_config.dart';
5
-import 'package:lszlgl/config/colors.dart';
6 5
 import 'package:lszlgl/network/my_api.dart';
7 6
 import 'package:lszlgl/service/upgrade_service.dart';
8 7
 import 'package:lszlgl/widget/button.dart';

+ 2 - 2
lib/plugin/bluetooth_plugin.dart

@@ -110,12 +110,12 @@ class BluetoothPlugin {
110 110
 
111 111
 
112 112
   //开始打印
113
-  Future<bool> startBluetoothPrintBarCodeWithText(String barCode, String text) async {
113
+  Future<bool> startBluetoothPrintBarCodeWithText(String barCode, String text,List<String> textList) async {
114 114
 
115 115
     if (Platform.isIOS) {
116 116
       return false;
117 117
     }
118
-    return _channel.invokeMethod('startBluetoothPrintBarCodeWithText', {"barCode": barCode, "text": text}).then<bool>((d) => d);
118
+    return _channel.invokeMethod('startBluetoothPrintBarCodeWithText', {"barCode": barCode, "text": text, "textList":textList}).then<bool>((d) => d);
119 119
   }
120 120
 
121 121
 

+ 2 - 2
lib/service/print_service.dart

@@ -170,10 +170,10 @@ class PrintService {
170 170
   }
171 171
 
172 172
   //开始打印二维码和文本
173
-  static Future<bool> startBluetoothPrintBarCodeWithText(String barCode, String text) async {
173
+  static Future<bool> startBluetoothPrintBarCodeWithText(String barCode, String text,List<String> textList) async {
174 174
 
175 175
     if(await canExecAction()) {
176
-      return await BluetoothPlugin.instance.startBluetoothPrintBarCodeWithText(barCode, text);
176
+      return await BluetoothPlugin.instance.startBluetoothPrintBarCodeWithText(barCode, text, textList);
177 177
     } else {
178 178
       return false;
179 179
     }

+ 57 - 0
lib/widget/print_checkbox_widget.dart

@@ -0,0 +1,57 @@
1
+import 'package:flutter/material.dart';
2
+import 'package:lszlgl/base/base_lifecycle_state.dart';
3
+
4
+class PrintCheckboxWidget extends StatefulWidget {
5
+  final num itemId;
6
+  final ValueChanged<bool> onChanged;
7
+  final List<num> list;
8
+
9
+  const PrintCheckboxWidget({
10
+    super.key,
11
+    required this.itemId,
12
+    required this.list,
13
+    required this.onChanged,
14
+  });
15
+
16
+  @override
17
+  State<PrintCheckboxWidget> createState() => _PrintCheckboxWidgetState();
18
+}
19
+
20
+class _PrintCheckboxWidgetState extends State<PrintCheckboxWidget> {
21
+  bool _select = false;
22
+
23
+  @override
24
+  void initState() {
25
+    super.initState();
26
+    for(num item in widget.list){
27
+      if(item ==widget.itemId){
28
+        _select = true;
29
+        break ;
30
+      }
31
+    }
32
+  }
33
+
34
+  @override
35
+  Widget build(BuildContext context) {
36
+    return IconButton(
37
+      iconSize: 40,
38
+      padding: const EdgeInsets.all(0),
39
+      color: Colors.white,
40
+      onPressed: () {
41
+        if(!_select && widget.list.length>=5){
42
+          MyNavigator.showToast('一次最多选5条数据');
43
+          return;
44
+        }
45
+
46
+        setState(() {
47
+          _select = !_select;
48
+        });
49
+        widget.onChanged(_select);
50
+      },
51
+      icon: Icon(
52
+        Icons.check_circle,
53
+        color: _select ? Colors.green : Colors.grey,
54
+      ),
55
+    );
56
+  }
57
+}

+ 11 - 5
lib/widget/upgrade_dialog.dart

@@ -1,5 +1,3 @@
1
-import 'dart:convert';
2
-
3 1
 import 'package:flutter/material.dart';
4 2
 import 'package:lszlgl/main.dart';
5 3
 import 'package:lszlgl/service/upgrade_service.dart';
@@ -91,12 +89,20 @@ class UpgradeDialog extends StatelessWidget {
91 89
             ),
92 90
           ),
93 91
 
92
+          const SizedBox(
93
+            width: double.infinity,
94
+            child: Text(
95
+             '更新内容:',
96
+             style:  TextStyle(fontSize: 14,color: Color(0xFF333333)),
97
+            ),
98
+          ),
99
+
94 100
           SizedBox(
95 101
             width: double.infinity,
96 102
             child: Text(
97
-             '更新内容:\n$contents',
98
-             style: const TextStyle(fontSize: 14,color: Color(0xFF333333)),
99
-                     ),
103
+              contents,
104
+              style: const TextStyle(fontSize: 14,color: Color(0xFF333333),fontWeight: FontWeight.bold),
105
+            ),
100 106
           ),
101 107
 
102 108
           const SizedBox(height: 24),

+ 1 - 1
pubspec.yaml

@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
16 16
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17 17
 # In Windows, build-name is used as the major, minor, and patch parts
18 18
 # of the product and file versions while build-number is used as the build suffix.
19
-version: 0.0.27+27
19
+version: 0.0.28+28
20 20
 
21 21
 environment:
22 22
   sdk: '>=3.1.5 <4.0.0'