服务端的TigerApi 框架,基于.NET6 2024 版本
Rodney Chen
2024-09-25 2420648a1522c2e1cd8138bb43dd7d46a6561a1a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
using Rhea.Common;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tiger.IBusiness;
using Tiger.IBusiness.MES.WorkAction;
using Tiger.Model;
using Tiger.Model.Entitys.MES.Position;
 
namespace Tiger.Business.MES.WorkAction
{
    public class PackingAction : IPackingAction
    {
        #region Propertys & Variables
        #region 固定写法,工序中的必要信息
        public bool IsFinished { get; set; } = false;
        public IWorkStep CurStep { get; set; }
        public IPosition CurPosition { get; set; }
        public MES_WO_NODE_ACT NodeAct { get; set; }
        public MES_WO_ACTION Setting { get; set; }
        #endregion
        public BAS_PKG_RULE PkgRule { get; set; }
        public BAS_PKG_PROD PkgProd { get; set; }
        public WipPkg CurPkg { get; set; }
        public WipPkgItem CurPkgItem { get; set; }
        public PackingActionOutput CurCmd { get; set; }
        public int PrintTimes = 0;
        public Dictionary<int, BAS_LABEL_TEMP> LabelDic { get; set; }    = new();
        public List<BAS_LABEL_PV> LabelPV { get; set; } = new();
        public int FinishLevel = 0;
        private bool IsManually => CurStep.IsNullOrEmpty();
        #endregion Propertys & Variables
 
        #region Functions
        /// <summary>
        /// 初始化工序行为(正常条码过站)
        /// </summary>
        /// <returns></returns>
        public void Init(IWorkStep curStep, IPosition position, MES_WO_NODE_ACT nodeAct, MES_WO_ACTION setting)
        {
            #region 固定写法,给默认变量赋值
            CurStep = curStep;
            CurPosition = position;
            NodeAct = nodeAct;
            Setting = setting;
            #endregion
 
            //正常条码过站执行包装行为
            PkgRule = Biz.Db.Queryable<BAS_PKG_RULE>().Where(q => q.RULE_CODE == setting.PKG_CODE).IncludesAllFirstLayer().IncludesAllSecondLayer(q => q.Details).First();
 
            //根据行为设置获取多层包装的标签打印模板字典
            var codes = (Setting.OPTION_1 ?? "").JsonToObject<List<WipPkgItem>>();
            foreach (var code in codes)
            {
                var label = code.LABEL_CODE.IsNullOrEmpty() ? null : Biz.Db.Queryable<BAS_LABEL_TEMP>().Where(q => q.LABEL_CODE == code.LABEL_CODE).IncludesAllFirstLayer().First();
                LabelDic.Add(code.PKG_LEVEL, label);
            }
            LabelPV = Biz.Db.Queryable<BAS_LABEL_PV>().ToList();
            //如果工序上下文中没有包装记录则新建一个,有则获取当前的包装记录
            if (CurPosition.Context.ContainsKey("CurPackage") && !CurPosition.Context["CurPackage"].IsNullOrEmpty())
            {
                CurPkg = (CurPosition.Context["CurPackage"] as WipPkg).Clone();
            }
            else
            {
                var max = PkgRule.Details.OrderByDescending(q => q.PKG_LEVEL).First();
                CurPkg = new WipPkg()
                {
                    WorkBatch = CurPosition.WorkBatch.Batch.BATCH_NO,
                    RULE_CODE = PkgRule.RULE_CODE,
                    RULE_NAME = PkgRule.RULE_NAME,
                    ITEM_CODE = CurPosition.WorkBatch.WO.ITEM_CODE,
                    Item = new WipPkgItem()
                    {
                        PKG_CODE = max.PKG_CODE,
                        PKG_NAME = max.PkgType.PKG_NAME,
                        IS_MIN_PKG = max.PkgType.IS_MIN_PKG,
                        PKG_LEVEL = max.PKG_LEVEL,
                        PKG_QTY = max.PKG_QTY,
                        LABEL_CODE = LabelDic[max.PKG_LEVEL]?.LABEL_CODE,
                    }
                };
                WipPkgItem child = null;
                foreach (var dtl in PkgRule.Details.OrderBy(q => q.PKG_LEVEL))
                {
                    if (1 < dtl.PKG_LEVEL && dtl.PKG_LEVEL < max.PKG_LEVEL)
                    {
                        var item = new WipPkgItem()
                        {
                            PKG_CODE = dtl.PKG_CODE,
                            PKG_NAME = dtl.PkgType.PKG_NAME,
                            IS_MIN_PKG = dtl.PkgType.IS_MIN_PKG,
                            PKG_LEVEL = dtl.PKG_LEVEL,
                            PKG_QTY = dtl.PKG_QTY,
                            LABEL_CODE = LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE,
                        };
                        if (!child.IsNullOrEmpty())
                        {
                            item.Items.Add(child);
                        }
                        child = item;
                    }
                }
                if (!child.IsNullOrEmpty())
                {
                    CurPkg.Item.Items.Add(child);
                }
            }
            //获取是否包装完后需要称重
            CurPkg.NeedWeighing = Setting.OPTION_2 == "Y";
            //获取包装规则的称重范围
            PkgProd = Biz.Db.Queryable<BAS_PKG_PROD>().Where(q => q.PKG_RULE_ID == PkgRule.ID && q.ITEM_CODE == CurPosition.WorkBatch.WO.ITEM_CODE).First();
 
            CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("记录包装数据"));
        }
 
        /// <summary>
        /// 初始化工序行为(手动结束包装专用)
        /// </summary>
        /// <returns></returns>
        public void Init(IPosition position)
        {
            #region 固定写法,给默认变量赋值
            CurStep = null;
            CurPosition = position;
            NodeAct = null;
            Setting = null;
            #endregion
            //获取当前的包装记录
            if (CurPosition.Context.ContainsKey("CurPackage") && !CurPosition.Context["CurPackage"].IsNullOrEmpty())
            {
                CurPkg = (CurPosition.Context["CurPackage"] as WipPkg).Clone();
            }
            else
            {
                throw new Exception("找不到包装数据,请重新扫描需要包装的产品");
            }
            //手动结束包装专用,临时执行行为
            PkgRule = Biz.Db.Queryable<BAS_PKG_RULE>().Where(q => q.RULE_CODE == CurPkg.RULE_CODE).IncludesAllFirstLayer().IncludesAllSecondLayer(q => q.Details).First();
 
            //根据行为设置获取多层包装的标签打印模板字典
            LabelDic = CurPosition.Context["CurLabelDic"] as Dictionary<int, BAS_LABEL_TEMP>;
            LabelPV = Biz.Db.Queryable<BAS_LABEL_PV>().ToList();
            //获取包装规则的称重范围
            PkgProd = Biz.Db.Queryable<BAS_PKG_PROD>().Where(q => q.PKG_RULE_ID == PkgRule.ID && q.ITEM_CODE == CurPkg.ITEM_CODE).First();
 
            CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("记录包装数据"));
        }
 
        /// <summary>
        /// 获取行为开始的提示信息
        /// </summary>
        /// <returns></returns>
        public Locale GetBeginMsg()
        {
            var min = PkgRule.Details.OrderBy(q => q.PKG_LEVEL).First();
            //行为设定的OPTION_1是第一层包装的标签模板代码,如果为空则不需要打印
            if (LabelDic[min.PKG_LEVEL].IsNullOrEmpty())
            {
                var msg = new Locale("MES.WorkAction.PackingAction.BeginMsg", min.PKG_LEVEL, min.PkgType.PKG_NAME, CurPosition.CurSN);
                //var msg = new Locale($"已扫描第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签条码[{CurPosition.CurWipSN.SN}]");
                return msg;
            }
            else
            {
                var msg = new Locale("MES.WorkAction.PackingAction.BeginPrint", min.PKG_LEVEL, min.PkgType.PKG_NAME, LabelDic[min.PKG_LEVEL]?.LABEL_CODE, LabelDic[min.PKG_LEVEL].LABEL_NAME);
                //var msg = new Locale($"开始打印第{min.PKG_LEVEL}层包装[{min.PkgType.PKG_NAME}]的标签[{LabelDic[min.PKG_LEVEL]?.LABEL_CODE}: {LabelDic[min.PKG_LEVEL].LABEL_NAME}]");
                return msg;
            }
        }
 
        /// <summary>
        /// 尝试开始执行工序行为
        /// </summary>
        /// <returns></returns>
        public ApiAction<SubmitOutput> TryBegin(SubmitInput input)
        {
            var action = new ApiAction<SubmitOutput>(new SubmitOutput());
            action.LocaleMsg = GetBeginMsg();
 
            var min = PkgRule.Details.OrderBy(q => q.PKG_LEVEL).First();
            if (min.PKG_LEVEL == CurPkg.Item.PKG_LEVEL && CurPkg.NeedWeighing)
            {
                var data = new PackingActionOutput() { PkgInfo = CurPkg };
                data.ExecCode = "Weighing";
                data.PkgLevel = min.PKG_LEVEL;
                CurCmd = data;
                CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("上称称重"));
                action.Data.Data = data;
                action.Data.ShortMsg = new("上称称重", ShortMessage.Types.Success);
                //action.LocaleMsg = new($"请把外包装上称称重");
                action.LocaleMsg = new("MES.WorkAction.PackingAction.PleaseWeighing");
            }
            //根据包装不同层级的标签模板代码,如果为空则不需要打印
            else if (LabelDic[min.PKG_LEVEL].IsNullOrEmpty())
            {
                input.Data = new PackingActionInput()
                {
                    ExecCode = "Scan",
                    IsFinish = true,
                    PkgLevel = min.PKG_LEVEL,
                    PkgSN = CurPosition.CurSN,
                }.ToJson();
                action = Submit(input);
            }
            else
            {
                //设置打印变量值
                LabelDic[min.PKG_LEVEL] = CurPosition.SetLabelVariables(LabelPV, LabelDic[min.PKG_LEVEL], this);
 
                var data = new PackingActionOutput() { PkgInfo = CurPkg };
                data.ExecCode = "Print";
                data.PkgLevel = min.PKG_LEVEL;
                data.PrintLable = LabelDic[min.PKG_LEVEL];
                CurCmd = data;
                PrintTimes++;
                CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("打印标签"));
                action.Data.Data = data;
                action.Data.ShortMsg = new("打印标签", ShortMessage.Types.Normal);
                //action.LocaleMsg = new Locale($"开始第{PrintTimes}次打印第{min.PKG_LEVEL}层包装[{min.PkgType.PKG_NAME}]的标签[{LabelDic[min.PKG_LEVEL]?.LABEL_CODE}: {LabelDic[min.PKG_LEVEL].LABEL_NAME}]");
                action.LocaleMsg = new Locale("MES.WorkAction.PackingAction.BeginPrint", PrintTimes, min.PKG_LEVEL, min.PkgType.PKG_NAME, LabelDic[min.PKG_LEVEL]?.LABEL_CODE, LabelDic[min.PKG_LEVEL].LABEL_NAME);
            }
 
            //如果返回成功则认为当前行为可以开始执行,否则返回失败
            action.IsSuccessed = true;
            return action;
        }
 
        /// <summary>
        /// 工序行为提交数据
        /// </summary>
        /// <returns></returns>
        public ApiAction<SubmitOutput> Submit(SubmitInput input)
        {
            var action = new ApiAction<SubmitOutput>(new SubmitOutput());
 
            var pInput = input?.Data?.JsonToObject<PackingActionInput>();
            switch (pInput?.ExecCode)
            {
                //Scan:扫码,扫描当前包装层级的条码
                case "Scan":
                    if (CurCmd.IsNullOrEmpty() || CurCmd.ExecCode == "Scan" || (CurCmd.ExecCode == "Print" && CurCmd.PkgLevel == pInput.PkgLevel))
                    {
                        //客户端扫描失败
                        if (!pInput.IsFinish || pInput.PkgSN.IsNullOrEmpty())
                        {
                            var dtl = PkgRule.Details.First(q => q.PKG_LEVEL == pInput.PkgLevel);
                            CurStep?.SetStatusMessage(StepStatus.Error, Biz.L("扫描错误"));
                            action.Data.ShortMsg = new("扫描错误", ShortMessage.Types.Error);
                            action.IsSuccessed = false;
                            //action.LocaleMsg = new($"条码扫描失败,请重新扫描第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签条码");
                            action.LocaleMsg = new("MES.WorkAction.PackingAction.ScanFail", dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME);
                            return action;
                        }
                        //验证当前包装条码是否已经被扫描过
                        if (GetPackageList(CurPkg.Item).Any(q => q.SN == pInput.PkgSN))
                        {
                            var dtl = PkgRule.Details.First(q => q.PKG_LEVEL == pInput.PkgLevel);
                            CurStep?.SetStatusMessage(StepStatus.Error, Biz.L("扫描错误"));
                            action.Data.ShortMsg = new("扫描错误", ShortMessage.Types.Error);
                            action.IsSuccessed = false;
                            //action.LocaleMsg = new($"条码[{pInput.PkgSN}]无需重复扫描,请扫描第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签条码");
                            action.LocaleMsg = new("MES.WorkAction.PackingAction.ScanRepeat", pInput.PkgSN, dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME);
                            return action;
                        }
                        //客户端扫描成功
                        CurCmd = null;
                        PrintTimes = 0;
                        action = SavePkgData(input, action);
                        if (action.IsSuccessed)
                        {
                            CurStep?.SetStatusMessage(StepStatus.Success, Biz.L("扫描成功"));
                            action.Data.ShortMsg = new("扫描成功", ShortMessage.Types.Success);
                        }
                    }
                    break;
                //Print:打印,打印当前包装层级的标签
                case "Print":
                    if (CurCmd.ExecCode == "Print")
                    {
                        var dtl = PkgRule.Details.First(q => q.PKG_LEVEL == pInput.PkgLevel);
                        //客户端完成打印
                        if (pInput.IsFinish)
                        {
                            CurCmd = null;
                            PrintTimes = 0;
                            var data = new PackingActionOutput() { PkgInfo = CurPkg };
                            data.ExecCode = "Scan";
                            data.PkgLevel = dtl.PKG_LEVEL;
                            CurCmd = data;
                            CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("扫描标签"));
                            action.Data.Data = data;
                            action.Data.ShortMsg = new("扫描标签", ShortMessage.Types.Normal);
                            //action.LocaleMsg = new($"请扫描第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签条码");
                            action.LocaleMsg = new("MES.WorkAction.PackingAction.PleaseScanLabel", dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME);
                        } 
                        //客户端打印失败
                        else
                        {
                            //如果打印失败则尝试三次重新打印,如果都失败则重置工序
                            if (PrintTimes < 3 && !CurCmd.IsNullOrEmpty())
                            {
                                PrintTimes++;
                                CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("重新打印"));
                                action.Data.Data = CurCmd;
                                action.Data.ShortMsg = new("重新打印", ShortMessage.Types.Normal);
                                //action.LocaleMsg = new Locale($"开始{PrintTimes}次打印第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签[{LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE}: {LabelDic[dtl.PKG_LEVEL].LABEL_NAME}]");
                                action.LocaleMsg = new Locale("MES.WorkAction.PackingAction.BeginPrint", PrintTimes, dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME, LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE, LabelDic[dtl.PKG_LEVEL].LABEL_NAME);
                            }
                            else
                            {
                                CurCmd = null;
                                PrintTimes = 0;
                                CurStep?.SetStatusMessage(StepStatus.Error, Biz.L("打印失败"));
                                action.Data.ShortMsg = new("打印失败", ShortMessage.Types.Failed);
                                action.IsSuccessed = false;
                                //action.LocaleMsg = new($"尝试第{PrintTimes}次打印第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签[{LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE}: {LabelDic[dtl.PKG_LEVEL].LABEL_NAME}]失败,工序已重置,请重新扫描进站产品条码");
                                action.LocaleMsg = new("MES.WorkAction.PackingAction.PrintFail3Times", PrintTimes, dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME, LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE, LabelDic[dtl.PKG_LEVEL].LABEL_NAME);
                                CurPosition.ResetNode();
                            }
                        }
                    }
                    break;
                // Weighing:称重,完成包装后对整个包装成称重
                case "Weighing":
                    if (CurCmd.ExecCode == "Weighing")
                    {
                        if (!pInput.WeightInfo.IsNullOrEmpty() && pInput.WeightInfo.Weight > 0)
                        {
                            //验证重量数据是否符合设置好的重量范围
                            if (!PkgProd.IsNullOrEmpty() && ((pInput.WeightInfo.Weight < PkgProd.MIN_WEIGHT && !IsManually) || PkgProd.MAX_WEIGHT < pInput.WeightInfo.Weight))
                            {
                                action.IsSuccessed = false;
                                CurStep?.SetStatusMessage(StepStatus.Error, Biz.L("重量超限"));
                                action.Data.Data = CurCmd;
                                action.Data.ShortMsg = new("重量超限", ShortMessage.Types.Failed);
                                //action.LocaleMsg = new($"外包装重量[{0}]超出产品[{1}]在包装规则[{2}]中的预设范围[{3} - {4}],请处理后重新上称称重");
                                action.LocaleMsg = new("MES.WorkAction.PackingAction.PackageOverWeight", pInput.WeightInfo.Weight + pInput.WeightInfo.Unit.IsNullOrEmpty("", " " + pInput.WeightInfo.Unit), CurPosition.WorkBatch.WO.ITEM_CODE, PkgRule.RULE_NAME, PkgProd.MIN_WEIGHT + PkgProd.MIN_UNIT.IsNullOrEmpty("", " " + PkgProd.MIN_UNIT), PkgProd.MAX_WEIGHT + PkgProd.MAX_UNIT.IsNullOrEmpty("", " " + PkgProd.MAX_UNIT));
                                return action;
                            }
 
                            CurCmd = null;
                            PrintTimes = 0;
                            CurPkg.WeightInfo.Weight = pInput.WeightInfo.Weight;
                            CurPkg.WeightInfo.Unit = pInput.WeightInfo.Unit;
                            CurPkg.NeedWeighing = false;
 
                            //称重成功,继续行为
                            var dtl = PkgRule.Details.FirstOrDefault(q => q.PKG_LEVEL == FinishLevel + 1);
                            //最外层包装已处理完成则直接结束行为
                            if (CurPkg.Item.PKG_LEVEL == FinishLevel)
                            {
                                action = End(input);
                            }
                            //最外层包装未打印扫描则继续
                            else
                            {
                                //如果为空则不需要打印
                                if (LabelDic[dtl.PKG_LEVEL].IsNullOrEmpty())
                                {
                                    var data = new PackingActionOutput() { PkgInfo = CurPkg };
                                    data.ExecCode = "Scan";
                                    data.PkgLevel = dtl.PKG_LEVEL;
                                    CurCmd = data;
                                    CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("扫描标签"));
                                    action.Data.Data = data;
                                    action.Data.ShortMsg = new("扫描标签", ShortMessage.Types.Normal);
                                    //action.LocaleMsg = new($"请扫描第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签条码");
                                    action.LocaleMsg = new("MES.WorkAction.PackingAction.PleaseScanLabel", dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME);
                                }
                                else
                                {
                                    //设置打印变量值
                                    LabelDic[dtl.PKG_LEVEL] = CurPosition.SetLabelVariables(LabelPV, LabelDic[dtl.PKG_LEVEL], this);
    
                                    var data = new PackingActionOutput() { PkgInfo = CurPkg };
                                    data.ExecCode = "Print";
                                    data.PkgLevel = dtl.PKG_LEVEL;
                                    data.PrintLable = LabelDic[dtl.PKG_LEVEL];
                                    CurCmd = data;
                                    PrintTimes++;
                                    CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("打印标签"));
                                    action.Data.Data = data;
                                    action.Data.ShortMsg = new("打印标签", ShortMessage.Types.Normal);
                                    //action.LocaleMsg = new Locale($"开始第{PrintTimes}次打印第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签[{LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE}: {LabelDic[dtl.PKG_LEVEL].LABEL_NAME}]");
                                    action.LocaleMsg = new Locale("MES.WorkAction.PackingAction.BeginPrint", PrintTimes, dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME, LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE, LabelDic[dtl.PKG_LEVEL].LABEL_NAME);
                                }
                            }
                        }
                        else
                        {
                            action.IsSuccessed = false;
                            CurStep?.SetStatusMessage(StepStatus.Error, Biz.L("称重失败"));
                            action.Data.Data = CurCmd;
                            action.Data.ShortMsg = new("称重失败", ShortMessage.Types.Failed);
                            //action.LocaleMsg = new($"外包装称重数据异常,请重新上称称重");
                            action.LocaleMsg = new("MES.WorkAction.PackingAction.PleaseWeighingAgain");
                            return action;
                        }
                    }
                    break;
                // Complete:完成,完成全部包装后结束行为
                case "Complete":
                    if (CurCmd.ExecCode == "Complete")
                    {
                        CurCmd = null;
                        PrintTimes = 0;
                        //打印后称重
                        if (CurPkg.NeedWeighing)
                        {
                            var data = new PackingActionOutput() { PkgInfo = CurPkg };
                            data.ExecCode = "Weighing";
                            data.PkgLevel = CurPkgItem.PKG_LEVEL;
                            CurCmd = data;
                            CurStep?.SetStatusMessage(StepStatus.Success, Biz.L("包装成功"));
                            action.Data.Data = data;
                            action.Data.ShortMsg = new("包装成功", ShortMessage.Types.Success);
                            //action.LocaleMsg = new($"请把包装[{CurPkgItem.Package.SN}]上称称重");
                            action.LocaleMsg = new("MES.WorkAction.PackingAction.PleaseWeighing", CurPkgItem.Package.SN);
                        }
                        else
                        {
                            action = End(input);
                        }
                    }
                    break;
                // 手动结束包装,保存暂存的包装数据
                case null:
                    {
                        CurCmd = null;
                        PrintTimes = 0;
                        FinishLevel = 1;
                        WipPkgItem curItem = CurPkg.Item;
                        while (curItem.PKG_LEVEL > 2)
                        {
                            var next = curItem.Items.FirstOrDefault(q => !q.IsFinished);
                            curItem = next;
                        }
                        CurPkgItem = curItem;
 
                        //手动结束包装默认从第二层包装开始验证
                        var dtl = PkgRule.Details.First(q => q.PKG_LEVEL == 2);
                        if (dtl.PKG_LEVEL == CurPkg.Item.PKG_LEVEL && CurPkg.NeedWeighing)
                        {
                            var data = new PackingActionOutput() { PkgInfo = CurPkg };
                            data.ExecCode = "Weighing";
                            data.PkgLevel = dtl.PKG_LEVEL;
                            CurCmd = data;
                            CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("上称称重"));
                            action.Data.Data = data;
                            action.Data.ShortMsg = new("上称称重", ShortMessage.Types.Success);
                            //action.LocaleMsg = new($"请把外包装上称称重");
                            action.LocaleMsg = new("MES.WorkAction.PackingAction.PleaseWeighing");
                        }
                        //根据包装不同层级的标签模板代码,如果为空则不需要打印
                        else if (LabelDic[dtl.PKG_LEVEL].IsNullOrEmpty())
                        {
                            var data = new PackingActionOutput() { PkgInfo = CurPkg };
                            data.ExecCode = "Scan";
                            data.PkgLevel = dtl.PKG_LEVEL;
                            CurCmd = data;
                            CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("扫描标签"));
                            action.Data.Data = data;
                            action.Data.ShortMsg = new("扫描标签", ShortMessage.Types.Normal);
                            //action.LocaleMsg = new($"请扫描第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签条码");
                            action.LocaleMsg = new("MES.WorkAction.PackingAction.PleaseScanLabel", dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME);
                        }
                        else
                        {
                            //设置打印变量值
                            LabelDic[dtl.PKG_LEVEL] = CurPosition.SetLabelVariables(LabelPV, LabelDic[dtl.PKG_LEVEL], this);
 
                            var data = new PackingActionOutput() { PkgInfo = CurPkg };
                            data.ExecCode = "Print";
                            data.PkgLevel = dtl.PKG_LEVEL;
                            data.PrintLable = LabelDic[dtl.PKG_LEVEL];
                            CurCmd = data;
                            PrintTimes++;
                            CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("打印标签"));
                            action.Data.Data = data;
                            action.Data.ShortMsg = new("打印标签", ShortMessage.Types.Normal);
                            //action.LocaleMsg = new Locale($"开始第{PrintTimes}次打印第{min.PKG_LEVEL}层包装[{min.PkgType.PKG_NAME}]的标签[{LabelDic[min.PKG_LEVEL]?.LABEL_CODE}: {LabelDic[min.PKG_LEVEL].LABEL_NAME}]");
                            action.LocaleMsg = new Locale("MES.WorkAction.PackingAction.BeginPrint", PrintTimes, dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME, LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE, LabelDic[dtl.PKG_LEVEL].LABEL_NAME);
                        }
                    }
                    break;
                default:
                    break;
            }
 
            //如果行为设置为出错需要重置工序操作
            if (!action.IsSuccessed && NodeAct?.NEED_RESET == "Y")
            {
                CurPosition.ResetNode();
            }
            return action;
        }
 
        //保存包装信息
        public ApiAction<SubmitOutput> SavePkgData(SubmitInput input, ApiAction<SubmitOutput> action)
        {
            var pInput = input.Data?.JsonToObject<PackingActionInput>();
            try
            {
                //正在处理的包装层级明细
                var dtl = PkgRule.Details.First(q => q.PKG_LEVEL == FinishLevel + 1);
 
                //没有保存过任何包装层级的数据,则先处理最小包装数据
                if (FinishLevel == 0)
                {
                    CurPkgItem = new WipPkgItem()
                    {
                        PKG_CODE = dtl.PKG_CODE,
                        PKG_NAME = dtl.PkgType.PKG_NAME,
                        IS_MIN_PKG = dtl.PkgType.IS_MIN_PKG,
                        PKG_LEVEL = dtl.PKG_LEVEL,
                        PKG_QTY = dtl.PKG_QTY,
                        LABEL_CODE = LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE,
                        IsFinished = true,
                    };
 
                    CurPkgItem.Package = Biz.Db.Queryable<MES_WIP_PKG>().Where(q => q.SN == pInput.PkgSN && q.AUTH_ORG == CurPosition.WorkBatch.WO.AUTH_ORG).First() ?? new()
                    {
                        AUTH_ORG = CurPosition.WorkBatch.WO.AUTH_ORG,
                        AUTH_PROD = CurPosition.CurLine.LINE_CODE,
                        SN = pInput.PkgSN,
                    };
                    CurPkgItem.Package.WIP_ID = CurPosition.CurWipSNs.Count == 1 ? CurPosition.CurWipSNs.First().ID : null;
                    CurPkgItem.Package.PKG_TYPE = dtl.PkgType.PKG_NAME;
                    CurPkgItem.Package.ITEM_CODE = CurPosition.CurWipSNs.First().ITEM_CODE;
                    CurPkgItem.Package.QTY = CurPosition.CurWipSNs.First().QTY;
                    CurPkgItem.Package.UNIT = dtl.PkgType.PKG_NAME;
                    CurPkgItem.Package.WORK_ORDER = CurPosition.CurWipSNs.First().WORK_ORDER;
                    CurPkgItem.Package.BATCH_NO = CurPosition.CurWipSNs.First().BATCH_NO;
                    CurPkgItem.Package.ROT_CODE = CurPosition.CurWipSNs.First().ROT_CODE;
                    CurPkgItem.Package.NODE_ID = CurPosition.CurWipSNs.First().NODE_ID;
                    CurPkgItem.Package.NODE_NAME = CurPosition.CurWipSNs.First().NODE_NAME;
                    CurPkgItem.Package.FTY_CODE = CurPosition.CurWipSNs.First().FTY_CODE;
                    CurPkgItem.Package.WS_CODE = CurPosition.CurWipSNs.First().WS_CODE;
                    CurPkgItem.Package.LINE_CODE = CurPosition.CurWipSNs.First().LINE_CODE;
                    CurPkgItem.Package.POST_CODE = CurPosition.CurWipSNs.First().POST_CODE;
                    CurPkgItem.Package.OPER_CODE = CurPosition.CurWipSNs.First().OPER_CODE;
                    CurPkgItem.Package.SEGMENT = CurPosition.CurWipSNs.First().SEGMENT;
                    FinishLevel++;
                    //完成包装的层级小于最外层包装层级
                    if (FinishLevel < PkgRule.Details.Max(q => q.PKG_LEVEL))
                    {
                        //当前处理的包装层级已经处理完,继续往上保存
                        action = SavePkgData(input, action);
                    }
                    //最外层包装已经完成包装,保存包装数据到数据库
                    else
                    {
                        CurPkg.Item = CurPkgItem;
                        action = CompletePkg();
                    }
                }
                //处理其他包装层级数据
                else 
                {
                    //客户端提交的包装层级等于当前处理的包装层级
                    if (pInput.PkgLevel == dtl.PKG_LEVEL)
                    {
                        CurPkgItem.IsFinished = true;
                        CurPkgItem.Package = IsManually ? new()
                        {
                            AUTH_ORG = CurPosition.WorkBatch.WO.AUTH_ORG,
                            AUTH_PROD = CurPosition.CurLine.LINE_CODE,
                            SN = pInput.PkgSN,
                            PKG_TYPE = dtl.PkgType.PKG_NAME,
                            ITEM_CODE = CurPkgItem.Items.First().Package.ITEM_CODE,
                            QTY = CurPkgItem.Items.Sum(q => q.Package.QTY),
                            UNIT = dtl.PkgType.PKG_NAME,
                            WORK_ORDER = CurPkgItem.Items.First().Package.WORK_ORDER,
                            BATCH_NO = CurPkgItem.Items.First().Package.BATCH_NO,
                            ROT_CODE = CurPkgItem.Items.First().Package.ROT_CODE,
                            NODE_ID = CurPkgItem.Items.First().Package.NODE_ID,
                            NODE_NAME = CurPkgItem.Items.First().Package.NODE_NAME,
                            FTY_CODE = CurPkgItem.Items.First().Package.FTY_CODE,
                            WS_CODE = CurPkgItem.Items.First().Package.WS_CODE,
                            LINE_CODE = CurPkgItem.Items.First().Package.LINE_CODE,
                            POST_CODE = CurPkgItem.Items.First().Package.POST_CODE,
                            OPER_CODE = CurPkgItem.Items.First().Package.OPER_CODE,
                            SEGMENT = CurPkgItem.Items.First().Package.SEGMENT,
                        } : new()
                        {
                            AUTH_ORG = CurPosition.WorkBatch.WO.AUTH_ORG,
                            AUTH_PROD = CurPosition.CurLine.LINE_CODE,
                            SN = pInput.PkgSN,
                            PKG_TYPE = dtl.PkgType.PKG_NAME,
                            ITEM_CODE = CurPosition.CurWipSNs.First().ITEM_CODE,
                            QTY = CurPkgItem.Items.Sum(q => q.Package.QTY),
                            UNIT = dtl.PkgType.PKG_NAME,
                            WORK_ORDER = CurPosition.CurWipSNs.First().WORK_ORDER,
                            BATCH_NO = CurPosition.CurWipSNs.First().BATCH_NO,
                            ROT_CODE = CurPosition.CurWipSNs.First().ROT_CODE,
                            NODE_ID = CurPosition.CurWipSNs.First().NODE_ID,
                            NODE_NAME = CurPosition.CurWipSNs.First().NODE_NAME,
                            FTY_CODE = CurPosition.CurWipSNs.First().FTY_CODE,
                            WS_CODE = CurPosition.CurWipSNs.First().WS_CODE,
                            LINE_CODE = CurPosition.CurWipSNs.First().LINE_CODE,
                            POST_CODE = CurPosition.CurWipSNs.First().POST_CODE,
                            OPER_CODE = CurPosition.CurWipSNs.First().OPER_CODE,
                            SEGMENT = CurPosition.CurWipSNs.First().SEGMENT,
                        };
                        FinishLevel++;
                        //完成包装的层级小于最外层包装层级
                        if (FinishLevel < PkgRule.Details.Max(q => q.PKG_LEVEL))
                        {
                            //当前处理的包装层级已经处理完,继续往上保存
                            action = SavePkgData(input, action);
                        }
                        //最外层包装已经完成包装,保存包装数据到数据库
                        else
                        {
                            action = CompletePkg();
                        }
                    }
                    //当前处理的包装层级已经处理完,继续往上保存
                    else if (pInput.PkgLevel == FinishLevel)
                    {
                        //获取当前的包装明细的上一层包装对象
                        WipPkgItem curItem = CurPkg.Item;
                        while (curItem.PKG_LEVEL > dtl.PKG_LEVEL)
                        {
                            var next = curItem.Items.FirstOrDefault(q => !q.IsFinished);
                            if (next.IsNullOrEmpty())
                            {
                                var nextDtl = PkgRule.Details.First(q => q.PKG_LEVEL == curItem.PKG_LEVEL - 1);
                                next = new WipPkgItem()
                                {
                                    PKG_CODE = nextDtl.PKG_CODE,
                                    PKG_NAME = nextDtl.PkgType.PKG_NAME,
                                    IS_MIN_PKG = nextDtl.PkgType.IS_MIN_PKG,
                                    PKG_LEVEL = nextDtl.PKG_LEVEL,
                                    PKG_QTY = nextDtl.PKG_QTY,
                                    LABEL_CODE = LabelDic[nextDtl.PKG_LEVEL]?.LABEL_CODE,
                                };
                                curItem.Items.Add(next);
                            }
                            curItem = next;
                        }
                        //添加当前的包装明细到上一层包装的明细列表
                        if (!curItem.Items.Contains(CurPkgItem))
                        {
                            curItem.Items.Add(CurPkgItem);
                        }
                        CurPkgItem = curItem;
 
                        //添加明细后判断当前包装层级的明细数量是否等于包装数量,若相等则标记当前包装层级为完成并尝试打印标签
                        if (CurPkgItem.Items.Count(q => q.IsFinished) == CurPkgItem.PKG_QTY || IsManually)
                        {
                            //打印前称重:如果当前的包装明细的上一层包装对象是最外层包装且需要称重时,先称重,合格后在发印或者扫描最外层包装标签
                            if (CurPkgItem.PKG_LEVEL == CurPkg.Item.PKG_LEVEL && CurPkg.NeedWeighing)
                            {
                                var data = new PackingActionOutput() { PkgInfo = CurPkg };
                                data.ExecCode = "Weighing";
                                data.PkgLevel = CurPkgItem.PKG_LEVEL;
                                CurCmd = data;
                                CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("上称称重"));
                                action.Data.Data = data;
                                action.Data.ShortMsg = new("上称称重", ShortMessage.Types.Success);
                                //action.LocaleMsg = new($"请把外包装上称称重");
                                action.LocaleMsg = new("MES.WorkAction.PackingAction.PleaseWeighing");
                            } 
                            else
                            {
                                //如果为空则不需要打印
                                if (LabelDic[dtl.PKG_LEVEL].IsNullOrEmpty())
                                {
                                    var data = new PackingActionOutput() { PkgInfo = CurPkg };
                                    data.ExecCode = "Scan";
                                    data.PkgLevel = dtl.PKG_LEVEL;
                                    CurCmd = data;
                                    CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("扫描标签"));
                                    action.Data.Data = data;
                                    action.Data.ShortMsg = new("扫描标签", ShortMessage.Types.Normal);
                                    //action.LocaleMsg = new($"请扫描第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签条码");
                                    action.LocaleMsg = new("MES.WorkAction.PackingAction.PleaseScanLabel", dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME);
                                }
                                else
                                {
                                    //设置打印变量值
                                    LabelDic[dtl.PKG_LEVEL] = CurPosition.SetLabelVariables(LabelPV, LabelDic[dtl.PKG_LEVEL], this);
    
                                    var data = new PackingActionOutput() { PkgInfo = CurPkg };
                                    data.ExecCode = "Print";
                                    data.PkgLevel = dtl.PKG_LEVEL;
                                    data.PrintLable = LabelDic[dtl.PKG_LEVEL];
                                    CurCmd = data;
                                    PrintTimes++;
                                    CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("打印标签"));
                                    action.Data.Data = data;
                                    action.Data.ShortMsg = new("打印标签", ShortMessage.Types.Normal);
                                    //action.LocaleMsg = new Locale($"开始第{PrintTimes}次打印第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签[{LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE}: {LabelDic[dtl.PKG_LEVEL].LABEL_NAME}]");
                                    action.LocaleMsg = new Locale("MES.WorkAction.PackingAction.BeginPrint", PrintTimes, dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME, LabelDic[dtl.PKG_LEVEL]?.LABEL_CODE, LabelDic[dtl.PKG_LEVEL].LABEL_NAME);                
                                }
                            }
                        }
                        //当前包装层级的明细数量未达到包装数量,则完成本次扫描,等待下个产品进站
                        else
                        {
                            action = End(input);
                        }
                    }
                    //数据异常
                    else
                    {
                        CurStep?.SetStatusMessage(StepStatus.Error, Biz.L("包装错误"));
                        action.Data.ShortMsg = new("包装错误", ShortMessage.Types.Error);
                        var pdtl = PkgRule.Details.First(q => q.PKG_LEVEL == pInput.PkgLevel);
                        action.IsSuccessed = false;
                        //action.LocaleMsg = new($"客户端提交的包装层级[{pdtl.PKG_LEVEL}]({pdtl.PkgType.PKG_NAME})数据不是正在处理的包装层级[{dtl.PKG_LEVEL}]({dtl.PkgType.PKG_NAME}),工序已重置,请重新扫描进站产品条码");
                        action.LocaleMsg = new("MES.WorkAction.PackingAction.SaveLevelNotMatchException", pdtl.PKG_LEVEL, pdtl.PkgType.PKG_NAME, dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME);
                        CurPosition.ResetNode();
                    }
                }
            }
            catch (System.Exception ex)
            {
                CurStep?.SetStatusMessage(StepStatus.Error, Biz.L("包装异常"));
                action.Data.ShortMsg = new("包装异常", ShortMessage.Types.Exception);
                var dtl = PkgRule.Details.First(q => q.PKG_LEVEL == pInput.PkgLevel);
                action.CatchExceptionWithLog(ex, $"包装行为:扫描第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签条码[{input.SN}]后保存数据失败");
                action.IsSuccessed = false;
                //action.LocaleMsg = new($"扫描第{dtl.PKG_LEVEL}层包装[{dtl.PkgType.PKG_NAME}]的标签条码[{input.SN}]后保存数据失败,工序已重置,请重新扫描进站产品条码");
                action.LocaleMsg = new("MES.WorkAction.PackingAction.SavePkgDataException", dtl.PKG_LEVEL, dtl.PkgType.PKG_NAME, input.SN);
                CurPosition.ResetNode();
            }
            return action;
        }
 
        private List<MES_WIP_PKG> GetPackageList(WipPkgItem parent)
        {
            List<MES_WIP_PKG> list = new();
            if (!parent.Package.IsNullOrEmpty())
            {
                list.Add(parent.Package);
            }
            foreach (var item in parent.Items)
            {
                item.Package.PARENT_SN = parent.Package?.SN;
                list.AddRange(GetPackageList(item));
            }
            return list;
        }
 
        public List<MES_WIP_PKG> GetMinPackageList(WipPkgItem parent)
        {
            List<MES_WIP_PKG> list = new();
            if (parent.Items.Any())
            {
                foreach (var item in parent.Items)
                {
                    item.Package.PARENT_SN = parent.Package?.SN;
                    list.AddRange(GetMinPackageList(item));
                }
            } 
            else
            {
                if (!parent.Package.IsNullOrEmpty())
                {
                    list.Add(parent.Package);
                }
            }
            return list;
        }
 
        public ApiAction<SubmitOutput> CompletePkg()
        {
            var action = new ApiAction<SubmitOutput>(new SubmitOutput());
 
            var data = new PackingActionOutput() { PkgInfo = CurPkg };
            data.ExecCode = "Complete";
            data.PkgLevel = CurPkg.Item.PKG_LEVEL;
            CurCmd = data;
            CurStep?.SetStatusMessage(StepStatus.Normal, Biz.L("保存包装数据"));
            action.Data.Data = data;
            action.Data.ShortMsg = new("保存包装数据", ShortMessage.Types.Normal);
            //action.LocaleMsg = new($"第{CurPkg.Item.PKG_LEVEL}层包装[{CurPkg.Item.PKG_NAME}]已经全部完成,保存包装数据");
            action.LocaleMsg = new("MES.WorkAction.PackingAction.PackageComplete", CurPkg.Item.PKG_LEVEL, CurPkg.Item.PKG_NAME);
 
            //手动结束包装则标记行为完成
            //if (IsManually)
            //{
            //    IsFinished = true;
            //}
 
            return action;
        }
 
        /// <summary>
        /// 结束执行工序行为
        /// </summary>
        /// <returns></returns>
        public ApiAction<SubmitOutput> End(SubmitInput input)
        {
            var action = new ApiAction<SubmitOutput>(new SubmitOutput());
 
            //记录外包装的称重数据
            if (CurPkg.IsFinished)
            {
                CurPkg.Item.Package.WEIGHT = CurPkg.WeightInfo.Weight;
                CurPkg.Item.Package.WEIGHT_UNIT = CurPkg.WeightInfo.Unit;
            }
            
            //不是手动结束包装则保存行为操作记录
            if (!IsManually)
            {
                //记录行为操作记录
                var wipActs = new List<MES_WIP_ACT>();
                foreach (var wipSn in CurPosition.CurWipSNs)
                {
                    var wipAct = new MES_WIP_ACT()
                    {
                        AUTH_ORG = CurPosition.WorkBatch.WO.AUTH_ORG,
                        AUTH_PROD = CurPosition.CurLine.LINE_CODE,
                        WIP_ID = wipSn.ID,
                        HIS_ID = CurPosition.CurWipSNHiss.First(q => q.SN == wipSn.SN).ID,
                        SN = wipSn.SN,
                        STATUS = wipSn.STATUS,
                        ITEM_CODE = wipSn.ITEM_CODE,
                        WORK_ORDER = wipSn.WORK_ORDER,
                        BATCH_NO = wipSn.BATCH_NO,
                        ROT_CODE = wipSn.ROT_CODE,
                        NODE_ID = wipSn.NODE_ID,
                        NODE_NAME = wipSn.NODE_NAME,
                        ACT_ID = NodeAct.ID,
                        ACT_NAME = NodeAct.ACT_NAME,
                        FTY_CODE = wipSn.FTY_CODE,
                        WS_CODE = wipSn.WS_CODE,
                        LINE_CODE = wipSn.LINE_CODE,
                        POST_CODE = wipSn.POST_CODE,
                        OPER_CODE = wipSn.OPER_CODE,
                        SEGMENT = wipSn.SEGMENT,
                        FLOW_SN = wipSn.FLOW_SN,
                        TRAY_SN = wipSn.TRAY_SN,
                        INNER_SN = wipSn.INNER_SN,
                        CARTON_SN = wipSn.CARTON_SN,
                        PALLET_SN = wipSn.PALLET_SN,
                        OPERATION_TIME = DateTime.Now,
                        SFTS_CODE = wipSn.SFTS_CODE,
                        SFT_CODE = wipSn.SFT_CODE,
                        PRD_CODE = wipSn.PRD_CODE,
                        ACT_TYPE = NodeAct.ACT_TYPE,
                        ACT_SN = wipSn.SN,
                        ACT_RESULT = "Y",
                        ELAPSED_TIME = CurStep.GetElapsedTime().TotalMilliseconds.ToInt64(),
                        TRACE_INFO = $"产品条码[{string.Join(",", CurPosition.CurSN)}]包装完成",
                    };
                    wipActs.Add(wipAct);
                }
 
                //创建变量克隆对象用于传入DBSubmitAction中保存当前需要暂存的数据值
                var _wipActs = wipActs.Clone();
                var _pkgList = CurPkg.IsFinished ? GetPackageList(CurPkg.Item) : new();
                //保存数据
                CurStep.DBSubmitAction = () =>
                {
                    var db = CurPosition.GetCommitDB();
                    if (_wipActs.Any())
                    {
                        db.Storageable(_wipActs, CurPosition.UserCode).ExecuteCommand();
                    }
                    if (_pkgList.Any())
                    {
                        db.Storageable(_pkgList, CurPosition.UserCode).ExecuteCommand();
                        foreach (var pkg in _pkgList)
                        {
                            //包装信息保存到在制品信息表
                            db.Updateable<MES_WIP_DATA>()
                                .SetColumns(q => q.TRAY_SN == CurPkg.Item.Package.SN)
                                .SetColumns(q => q.INNER_SN == q.CARTON_SN)
                                .SetColumns(q => q.CARTON_SN == CurPkg.Item.Package.SN)
                                .Where(q => q.WORK_ORDER == pkg.WORK_ORDER && q.SN == pkg.SN)
                                .ExecuteCommand();
                            //包装信息保存到工单条码明细表
                            db.Updateable<BIZ_MES_WO_SN>()
                                .SetColumns(q => q.TRAY_SN == CurPkg.Item.Package.SN)
                                .SetColumns(q => q.OUTER_SN == CurPkg.Item.Package.SN)
                                .Where(q => q.WORK_ORDER == pkg.WORK_ORDER && q.SN == pkg.SN)
                                .ExecuteCommand();
                        }
                    }
                };
            }
            else
            {
                var _pkgList = CurPkg.IsFinished ? GetPackageList(CurPkg.Item) : new();
                //保存数据
                var db = Biz.Db;
                var dbTran = db.UseTran(() =>
                {
                    if (_pkgList.Any())
                    {
                        db.Storageable(_pkgList, CurPosition.UserCode).ExecuteCommand();
                        foreach (var pkg in _pkgList)
                        {
                            //包装信息保存到在制品信息表
                            db.Updateable<MES_WIP_DATA>()
                                .SetColumns(q => q.TRAY_SN == CurPkg.Item.Package.SN)
                                .SetColumns(q => q.INNER_SN == q.CARTON_SN)
                                .SetColumns(q => q.CARTON_SN == CurPkg.Item.Package.SN)
                                .Where(q => q.WORK_ORDER == pkg.WORK_ORDER && q.SN == pkg.SN)
                                .ExecuteCommand();
                            //包装信息保存到工单条码明细表
                            db.Updateable<BIZ_MES_WO_SN>()
                                .SetColumns(q => q.TRAY_SN == CurPkg.Item.Package.SN)
                                .SetColumns(q => q.OUTER_SN == CurPkg.Item.Package.SN)
                                .Where(q => q.WORK_ORDER == pkg.WORK_ORDER && q.SN == pkg.SN)
                                .ExecuteCommand();
                        }
                    }
                });
                if (!dbTran.IsSuccess)
                {
                    //抛出异常
                    throw dbTran.ErrorException;
                }
            }
 
            if (CurPkg.IsFinished)
            {
                //最外层包装已经完成包装,则把工序中暂存标记设为false,统一提交包装内产品的过站记录
                CurPosition.NeedTemporaryStoreDBCommitAction = false;
                //删除工序上下文中的包装记录
                CurPosition.Context.Remove("CurPackage");
                CurPosition.Context.Remove("CurLabelDic");
                //action.LocaleMsg = new($"条码[{CurPkg.Item.Package?.SN}]包装完成");
                action.LocaleMsg = new("MES.WorkAction.PackingAction.PackingSuccess", CurPkg.Item.Package.SN);
            }
            else
            {
                //最外层包装未完成包装,则把工序中暂存标记设为true,待全部包装完成再统一提交包装内产品的过站记录
                CurPosition.NeedTemporaryStoreDBCommitAction = true;
                //如果工序上下文中没有包装记录则新建一个
                if (CurPosition.Context.ContainsKey("CurPackage"))
                {
                    CurPosition.Context["CurPackage"] = CurPkg;
                    CurPosition.Context["CurLabelDic"] = LabelDic;
                }
                else
                {
                    CurPosition.Context.Add("CurPackage", CurPkg);
                    CurPosition.Context.Add("CurLabelDic", LabelDic);
                }
                //action.LocaleMsg = new($"条码[{CurPosition.CurSN}]包装完成");
                action.LocaleMsg = new("MES.WorkAction.PackingAction.PackingSuccess", CurPosition.CurSN);
            }
 
            IsFinished = true;
            CurStep?.SetStatusMessage(StepStatus.Finished, Biz.L("包装完成"));
            action.Data.ShortMsg = new("包装完成", ShortMessage.Types.Success);
            
            return action;
        }
 
 
        #endregion Functions
    }
}