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
                 Log.d("ble", "startBluetoothPrintText :" + methodCall.arguments);
175
                 Log.d("ble", "startBluetoothPrintText :" + methodCall.arguments);
176
                 startBluetoothPrintText(methodCall, result);
176
                 startBluetoothPrintText(methodCall, result);
177
                 break;
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
                 break;
181
                 break;
182
             case "startBluetoothPrintBitMapAndText":
182
             case "startBluetoothPrintBitMapAndText":
183
                 Log.d("ble", "PrintBitMapAndText :" + methodCall.arguments);
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
         BluetoothDevice bluetoothDevice = mBluetoothAdapter.getRemoteDevice(itemPosition.getDeviceHardwareAddress());
388
         BluetoothDevice bluetoothDevice = mBluetoothAdapter.getRemoteDevice(itemPosition.getDeviceHardwareAddress());
387
         if (ActivityCompat.checkSelfPermission(_applicationContext, Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
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
         BlueDeviceInfo blueDeviceInfo = new BlueDeviceInfo(bluetoothDevice.getName(), bluetoothDevice.getAddress(), itemPosition.getConnectState());
392
         BlueDeviceInfo blueDeviceInfo = new BlueDeviceInfo(bluetoothDevice.getName(), bluetoothDevice.getAddress(), itemPosition.getConnectState());
391
         if(blueDeviceInfo.getDeviceName().contains("BTP")) {
393
         if(blueDeviceInfo.getDeviceName().contains("BTP")) {
392
-            BTPPrintUtil.printBitMap(bitmap, blueDeviceInfo.getDeviceName(), result);
394
+            BTPPrintUtil.printBarCodeWithText(brCode, text, textList, result);
393
         } else {
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
         result.success(code == 0 ? true : false);
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
     // BTP打印机同时打印图标和标签只能调这个,依次printBitMap再printText会导致偶发printText不走。
204
     // BTP打印机同时打印图标和标签只能调这个,依次printBitMap再printText会导致偶发printText不走。
134
     public  static  void PrintBitMapAndText(Bitmap bitmap, String deviceName, ArrayList<String> textList,@NonNull MethodChannel.Result result) {
205
     public  static  void PrintBitMapAndText(Bitmap bitmap, String deviceName, ArrayList<String> textList,@NonNull MethodChannel.Result result) {
135
         int x = 0;
206
         int x = 0;

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

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

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

@@ -132,6 +132,7 @@ SampleTaskItem _$SampleTaskItemFromJson(Map<String, dynamic> json) =>
132
       ewmfilePictureList: (json['ewmfilePictureList'] as List<dynamic>?)
132
       ewmfilePictureList: (json['ewmfilePictureList'] as List<dynamic>?)
133
           ?.map((e) => UrlItem.fromJson(e as Map<String, dynamic>))
133
           ?.map((e) => UrlItem.fromJson(e as Map<String, dynamic>))
134
           .toList(),
134
           .toList(),
135
+      isSelect: json['isSelect'] as bool? ?? false,
135
     );
136
     );
136
 
137
 
137
 Map<String, dynamic> _$SampleTaskItemToJson(SampleTaskItem instance) =>
138
 Map<String, dynamic> _$SampleTaskItemToJson(SampleTaskItem instance) =>
@@ -231,6 +232,7 @@ Map<String, dynamic> _$SampleTaskItemToJson(SampleTaskItem instance) =>
231
       'xzqhCode': const StringConverter().toJson(instance.xzqhCode),
232
       'xzqhCode': const StringConverter().toJson(instance.xzqhCode),
232
       'filePictureList': instance.filePictureList,
233
       'filePictureList': instance.filePictureList,
233
       'ewmfilePictureList': instance.ewmfilePictureList,
234
       'ewmfilePictureList': instance.ewmfilePictureList,
235
+      'isSelect': instance.isSelect,
234
     };
236
     };
235
 
237
 
236
 UrlItem _$UrlItemFromJson(Map<String, dynamic> json) => UrlItem(
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
 class _HomePageState extends BaseState<HomePage> with AutomaticKeepAliveClientMixin {
16
 class _HomePageState extends BaseState<HomePage> with AutomaticKeepAliveClientMixin {
17
   List<String> bannerList = [
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
     'https://gd-hbimg.huaban.com/82e60fd3c61530d52ec1d01f80cfda11526c42e4495cb-6JwN1d_fw658webp',
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
 class PrintPageArgs {
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
   @override
28
   @override
25
   String toString() {
29
   String toString() {
@@ -60,7 +64,13 @@ class _PrintPageState extends BaseLifecycleState<PrintPage> {
60
     super.initState();
64
     super.initState();
61
     serviceList = [
65
     serviceList = [
62
       ServiceModel(name: '搜索', icon: imgBleSearch, onTap: () => startScan()),
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
     deviceList = [];
75
     deviceList = [];
66
     deviceMacList = [];
76
     deviceMacList = [];
@@ -75,6 +85,23 @@ class _PrintPageState extends BaseLifecycleState<PrintPage> {
75
     getLocation();
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
   Future<void> startPrint() async {
106
   Future<void> startPrint() async {
80
 
107
 
@@ -84,7 +111,7 @@ class _PrintPageState extends BaseLifecycleState<PrintPage> {
84
     }
111
     }
85
 
112
 
86
     final codec = await ui.instantiateImageCodec(
113
     final codec = await ui.instantiateImageCodec(
87
-      widget.args.bytes,
114
+      widget.args.bytes!,
88
       targetHeight: 590,  // 640
115
       targetHeight: 590,  // 640
89
       targetWidth: targetWidth, // 560
116
       targetWidth: targetWidth, // 560
90
     );
117
     );
@@ -96,10 +123,10 @@ class _PrintPageState extends BaseLifecycleState<PrintPage> {
96
 
123
 
97
     MyNavigator.showLoading(msg: '打印中...');
124
     MyNavigator.showLoading(msg: '打印中...');
98
     if(PrintService.connectedDeviceList.last.deviceName.contains("BTP")) {
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
     } else {
127
     } else {
101
       await PrintService.startBluetoothPrintBitMap(smallUint8List!);
128
       await PrintService.startBluetoothPrintBitMap(smallUint8List!);
102
-      await PrintService.startBluetoothPrintText(widget.args.textList);
129
+      await PrintService.startBluetoothPrintText(widget.args.textList!);
103
     }
130
     }
104
     MyNavigator.dismiss();
131
     MyNavigator.dismiss();
105
     MyNavigator.showToast('打印成功');
132
     MyNavigator.showToast('打印成功');

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

@@ -13,6 +13,8 @@ class SampleListVM extends BaseVM {
13
   late List<SampleTaskListReq> reqList;
13
   late List<SampleTaskListReq> reqList;
14
   late List<ValueNotifier<DataStatusModel<List<SampleTaskItem>>>> pageStateList;
14
   late List<ValueNotifier<DataStatusModel<List<SampleTaskItem>>>> pageStateList;
15
 
15
 
16
+  ValueNotifier<bool> showPrintBtn = ValueNotifier(false);
17
+
16
   SampleListVM() {
18
   SampleListVM() {
17
     pageStateList = [
19
     pageStateList = [
18
       DataStatusModel<List<SampleTaskItem>>().notifier<DataStatusModel<List<SampleTaskItem>>>(),
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
   final bool currentComplete = false;
42
   final bool currentComplete = false;
36
 
43
 

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

@@ -1,3 +1,4 @@
1
+
1
 import 'package:easy_refresh/easy_refresh.dart';
2
 import 'package:easy_refresh/easy_refresh.dart';
2
 import 'package:flutter/material.dart';
3
 import 'package:flutter/material.dart';
3
 import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
4
 import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
@@ -6,13 +7,16 @@ import 'package:lszlgl/base/base_vm.dart';
6
 import 'package:lszlgl/config/colors.dart';
7
 import 'package:lszlgl/config/colors.dart';
7
 import 'package:lszlgl/model/rsp/sample_task_rsp.dart';
8
 import 'package:lszlgl/model/rsp/sample_task_rsp.dart';
8
 import 'package:lszlgl/network/my_api.dart';
9
 import 'package:lszlgl/network/my_api.dart';
10
+import 'package:lszlgl/page/print/print_page.dart';
9
 import 'package:lszlgl/page/sample_task/sample_list_vm.dart';
11
 import 'package:lszlgl/page/sample_task/sample_list_vm.dart';
10
 import 'package:lszlgl/page/sample_task/sample_task_list_tab_page.dart';
12
 import 'package:lszlgl/page/sample_task/sample_task_list_tab_page.dart';
11
 import 'package:lszlgl/service/dict_service.dart';
13
 import 'package:lszlgl/service/dict_service.dart';
14
+import 'package:lszlgl/service/print_service.dart';
12
 import 'package:lszlgl/utils/date_time_utils.dart';
15
 import 'package:lszlgl/utils/date_time_utils.dart';
13
 import 'package:lszlgl/utils/inject.dart';
16
 import 'package:lszlgl/utils/inject.dart';
14
 import 'package:lszlgl/widget/button.dart';
17
 import 'package:lszlgl/widget/button.dart';
15
 import 'package:lszlgl/widget/page_widget.dart';
18
 import 'package:lszlgl/widget/page_widget.dart';
19
+import 'package:lszlgl/widget/print_checkbox_widget.dart';
16
 
20
 
17
 import '../../main.dart';
21
 import '../../main.dart';
18
 import 'reap_sample_detail/reap_sample_task_page.dart';
22
 import 'reap_sample_detail/reap_sample_task_page.dart';
@@ -36,6 +40,7 @@ class SampleTaskListPage extends StatefulWidget {
36
 class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
40
 class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
37
     with AutomaticKeepAliveClientMixin {
41
     with AutomaticKeepAliveClientMixin {
38
   late SampleListVM vm;
42
   late SampleListVM vm;
43
+  List<num> selectList = [];
39
 
44
 
40
   /// 详情
45
   /// 详情
41
   void startTaskDetail(bool detail, SampleTaskItem data, {num? deliveryStatus}) async {
46
   void startTaskDetail(bool detail, SampleTaskItem data, {num? deliveryStatus}) async {
@@ -43,7 +48,8 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
43
     switch (widget.type) {
48
     switch (widget.type) {
44
       case StepType.reap:
49
       case StepType.reap:
45
         success = await MyRouter.startReapSampleTask(
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
         break;
53
         break;
48
       case StepType.stock:
54
       case StepType.stock:
49
         success = await MyRouter.startStockSampleTask(
55
         success = await MyRouter.startStockSampleTask(
@@ -101,7 +107,12 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
101
   @override
107
   @override
102
   Widget build(BuildContext context) {
108
   Widget build(BuildContext context) {
103
     super.build(context);
109
     super.build(context);
104
-    return buildBody();
110
+    return Stack(
111
+      children: [
112
+        buildBody(),
113
+        buildPrintBtn(),
114
+      ],
115
+    );
105
     //   Container(
116
     //   Container(
106
     //   margin: const EdgeInsets.symmetric(horizontal: 8),
117
     //   margin: const EdgeInsets.symmetric(horizontal: 8),
107
     //   clipBehavior: Clip.hardEdge,
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
   Widget buildBody() {
204
   Widget buildBody() {
118
     return EasyRefresh.builder(
205
     return EasyRefresh.builder(
119
       controller: vm.ctrlList[widget.tabIndex],
206
       controller: vm.ctrlList[widget.tabIndex],
@@ -161,7 +248,6 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
161
           borderRadius: BorderRadius.all(Radius.circular(8)),
248
           borderRadius: BorderRadius.all(Radius.circular(8)),
162
         ),
249
         ),
163
         child: Stack(
250
         child: Stack(
164
-          alignment: Alignment.topRight,
165
           children: [
251
           children: [
166
             Column(
252
             Column(
167
               crossAxisAlignment: CrossAxisAlignment.start,
253
               crossAxisAlignment: CrossAxisAlignment.start,
@@ -177,12 +263,42 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
177
               ],
263
               ],
178
             ),
264
             ),
179
             buildState(item.getDeliveryStatusText()),
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
   Widget buildTop() {
302
   Widget buildTop() {
187
     return Row(
303
     return Row(
188
       children: [
304
       children: [
@@ -208,12 +324,16 @@ class _SampleTaskListPageState extends BaseLifecycleState<SampleTaskListPage>
208
       img = imgQYStateOn;
324
       img = imgQYStateOn;
209
       color = const Color(0xFFDEA70A);
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
     } else {
440
     } else {
321
       button = MyButton(
441
       button = MyButton(
322
         '修改信息',
442
         '修改信息',
323
-        onTap: () => startTaskDetail(false, item,deliveryStatus: item.deliveryStatus),
443
+        onTap: () => startTaskDetail(false, item, deliveryStatus: item.deliveryStatus),
324
         fountSize: 13,
444
         fountSize: 13,
325
         radius: 6,
445
         radius: 6,
326
         alignment: null,
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
 import '../filter/filter_page.dart';
8
 import '../filter/filter_page.dart';
9
 
9
 
10
 enum StepType {
10
 enum StepType {
11
+  /// 收获
11
   reap('收获环节', 1),
12
   reap('收获环节', 1),
13
+  /// 库存
12
   stock('库存环节', 2);
14
   stock('库存环节', 2);
13
 
15
 
14
   const StepType(this.title, this.value);
16
   const StepType(this.title, this.value);
@@ -103,7 +105,11 @@ class _SampleTaskListTabPageState extends BaseLifecycleState<SampleTaskListTabPa
103
       children: [
105
       children: [
104
         myAppBar(
106
         myAppBar(
105
           title: widget.args.type.title,
107
           title: widget.args.type.title,
106
-          actions: [buildFilter()],
108
+          actions: [
109
+            if (widget.args.type == StepType.reap)
110
+              buildMultiplePrint(),
111
+            buildFilter(),
112
+          ],
107
           naviBarColor: Colors.white,
113
           naviBarColor: Colors.white,
108
         ),
114
         ),
109
         buildTab(),
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
   Widget buildFilter() {
131
   Widget buildFilter() {
117
     return GestureDetector(
132
     return GestureDetector(
118
       onTap: showFilter,
133
       onTap: showFilter,
119
       behavior: HitTestBehavior.opaque,
134
       behavior: HitTestBehavior.opaque,
120
       child: Padding(
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
 import 'package:flutter/material.dart';
2
 import 'package:flutter/material.dart';
3
 import 'package:lszlgl/base/base_state.dart';
3
 import 'package:lszlgl/base/base_state.dart';
4
 import 'package:lszlgl/config/app_config.dart';
4
 import 'package:lszlgl/config/app_config.dart';
5
-import 'package:lszlgl/config/colors.dart';
6
 import 'package:lszlgl/network/my_api.dart';
5
 import 'package:lszlgl/network/my_api.dart';
7
 import 'package:lszlgl/service/upgrade_service.dart';
6
 import 'package:lszlgl/service/upgrade_service.dart';
8
 import 'package:lszlgl/widget/button.dart';
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
     if (Platform.isIOS) {
115
     if (Platform.isIOS) {
116
       return false;
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
     if(await canExecAction()) {
175
     if(await canExecAction()) {
176
-      return await BluetoothPlugin.instance.startBluetoothPrintBarCodeWithText(barCode, text);
176
+      return await BluetoothPlugin.instance.startBluetoothPrintBarCodeWithText(barCode, text, textList);
177
     } else {
177
     } else {
178
       return false;
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
 import 'package:flutter/material.dart';
1
 import 'package:flutter/material.dart';
4
 import 'package:lszlgl/main.dart';
2
 import 'package:lszlgl/main.dart';
5
 import 'package:lszlgl/service/upgrade_service.dart';
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
           SizedBox(
100
           SizedBox(
95
             width: double.infinity,
101
             width: double.infinity,
96
             child: Text(
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
           const SizedBox(height: 24),
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
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
16
 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17
 # In Windows, build-name is used as the major, minor, and patch parts
17
 # In Windows, build-name is used as the major, minor, and patch parts
18
 # of the product and file versions while build-number is used as the build suffix.
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
 environment:
21
 environment:
22
   sdk: '>=3.1.5 <4.0.0'
22
   sdk: '>=3.1.5 <4.0.0'