zs
2025-05-16 a2448a582f2baeabf32c4f8dd8ab447feb2538e6
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
using CMS.Extensions.Variable;
using CMS.Plugin.FlowManagement.Abstractions.FlowBusiness;
using CMS.Plugin.PipeLineLems.Apis;
using CMS.Plugin.PipeLineLems.Application.Contracts.Dtos.MyTestEntityNames;
using CMS.Plugin.PipeLineLems.Domain.MyTestEntityNames;
using CMS.Plugin.PipeLineLems.Jobs;
using CMS.Plugin.ProcessManagement.Abstractions;
using CMS.Plugin.TraceManagement.Abstractions.Models.Traces;
using CMS.Plugin.TraceManagement.Abstractions;
using CMS.Project;
using CMS.Project.Abstractions;
using CMS.Unit.RuntimeValue.Abstractions;
using KissUtil.Extensions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Uow;
using CMS.Plugin.PipeLineLems.Application.Contracts.Services;
using CMS.Plugin.PipeLineLems.Domain.WorkPlan;
using CMS.Plugin.PipeLineLems.Domain.CallMaterialOrder;
using System.Collections.Generic;
using CMS.Framework.AspNetCore.Users;
using NPOI.SS.Formula.Functions;
 
namespace CMS.Plugin.PipeLineLems.ProjectService
{
    /// <summary>
    /// 工程服务,和工程关联的后台服务,当<see cref="IProjectServiceRunner"/>以当前Key调用时会被执行
    /// </summary>
    public class PipeLineLemsProjectService : BaseProjectService
    {
        private IServiceProvider _serviceProvider;
        private readonly ILogger<PipeLineLemsProjectService> _logger;
        private readonly IVariableDataCache _variableDataCache;
 
 
        /// <summary>
        /// 变量服务
        /// </summary>
        private readonly VariableService _variableService;
        private FlowVariableChannelListener _channelListener;
        private Dictionary<string, string> _monitorVariableNames;
 
        /// <summary>
        /// 服务的Key,唯一,供<see cref="IProjectServiceRunner"/>使用
        /// </summary>
        public override string Key => "PipeLineLems";
 
        /// <summary>
        /// 服务描述,显示在服务列表UI上的名称
        /// </summary>
        public override string Description => "PipeLineLems服务";
 
        /// <summary>
        /// 启用授权
        /// </summary>
        public override bool AuthRequired => true;
 
        /// <summary>
        /// Initializes a new instance of the <see cref="PipeLineLemsProjectService"/> class.
        /// </summary>
        /// <param name="logger">The logger.</param>
        /// <param name="variableDataCache">The variable data cache.</param>
        public PipeLineLemsProjectService(
            VariableService variableService,
            IServiceProvider serviceProvider, ILogger<PipeLineLemsProjectService> logger, IVariableDataCache variableDataCache)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
            _variableDataCache = variableDataCache;
            _variableService = variableService;
        }
 
        /// <summary>
        /// 开启服务
        /// </summary>
        /// <param name="serviceProvider">具有工程上下文的实例</param>
        public override async Task StartAsync(IServiceProvider serviceProvider)
        {
            if (State == ProjectServiceState.Started)
            {
                return;
            }
 
            // 监听变量
            _monitorVariableNames = new Dictionary<string, string>
            {
                { "打码进站信号", "打码进站信号(描述)" },
                { "请求生成打码产品码信号", "请求生成打码产品码信号(描述)" },
                { "请求生成切割产品码信号", "请求生成切割产品码信号(描述)" },
                { "切割进站信号", "切割进站信号(描述)" },
            };
 
            // 创建通道监听
            _channelListener?.Token?.Dispose();
            _channelListener = new FlowVariableChannelListener(_logger, _variableDataCache);
            _channelListener.CreateChannel(Key, waitListener: false, timeout: TimeSpan.FromSeconds(30), variableFilter: _monitorVariableNames.Keys.ToHashSet());
            _channelListener.TagChanged += OnTagValueChanged;
 
            await base.StartAsync(serviceProvider);
        }
 
        /// <summary>
        /// 停止服务
        /// </summary>
        /// <param name="serviceProvider">具有工程上下文的实例</param>
        public override async Task StopAsync(IServiceProvider serviceProvider)
        {
            if (_channelListener != null)
            {
                // 释放监听
                _channelListener.TagChanged -= OnTagValueChanged;
                _channelListener.Token.Dispose();
                _channelListener = null;
            }
 
            // 使用后台作业异步处理
            //await _serviceProvider.GetRequiredService<IBackgroundJobManager>().EnqueueAsync(new PipeLineLemsArgs
            //{
            //    Subject = "PipeLineLems_Subject",
            //    Body = "PipeLineLems_Body",
            //});
 
 
            await base.StopAsync(serviceProvider);
        }
 
        /// <summary>
        /// Called when [tag value changed].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="TagChangedEventArgs"/> instance containing the event data.</param>
        private async void OnTagValueChanged(object sender, TagChangedEventArgs e)
        {
            var changeds = e.Changeds.Where(x => _monitorVariableNames != null && _monitorVariableNames.ContainsKey(x.Name));
            if (!changeds.Any())
            {
                return;
            }
 
            foreach (var changed in changeds)
            {
                var oldValue = changed.Old?.Value;
                var newValue = changed.New?.Value;
                var traceId = e.TraceId;
 
                _logger.LogInformation($"{changed.Name} 变量值发生变化,旧值{oldValue}=新值{newValue},TraceId={traceId}");
 
                if (changed.Name == "请求生成打码产品码信号")
                {
 
                    // TODO: 处理变量值变化
                    // Tips:https://cms-docs.shengyc.com/cms/api/%E5%90%8E%E7%AB%AF#3-%E5%8F%98%E9%87%8F%E6%A8%A1%E5%9D%97
                    /* 说明:通过订阅 IVariableDataCache.TagChanged 事件,您可以实时监控变量的变化。此事件会传递所有变量至事件处理函数,因此,业务层需在函数中筛选关注的变量。
                        注意事项:
                        (1)性能影响: 发布事件时,事件的发送者将阻塞流程。因此,强烈建议避免在事件处理函数中执行 I/ O 操作、HTTP 接口访问或其他耗时操作,以防止对系统性能产生严重影响,导致整个系统响应延迟。
                        (2)高频率触发: 由于事件订阅了全量变量,触发频率可能非常高。
                        (3)异步处理: 鉴于事件触发频率很高,建议业务层在筛选关注变量后,使用 Task 启动新线程处理业务逻辑,以避免阻塞核心的变量监听功能,实现业务层与平台基座的解耦。
                        (4)并发管理: 如果业务层并发量大,必须优化代码设计和实施,以减少在高并发情况下的系统资源消耗,防止系统性能问题。
                        (5)代码安全: 安装并使用 CMS.CodeAnalysis 分析器来分析 IVariableDataCache.TagChanged 的使用情况。该工具能在使用不当时提供编译错误,帮助您提高代码质量。*/
 
                    if (changed.New?.Value.SafeString().ToBool() == true)
                    {
                        _ = Task.Run(async () =>
                        {
                            await HanlderForPringBarCodeByCreateProductAsync();
                        });
                    }
                    else
                    {
 
                        _ = Task.Run(async () =>
                        {
                            await HanlderForPringBarCodeByCreateProductWhenFalseAsync();
                        });
                    }
                }
 
                if (changed.Name == "打码进站信号" && changed.New?.Value.SafeString().ToBool() == true)
                {
 
                    // TODO: 处理变量值变化
                    // Tips:https://cms-docs.shengyc.com/cms/api/%E5%90%8E%E7%AB%AF#3-%E5%8F%98%E9%87%8F%E6%A8%A1%E5%9D%97
                    /* 说明:通过订阅 IVariableDataCache.TagChanged 事件,您可以实时监控变量的变化。此事件会传递所有变量至事件处理函数,因此,业务层需在函数中筛选关注的变量。
                        注意事项:
                        (1)性能影响: 发布事件时,事件的发送者将阻塞流程。因此,强烈建议避免在事件处理函数中执行 I/ O 操作、HTTP 接口访问或其他耗时操作,以防止对系统性能产生严重影响,导致整个系统响应延迟。
                        (2)高频率触发: 由于事件订阅了全量变量,触发频率可能非常高。
                        (3)异步处理: 鉴于事件触发频率很高,建议业务层在筛选关注变量后,使用 Task 启动新线程处理业务逻辑,以避免阻塞核心的变量监听功能,实现业务层与平台基座的解耦。
                        (4)并发管理: 如果业务层并发量大,必须优化代码设计和实施,以减少在高并发情况下的系统资源消耗,防止系统性能问题。
                        (5)代码安全: 安装并使用 CMS.CodeAnalysis 分析器来分析 IVariableDataCache.TagChanged 的使用情况。该工具能在使用不当时提供编译错误,帮助您提高代码质量。*/
 
                    _ = Task.Run(async () =>
                    {
                        await HanlderForPringBarCodeAsync();
                        // 例1:同步处理
                        //await ProcessAsync();
 
                        // 例2:调用外部API
                        //await ExecuteExternalApiAsync();
                    });
                }
 
 
 
                if (changed.Name == "切割进站信号" && changed.New?.Value.SafeString().ToBool() == true)
                {
 
                    // TODO: 处理变量值变化
                    // Tips:https://cms-docs.shengyc.com/cms/api/%E5%90%8E%E7%AB%AF#3-%E5%8F%98%E9%87%8F%E6%A8%A1%E5%9D%97
                    /* 说明:通过订阅 IVariableDataCache.TagChanged 事件,您可以实时监控变量的变化。此事件会传递所有变量至事件处理函数,因此,业务层需在函数中筛选关注的变量。
                        注意事项:
                        (1)性能影响: 发布事件时,事件的发送者将阻塞流程。因此,强烈建议避免在事件处理函数中执行 I/ O 操作、HTTP 接口访问或其他耗时操作,以防止对系统性能产生严重影响,导致整个系统响应延迟。
                        (2)高频率触发: 由于事件订阅了全量变量,触发频率可能非常高。
                        (3)异步处理: 鉴于事件触发频率很高,建议业务层在筛选关注变量后,使用 Task 启动新线程处理业务逻辑,以避免阻塞核心的变量监听功能,实现业务层与平台基座的解耦。
                        (4)并发管理: 如果业务层并发量大,必须优化代码设计和实施,以减少在高并发情况下的系统资源消耗,防止系统性能问题。
                        (5)代码安全: 安装并使用 CMS.CodeAnalysis 分析器来分析 IVariableDataCache.TagChanged 的使用情况。该工具能在使用不当时提供编译错误,帮助您提高代码质量。*/
 
                    _ = Task.Run(async () =>
                    {
                        await HanlderForCutAsync();
                        // 例1:同步处理
                        //await ProcessAsync();
 
                        // 例2:调用外部API
                        //await ExecuteExternalApiAsync();
                    });
                }
 
 
                if (changed.Name == "请求生成切割产品码信号")
                {
 
                    // TODO: 处理变量值变化
                    // Tips:https://cms-docs.shengyc.com/cms/api/%E5%90%8E%E7%AB%AF#3-%E5%8F%98%E9%87%8F%E6%A8%A1%E5%9D%97
                    /* 说明:通过订阅 IVariableDataCache.TagChanged 事件,您可以实时监控变量的变化。此事件会传递所有变量至事件处理函数,因此,业务层需在函数中筛选关注的变量。
                        注意事项:
                        (1)性能影响: 发布事件时,事件的发送者将阻塞流程。因此,强烈建议避免在事件处理函数中执行 I/ O 操作、HTTP 接口访问或其他耗时操作,以防止对系统性能产生严重影响,导致整个系统响应延迟。
                        (2)高频率触发: 由于事件订阅了全量变量,触发频率可能非常高。
                        (3)异步处理: 鉴于事件触发频率很高,建议业务层在筛选关注变量后,使用 Task 启动新线程处理业务逻辑,以避免阻塞核心的变量监听功能,实现业务层与平台基座的解耦。
                        (4)并发管理: 如果业务层并发量大,必须优化代码设计和实施,以减少在高并发情况下的系统资源消耗,防止系统性能问题。
                        (5)代码安全: 安装并使用 CMS.CodeAnalysis 分析器来分析 IVariableDataCache.TagChanged 的使用情况。该工具能在使用不当时提供编译错误,帮助您提高代码质量。*/
 
                    if (changed.New?.Value.SafeString().ToBool() == true)
                    {
                        _ = Task.Run(async () =>
                        {
                            await HanlderForCutByCreateProductAsync();
                        });
                    }
                    else
                    {
                        _ = Task.Run(async () =>
                        {
                            await HanlderForCutByCreateProductWhenFlaseAsync();
                        });
                    }
                }
            }
        }
 
        /// <summary>
        /// Processes the asynchronous.
        /// </summary>
        private async Task ProcessAsync()
        {
            using var scope = _serviceProvider.CreateScope();
            var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
            using var uow = unitOfWorkManager.Begin(requiresNew: true);
            var mytestentitynameRepository = scope.ServiceProvider.GetRequiredService<IMyTestEntityNameRepository>();
            var count = await mytestentitynameRepository.GetCountAsync();
 
            // 如果有更新数据库操作,需提交保存
            // await uow.SaveChangesAsync();
 
            _logger.LogInformation($"ProcessAsync,Count={count}");
        }
 
        /// <summary>
        /// Executes the external API.
        /// </summary>
        private async Task ExecuteExternalApiAsync()
        {
            try
            {
                await _serviceProvider.GetRequiredService<IPipeLineLemsExternalApi>().CreateAsync(new MyTestEntityNameCreateDto
                {
                    Name = "MyTestEntityName_Name",
                    Code = "MyTestEntityName_Code",
                });
            }
            catch (Exception e)
            {
                _logger.LogException(e);
            }
        }
 
        /// <summary>
        /// 打码进站信号
        /// </summary>
        /// <returns></returns>
        private async Task HanlderForPringBarCodeAsync()
        {
 
            var workPlanAppService = _serviceProvider.GetRequiredService<IWorkPlanAppService>();
            var workPlanRepository = _serviceProvider.GetRequiredService<IWorkPlanRepository>();
            var callMaterialOrderAppService = _serviceProvider.GetRequiredService<ICallMaterialOrderAppService>();
 
            using var scope = _serviceProvider.CreateScope();
            var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
            using var uow = unitOfWorkManager.Begin(requiresNew: true);
 
            var plcTaskNo = await _variableService.ReadValueAsync("打码进站PLC任务号");
 
            if (string.IsNullOrEmpty(plcTaskNo?.Content?.Value.SafeString().ToString()))
            {
 
            }
            else
            {
 
 
 
                var myTaskNo = plcTaskNo.Content.Value.SafeString().ToString();
                CallMaterialOrder callMaterialOrder = null;
                try
                {
                    //根据wms任务号寻找 叫料工单
                    callMaterialOrder = await callMaterialOrderAppService.FindByWmsTaskNoAsync(myTaskNo);
                    if (callMaterialOrder == null) return;//结束
 
 
 
                    //根据原料标识寻找 作业计划
                    var workPlanList = await workPlanAppService.GetListByFilterAsync(x => x.DataIdentifier == callMaterialOrder.DataIdentifier);
                    if (workPlanList?.Count == 0) return;//结束
 
                    ////TODO:暂时生成产品ID
                    ////var productID = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                    //var productID = workPlanList.First().PipeSpecCode;
                    //Dictionary<string, object?> keyValuePairs_productID = new Dictionary<string, object?>
                    //{
                    //    { "打码_ProductID", productID},
                    //};
                    //var ret = _variableService.WriteValueAsync(keyValuePairs_productID);
 
                    ////更新为生产中 
                    //foreach (var item in workPlanList)
                    //{
                    //    item.WorkPlanStatus = Domain.Shared.Enums.WorkPlanStatusEnum.生产中;
                    //}
                    //await workPlanRepository.UpdateManyAsync(workPlanList);
 
                    //得到码值
                    var code1 = "";
                    var code2 = "";
                    var code3 = "";
                    var pipeSpecCode1 = "";
                    var pipeSpecCode2 = "";
                    var pipeSpecCode3 = "";
                    var new_workPlanList = workPlanList.Where(x => x.ProcessRouteNumber == "切割").ToList();
                    for (int i = 0; i < new_workPlanList.Count; i++)
                    {
                        if (i == 0)
                        {
                            code1 = new_workPlanList[i].MarkingContent;
                            pipeSpecCode1 = new_workPlanList[i].PipeSpecCode;
                        }
                        if (i == 1)
                        {
                            code2 = new_workPlanList[i].MarkingContent;
                            pipeSpecCode2 = new_workPlanList[i].PipeSpecCode;
                        }
                        if (i == 2)
                        {
                            code3 = new_workPlanList[i].MarkingContent;
                            pipeSpecCode3 = new_workPlanList[i].PipeSpecCode;
                        }
                    }
                    //获取 批次
                    await callMaterialOrderAppService.wh
                    Dictionary<string, object?> keyValuePairs = new Dictionary<string, object?>
                    {
                        { "打码工件1",code1},
                        { "打码工件2", code2},
                        { "打码工件3", code3 },
                        { "打码管段编码1",pipeSpecCode1},
                        { "打码管段编码2", pipeSpecCode2},
                        { "打码管段编码3", pipeSpecCode3 },
                        { "打码管段编码", new_workPlanList.First().PipeSpecCode },
                        { "打码管段名称", new_workPlanList.First().PipeSectionName },
                        { "打码原料管型号", new_workPlanList.First().MaterialMode },
                        { "打码原料标识", new_workPlanList.First().DataIdentifier },
                        { "打码原料管批次", new_workPlanList.First() },
                    };
                    _variableService.WriteValueAsync(keyValuePairs);
 
                    //TODO:模拟采集参数
                    keyValuePairs = new Dictionary<string, object?>
                    {
                        { "打码速度", 100},
                        { "打码质量", 2},
                    };
                    var ret2 = _variableService.WriteValueAsync(keyValuePairs);
 
 
 
 
                    uow.CompleteAsync();
                }
                catch (Exception)
                {
                    uow.RollbackAsync();
                    throw;
                }
            }
        }
 
        /// <summary>
        /// 请求生成打码产品码信号
        /// </summary>
        /// <returns></returns>
        private async Task HanlderForPringBarCodeByCreateProductAsync()
        {
 
            var workPlanAppService = _serviceProvider.GetRequiredService<IWorkPlanAppService>();
            var workPlanRepository = _serviceProvider.GetRequiredService<IWorkPlanRepository>();
            var callMaterialOrderAppService = _serviceProvider.GetRequiredService<ICallMaterialOrderAppService>();
 
            using var scope = _serviceProvider.CreateScope();
            var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
            using var uow = unitOfWorkManager.Begin(requiresNew: true);
 
            var plcTaskNo = await _variableService.ReadValueAsync("打码进站PLC任务号");
 
            if (string.IsNullOrEmpty(plcTaskNo?.Content?.Value.SafeString().ToString()))
            {
 
            }
            else
            {
 
 
 
                var myTaskNo = plcTaskNo.Content.Value.SafeString().ToString();
                CallMaterialOrder callMaterialOrder = null;
                try
                {
                    //根据wms任务号寻找 叫料工单
                    callMaterialOrder = await callMaterialOrderAppService.FindByWmsTaskNoAsync(myTaskNo);
                    if (callMaterialOrder == null) return;//结束
 
 
 
                    //根据原料标识寻找 作业计划
                    var workPlanList = await workPlanAppService.GetListByFilterAsync(x => x.DataIdentifier == callMaterialOrder.DataIdentifier);
                    if (workPlanList?.Count == 0) return;//结束
 
                    //TODO:暂时生成产品ID
                    //var productID = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                    var productID = callMaterialOrder.DataIdentifier;
                    Dictionary<string, object?> keyValuePairs_productID = new Dictionary<string, object?>
                    {
                        { "打码_ProductID", productID},
                        { "CMS反馈请求生成打码产品码信号结果", true},
                    };
                    var ret = _variableService.WriteValueAsync(keyValuePairs_productID);
 
 
                    //更新为生产中 
                    var new_workPlanList = workPlanList.Where(x => x.ProcessRouteNumber == "切割").ToList();
                    foreach (var item in new_workPlanList)
                    {
                        item.WorkPlanStatus = Domain.Shared.Enums.WorkPlanStatusEnum.生产中;
                    }
                    await workPlanRepository.UpdateManyAsync(new_workPlanList);
 
 
                    uow.CompleteAsync();
                }
                catch (Exception)
                {
                    uow.RollbackAsync();
                    throw;
                }
            }
        }
 
        /// <summary>
        /// 请求生成打码产品码信号(值为false的时候)
        /// </summary>
        /// <returns></returns>
        private async Task HanlderForPringBarCodeByCreateProductWhenFalseAsync()
        {
            Dictionary<string, object?> keyValuePairs_productID = new Dictionary<string, object?>
            {
                        { "CMS反馈请求生成打码产品码信号结果", false},
                    };
            var ret = _variableService.WriteValueAsync(keyValuePairs_productID);
        }
 
 
        ///// <summary>
        ///// 切割
        ///// </summary>
        ///// <returns></returns>
        //private async Task HanlderForCutAsync()
        //{
 
        //    var plcTaskNo = await _variableService.ReadValueAsync("切割进站PLC任务号");
 
        //    if (string.IsNullOrEmpty(plcTaskNo?.Content?.Value.SafeString().ToString()))
        //    {
 
        //    }
        //    else
        //    {
        //        var myTaskNo = plcTaskNo.Content.Value.SafeString().ToString();
        //        //TODO:暂时先写入 内部变量
        //        Dictionary<string, object?> keyValuePairs = new Dictionary<string, object?>
        //            {
        //                { "切割位置1", "555555" },
        //                { "切割位置2", "66666" },
        //                { "切割位置3", "77777" }
        //            };
        //        _variableService.WriteValueAsync(keyValuePairs);
 
        //        //TODO:模拟采集参数
        //        keyValuePairs = new Dictionary<string, object?>
        //            {
        //                { "切割速度", 99},
        //                { "切割质量", 1},
        //            };
        //        var ret2 = _variableService.WriteValueAsync(keyValuePairs);
 
        //        //TODO:暂时生成产品ID
        //        //获取上一个工序的产品ID
        //        //根据工序名获取工序对象
        //        var _workSectionManager = _serviceProvider.GetRequiredService<IWorkSectionManager>();
        //        var lastWorkSection = "打码工序";
        //        var workSection = await _workSectionManager.GetByNameAsync(lastWorkSection);
 
        //        //获取工单数据(从末工序查询3个产品)
        //        //读取scms_productions表,根据当前时间查询最近3条记录
        //        var traceManager = _serviceProvider.GetRequiredService<ITraceProvider>();
        //        GetTracesRequest request = new GetTracesRequest()
        //        {
        //            WorkSectionId = workSection.Id,
        //        };
        //        TraceModel traceModel = null;
        //        var list = await traceManager.GetTracesAsync(request);
        //        if (list?.Count > 0)
        //        {
        //            //重新排序
        //            list = list.OrderByDescending(x => x.FinishTime).ToList();
        //            traceModel = list.First();
        //        }
        //        //var productID = Guid.NewGuid().ToString();
        //        var productID = DateTime.Now.ToString("yyyyMMddHHmmssfff");
        //        if (traceModel != null)
        //        {
        //            productID = traceModel.SerialNumber;
        //        }
        //        keyValuePairs = new Dictionary<string, object?>
        //            {
        //                { "切割_ProductID", productID},
        //            };
        //        var ret = _variableService.WriteValueAsync(keyValuePairs);
        //    }
        //}
 
        /// <summary>
        /// 切割
        /// </summary>
        /// <returns></returns>
        private async Task HanlderForCutAsync()
        {
 
            var workPlanAppService = _serviceProvider.GetRequiredService<IWorkPlanAppService>();
            var workPlanRepository = _serviceProvider.GetRequiredService<IWorkPlanRepository>();
            var callMaterialOrderAppService = _serviceProvider.GetRequiredService<ICallMaterialOrderAppService>();
 
            using var scope = _serviceProvider.CreateScope();
            var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
            using var uow = unitOfWorkManager.Begin(requiresNew: true);
 
            var plcTaskNo = await _variableService.ReadValueAsync("切割进站PLC任务号");
 
            if (string.IsNullOrEmpty(plcTaskNo?.Content?.Value.SafeString().ToString()))
            {
 
            }
            else
            {
 
 
 
                var myTaskNo = plcTaskNo.Content.Value.SafeString().ToString();
                CallMaterialOrder callMaterialOrder = null;
                try
                {
                    //根据wms任务号寻找 叫料工单
                    callMaterialOrder = await callMaterialOrderAppService.FindByWmsTaskNoAsync(myTaskNo);
                    if (callMaterialOrder == null) return;//结束
 
 
 
                    //根据原料标识寻找 作业计划
                    var workPlanList = await workPlanAppService.GetListByFilterAsync(x => x.DataIdentifier == callMaterialOrder.DataIdentifier);
                    if (workPlanList?.Count == 0) return;//结束
 
                    ////TODO:暂时生成产品ID
                    ////var productID = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                    //var productID = workPlanList.First().PipeSpecCode;
                    //Dictionary<string, object?> keyValuePairs_productID = new Dictionary<string, object?>
                    //{
                    //    { "切割_ProductID", productID},
                    //};
                    //var ret = _variableService.WriteValueAsync(keyValuePairs_productID);
 
                    ////更新为生产中 
                    //foreach (var item in workPlanList)
                    //{
                    //    item.WorkPlanStatus = Domain.Shared.Enums.WorkPlanStatusEnum.生产中;
                    //}
                    //await workPlanRepository.UpdateManyAsync(workPlanList);
 
                    //得到码值
                    decimal code1 = 0;
                    decimal code2 = 0;
                    decimal code3 = 0;
                    var pipeSpecCode1 = "";
                    var pipeSpecCode2 = "";
                    var pipeSpecCode3 = "";
                    var new_workPlanList = workPlanList.Where(x => x.ProcessRouteNumber == "装配").ToList();
                    for (int i = 0; i < new_workPlanList.Count; i++)
                    {
                        if (i == 0)
                        {
                            code1 = new_workPlanList[i].CuttingPosition;
                            pipeSpecCode1 = new_workPlanList[i].PipeSpecCode;
                        }
                        if (i == 1)
                        {
                            code2 = new_workPlanList[i].CuttingPosition;
                            pipeSpecCode2 = new_workPlanList[i].PipeSpecCode;
                        }
                        if (i == 2)
                        {
                            code3 = new_workPlanList[i].CuttingPosition;
                            pipeSpecCode3 = new_workPlanList[i].PipeSpecCode;
                        }
                    }
                    Dictionary<string, object?> keyValuePairs = new Dictionary<string, object?>
                    {
                        { "切割位置1",code1},
                        { "切割位置2", code2},
                        { "切割位置3", code3 },
                        { "切割管段编码1",pipeSpecCode1},
                        { "切割管段编码2", pipeSpecCode2},
                        { "切割管段编码3", pipeSpecCode3 },
                        { "切割管段编码", new_workPlanList.First().PipeSpecCode },
                        { "切割管段名称", new_workPlanList.First().PipeSectionName },
                        { "切割原料管型号", new_workPlanList.First().MaterialMode },
                        { "切割原料标识", new_workPlanList.First().DataIdentifier }
                    };
                    _variableService.WriteValueAsync(keyValuePairs);
 
                    //TODO:模拟采集参数
                    keyValuePairs = new Dictionary<string, object?>
                    {
                        { "切割速度", 99},
                        { "切割质量", 1},
                    };
                    var ret2 = _variableService.WriteValueAsync(keyValuePairs);
 
 
 
 
                    uow.CompleteAsync();
                }
                catch (Exception)
                {
                    uow.RollbackAsync();
                    throw;
                }
            }
        }
 
        /// <summary>
        /// 请求生成切割产品码信号
        /// </summary>
        /// <returns></returns>
        private async Task HanlderForCutByCreateProductAsync()
        {
 
            var workPlanAppService = _serviceProvider.GetRequiredService<IWorkPlanAppService>();
            var workPlanRepository = _serviceProvider.GetRequiredService<IWorkPlanRepository>();
            var callMaterialOrderAppService = _serviceProvider.GetRequiredService<ICallMaterialOrderAppService>();
 
            using var scope = _serviceProvider.CreateScope();
            var unitOfWorkManager = scope.ServiceProvider.GetRequiredService<IUnitOfWorkManager>();
            using var uow = unitOfWorkManager.Begin(requiresNew: true);
 
            var plcTaskNo = await _variableService.ReadValueAsync("切割进站PLC任务号");
 
            if (string.IsNullOrEmpty(plcTaskNo?.Content?.Value.SafeString().ToString()))
            {
 
            }
            else
            {
 
 
 
                var myTaskNo = plcTaskNo.Content.Value.SafeString().ToString();
                CallMaterialOrder callMaterialOrder = null;
                try
                {
                    //根据wms任务号寻找 叫料工单
                    callMaterialOrder = await callMaterialOrderAppService.FindByWmsTaskNoAsync(myTaskNo);
                    if (callMaterialOrder == null) return;//结束
 
 
 
                    //根据原料标识寻找 作业计划
                    var workPlanList = await workPlanAppService.GetListByFilterAsync(x => x.DataIdentifier == callMaterialOrder.DataIdentifier);
                    if (workPlanList?.Count == 0) return;//结束
 
                    //TODO:暂时生成产品ID
                    //var productID = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                    var productID = callMaterialOrder.DataIdentifier;
                    Dictionary<string, object?> keyValuePairs_productID = new Dictionary<string, object?>
                    {
                        { "切割_ProductID", productID},
                        { "CMS反馈请求生成切割产品码信号结果", true},
                    };
                    var ret = _variableService.WriteValueAsync(keyValuePairs_productID);
 
                    var new_workPlanList = workPlanList.Where(x => x.ProcessRouteNumber == "装配").ToList();
                    //更新为生产中 
                    foreach (var item in new_workPlanList)
                    {
                        item.WorkPlanStatus = Domain.Shared.Enums.WorkPlanStatusEnum.生产中;
                        item.Remark = "更新生产中";
                    }
                    await workPlanRepository.UpdateManyAsync(new_workPlanList);
 
                    var new_workPlanList_printCode = workPlanList.Where(x => x.ProcessRouteNumber == "切割").ToList();
                    foreach (var item in new_workPlanList_printCode)
                    {
                        item.WorkPlanStatus = Domain.Shared.Enums.WorkPlanStatusEnum.已完成;
                        item.Remark = "更新已完成";
                    }
                    await workPlanRepository.UpdateManyAsync(new_workPlanList_printCode);
 
 
                    uow.CompleteAsync();
                }
                catch (Exception)
                {
                    uow.RollbackAsync();
                    throw;
                }
            }
        }
 
        /// <summary>
        /// 请求生成切割产品码信号(值为false的时候)
        /// </summary>
        /// <returns></returns>
        private async Task HanlderForCutByCreateProductWhenFlaseAsync()
        {
 
            Dictionary<string, object?> keyValuePairs_productID = new Dictionary<string, object?>
                    {
                        { "CMS反馈请求生成切割产品码信号结果", false},
                    };
            var ret = _variableService.WriteValueAsync(keyValuePairs_productID);
        }
    }
}