#Const PRINT_FIRST = 1

Imports System.Globalization
Imports System.Text
Imports System.Threading
Imports OpenCvSharp
Imports OpenCvSharp.Extensions
Imports UTS_Core.DebugLog
Imports UTS_Core.UTSModule
Imports UTS_Core.UTSModule.DbConnect
Imports UTS_Core.UTSModule.DbTableModel.Customer
Imports UTS_Core.UTSModule.Station
Imports UTS_Core.UTSModule.Test
Imports UTS_Core.UTSModule.Test.Controls
Imports UTS_Core.UTSModule.Test.StatusMonitor

Public Class BM_ITM53_P1_FrmStationTest
    Implements IProcessStation
    Implements IProductionLine

    Private _utsApp As UtsAppForm
    Private _stationPlan As StationPackagePlan
    Private _ftp As FtpService
    Private _isSaveBarcode As Boolean

    Private CurrentRecordType As RecordTypes = RecordTypes.Production '全局变量，用于保存当前是量产状态还是返工状态
    Private gReowrkBoxNum As Integer = 0 '用于保持当前序列号

    Enum RecordTypes
        Production '量产状态，序列号自增’
        Rework '返工状态，序列号手工输入，并且不会自增’
    End Enum


    ''' <summary>
    ''' 内部订单
    ''' </summary>
    Private _mo As String = ""

    ''' <summary>
    ''' 外部订单
    ''' </summary>
    Private _po As String = ""

    ''' <summary>
    ''' 当前装箱的条码
    ''' </summary>
    Private _dutSn As String

    ''' <summary>
    ''' 当前箱号的条码
    ''' </summary>
    Private _boxCode As String

    ''' <summary>
    ''' 条码总数
    ''' </summary>
    Private _dutCount As Integer

    ''' <summary>
    ''' 全局箱号
    ''' </summary>
    Private _boxNum As Integer

    ''' <summary>
    ''' 当前装箱的条码集合
    ''' </summary>
    Private _dutSnLst As New List(Of String)

    ''' <summary>
    ''' 使用模板的名称
    ''' </summary>
    Private _templateName As String

    ''' <summary>
    ''' 录入表格中的变量集合
    ''' </summary>
    Dim _inputFileds As New Dictionary(Of String, Integer)

    ''' <summary>
    ''' 模板表格中的变量集合
    ''' </summary>
    Dim _tempFileds As New Dictionary(Of String, FiledLocation)


    Public Sub ShowForm(parentControl As Control)
        FormBorderStyle = FormBorderStyle.None
        TopLevel = False
        Dock = DockStyle.Fill
        Parent = parentControl

        Show()
    End Sub

    ''' <summary>
    ''' 产线变化
    ''' </summary>
    Public Sub ProductionLineChanged() Implements IProductionLine.ProductionLineChanged
        'Todo:产线变化代码
        ApplicationLog.WriteInfoLog($"测试页面生产线变更中。")


        ApplicationLog.WriteInfoLog($"测试页面生产线变更完成。")
    End Sub

    ''' <summary>
    ''' 站位变化
    ''' </summary>
    Public Sub Station_Changed() Implements IProcessStation.StationChanged
        'Todo:站位变化代码
        ApplicationLog.WriteInfoLog($"测试页面站位变更中，PN：{_utsApp.ProcessStation.ParentProject.Name} - SN:{_utsApp.ProcessStation.Name} - TP:{_utsApp.ProcessStation.Packet.Name}!")

        _stationPlan = CType(_utsApp.ProcessStation.Packet.StationPlan, StationPackagePlan)
        InitBarcodeGrid(_stationPlan)

        ApplicationLog.WriteInfoLog($"测试页面站位变更完成!")
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
        ApplicationLog.WriteInfoLog($"测试页面加载中。")

        '创建资源文件夹
        IO.Directory.CreateDirectory($"{Application.StartupPath}/Package")
        '创建打印PDF文件
        IO.Directory.CreateDirectory($"{Application.StartupPath}/PrintPDF")

        '初始化UTS窗体信息,失败则关闭窗体
        If InitializeUtsApp() = False Then Return

        '初始化窗体页面
        InitializeForm()

        Try
            _ftp = New FtpService(UtsRegistry.FtpHost, CInt(_utsApp.License.FtpPort), _utsApp.License.FtpUser, _utsApp.License.FtpPwd)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"初始化FTP服务器失败,原因：{ex.Message}")
            MsgBox($"初始化FTP服务器失败,原因：{ex.Message}")
            Close()
            Return
        End Try

        _boxNum = ReadBoxNumFromRegostry()
        ApplicationLog.WriteInfoLog($"初始箱号：{_boxNum}")

        NudBoxNum.Value = _boxNum

        ApplicationLog.WriteInfoLog($"测试页面加载完成。")
    End Sub

    Private Function InitializeUtsApp() As Boolean
        _utsApp = UtsAppForm.CreateSingleton()
        _utsApp.AddStatisticsObserver(Me)

        Try
            If _utsApp.IsInitialized = False Then
                _utsApp.Initialize(ProcessStation.StationTypeEnum.Package) 'Todo:可根据需要限定可选站位
            End If
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"初始化窗体失败,原因：{ex.Message}!")

            MsgBox($"初始化窗体失败,原因：{ex.Message}")
            Close()
            Return False
        End Try

        Return True
    End Function

    Private moDic As Dictionary(Of String, Integer)

    Private Sub InitializeForm()
        'Todo:初始化窗体代码

        InitBarcodeGrid()

        InitMoList()
    End Sub

    Private Sub InitMoList()
        CboMoList.Items.Clear()
        CboMoList.Items.Add("")
        moDic = New Dictionary(Of String, Integer)

        Dim dt As DataTable = DbConnector.SearchMoTable()
        If dt Is Nothing Then Return

        Try
            For row As Integer = 0 To dt.Rows.Count - 1
                moDic.Add(dt.Rows(row)(OrderInternalTable.ColNames.InternalNo.ToString).ToString, CInt(dt.Rows(row)(OrderInternalTable.ColNames.ID.ToString)))
                CboMoList.Items.Add(dt.Rows(row)(OrderInternalTable.ColNames.InternalNo.ToString).ToString)
            Next
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"初始化MO列表失败,原因：{ex.Message}")
            Console.WriteLine($"初始化MO列表失败,原因：{ex.Message}")
            Return
        End Try
    End Sub


    Private Sub SaveTestResult()
        If _utsApp.ProcessStation Is Nothing Then
            MsgBox($"请选择项目与测试站后再尝试录入！")
            Return
        End If

        If String.IsNullOrEmpty(_boxCode) Then
            MsgBox($"无效的箱号[{_boxCode}],请重新录入")
            Return
        End If

#If PRINT_FIRST = 0 Then
        If _imgList.Count <> _stationPlan.PictureCount Then
            MsgBox($"请拍摄全部图像后重试")
            Return
        End If
#End If
        If _dutSnLst.Count <> _dutCount Then
            If _stationPlan.MissingQuantity = StationPackagePlan.MissCountStatus.Yes Then
                If MsgBox($"当前录入数量[{_dutSnLst.Count}]与预期数量[{_dutCount}]不相符,是否录入", MsgBoxStyle.OkCancel) <> MsgBoxResult.Ok Then
                    Return
                End If
            ElseIf _stationPlan.MissingQuantity = StationPackagePlan.MissCountStatus.Key Then
                Dim pwd As String = UtsInputBox.ShowDialog("条码未满足录入数量，输入正确录入密码后继续操作", $"录入密码", "", True)

                If pwd Is Nothing Then Return
                If String.Compare(pwd, _stationPlan.MissingQuantityKey, True) <> 0 Then Return
            Else
                MsgBox($"当前录入数量[{_dutSnLst.Count}]与预期数量[{_dutCount}]不相符,请重试！")
            End If
        End If

#If PRINT_FIRST = 0 Then
        '上传图像资源至FTP
        For i As Integer = 1 To _stationPlan.PictureCount
            Dim imgRemotePath As String = $"/uts_Manager/AUTS/{_utsApp.License.VendorName}/Package/{_imgList(i - 1).FileName}"
            Dim localPath As String = $"{Application.StartupPath}/Package/{_imgList(i - 1).FileName}"

            '保存图像至本地
            Try
                _imgList(i - 1).InputImage.Save(localPath)
            Catch ex As Exception
                MsgBox($"保存第[{i}]个图像失败：{ex.Message}")
                LblResult.Text = "FAIL"
                LblResult.ForeColor = Color.Red
                TestStatusMonitor.TestStatus = TestStatusMonitor.TestStatusEnum.TestFail
                Return
            End Try
            '保存图像至云端
            If UploadFileToFtp(localPath, imgRemotePath) = False Then Return
        Next
#End If
        ApplicationLog.WriteInfoLog($"打印条码进行中，当前箱号：{_boxNum}")

        'Todo:填充测试记录
        For i As Integer = 0 To _dutSnLst.Count - 1
            FillTestResult(_dutSnLst(i))

            Try
                '提交测试记录,缺省参数默认为False，True则测试记录唯一,覆盖相同条码记录
                _utsApp.CommitTestResult()
            Catch ex As Exception
                ApplicationLog.WriteErrorLog($"{_dutSnLst(i)} 测试结果录入失败，原因：{ex.Message}")
                MsgBox($"{_dutSnLst(i)} 测试结果录入失败,原因：{ex.Message}")
                LblResult.Text = "FAIL"
                LblResult.ForeColor = Color.Red
                TestStatusMonitor.TestStatus = TestStatusMonitor.TestStatusEnum.TestFail
                Return
            End Try
        Next

        TestStatusMonitor.TestStatus = TestStatusMonitor.TestStatusEnum.TestPass
        LblResult.Text = "PASS"
        LblResult.ForeColor = Color.Green

        '打印
        If _stationPlan.AutoPrint Then
            GrdPriview.Print()
        Else
            GrdPriview.PrintPreview()
        End If

        '录入成功后处理
        _isSaveBarcode = True '已录入数据库

        BtnCommit.Enabled = False '2022-01-08 V1.2 Momo 录入成功后锁定按钮，防止重复提交
        _barcodeIndex = 1

        '设置焦点
        If CurrentRecordType = RecordTypes.Production Then
            TxtDevSn.Focus()
            TxtDevSn.SelectAll()

            '更新箱号
            _boxNum += 1
            NudBoxNum.Value = _boxNum

            ApplicationLog.WriteInfoLog($"打印条码完成,最新后箱号：{_boxNum}")
        Else
            TxtReworkSn.Focus()
            TxtReworkSn.SelectAll()
        End If
    End Sub

    Private Sub InitInputInfo()
        '清空SN
        _dutSnLst.Clear()

        '更新图像索引
        _imageIndex = 1
        GrdInput.Images.Clear()

        '清空录入信息
        GrdInput.Locked = False
        GrdInput.Range(1, ColNames.Value, GrdInput.Rows - 1, ColNames.Result).ClearAll()
        GrdInput.Locked = True

        '更新显示箱号
        _boxCode = GetBoxCode()
        Dim r As Integer = _inputFileds("boxnum")
        GrdInput.Cell(r, ColNames.Value).Text = _boxCode
        GrdInput.Cell(r, ColNames.Result).Text = "Pass"
        GrdInput.Cell(r, ColNames.Result).ForeColor = Color.Green

        For Each f As KeyValuePair(Of String, FiledLocation) In _tempFileds
            GrdPriview.Cell(f.Value.Row, f.Value.Col).Text = ""
        Next

        If _tempFileds.ContainsKey("boxnum") Then
            GrdPriview.Cell(_tempFileds("boxnum").Row, _tempFileds("boxnum").Col).Text = _boxCode
        End If

        LblResult.Text = "Testing"
        LblResult.ForeColor = Color.Yellow
        TestStatusMonitor.TestStatus = TestStatusMonitor.TestStatusEnum.Testing
    End Sub

    Private Sub SaveImage()
        If _isSaveBarcode = False Then
            MsgBox($"请打印箱号后重试！")
            Return
        End If

        If _imgList.Count <> _stationPlan.PictureCount Then
            MsgBox($"请拍摄全部图像后重试")
            Return
        End If

        '上传图像资源至FTP
        For i As Integer = 1 To _stationPlan.PictureCount
            Dim imgRemotePath As String = $"/uts_Manager/AUTS/{_utsApp.License.VendorName}/Package/{_imgList(i - 1).FileName}"
            Dim localPath As String = $"{Application.StartupPath}/Package/{_imgList(i - 1).FileName}"

            '保存图像至本地
            Try
                _imgList(i - 1).InputImage.Save(localPath)
            Catch ex As Exception
                ApplicationLog.WriteErrorLog($"保存第[{i}]个图像失败：{ex.Message}")
                MsgBox($"保存第[{i}]个图像失败：{ex.Message}")
                LblResult.Text = "FAIL"
                LblResult.ForeColor = Color.Red
                TestStatusMonitor.TestStatus = TestStatusMonitor.TestStatusEnum.TestFail
                Return
            End Try

            '保存图像至云端
            '  If UploadFileToFtp(localPath, imgRemotePath) = False Then Return
        Next


        For i As Integer = 0 To _dutSnLst.Count - 1
            '重置信息
            _utsApp.TestResult.ResetTestResult()

            '产线索引
            _utsApp.TestResult.ProductionLineID = -1

            '测试开始时间
            _utsApp.TestResult.StartTime = Now
            _utsApp.TestResult.DUT_SN = _dutSnLst(i)
            _utsApp.TestResult.TestResult = TestResult.TestResultEnum.Pass

            'Todo:自定义字段
            _utsApp.TestResult.AddCustomRecord("BoxCode", $"{_boxCode}")

            'todo:图像路径
            For j As Integer = 1 To _stationPlan.PictureCount
                _utsApp.TestResult.AddCustomRecord($"Image{j}", $"{ _imgList(j - 1).FileName}")
            Next

            Try
                '提交测试记录,缺省参数默认为False，True则测试记录唯一,覆盖相同条码记录
                _utsApp.CommitTestResult(True)

                TestStatusMonitor.TestStatus = TestStatusMonitor.TestStatusEnum.TestPass
            Catch ex As Exception
                ApplicationLog.WriteErrorLog($"录入图像信息失败：{ex.Message}")
                MsgBox($"录入图像信息失败：{ex.Message}")
                LblResult.Text = "FAIL"
                LblResult.ForeColor = Color.Red
                TestStatusMonitor.TestStatus = TestStatusMonitor.TestStatusEnum.TestFail
                Return
            End Try
        Next
    End Sub

    ''' <summary>
    ''' 填充测试记录内容，每个应用程序这个部分有所差异
    ''' </summary>
    Public Sub FillTestResult(dutSn As String)
        '重置信息
        _utsApp.TestResult.ResetTestResult()

        '产线索引
        _utsApp.TestResult.ProductionLineID = -1

        '测试开始时间
        _utsApp.TestResult.StartTime = Now
        _utsApp.TestResult.DUT_SN = dutSn
        _utsApp.TestResult.TestResult = TestResult.TestResultEnum.Pass

        'Todo:自定义字段
        _utsApp.TestResult.AddCustomRecord("BoxCode", $"{_boxCode}")

#If PRINT_FIRST = 0 Then
        'todo:图像路径
        For i As Integer = 1 To _stationPlan.PictureCount
            _utsApp.TestResult.AddCustomRecord($"Image{i}", $"{ _imgList(i - 1).FileName}")
        Next
#End If
    End Sub

    Private Function UploadFileToFtp(localPath As String, remotePath As String) As Boolean
        Try
            _ftp.FtpUpload(remotePath, localPath)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"上传图像[{localPath}]失败：{ex.Message}")
            MsgBox($"上传图像[{localPath}]失败：{ex.Message}")
            Return False
        End Try
        Return True
    End Function



    Private Sub BtnCommit_Click(sender As Object, e As EventArgs) Handles BtnCommit.Click
        SaveTestResult()
    End Sub

#Region "数据查询"

    Private Sub BtnSearch_Click(sender As Object, e As EventArgs) Handles BtnSearch.Click
        If CurrentRecordType = RecordTypes.Production Then
            _dutSn = TxtDevSn.Text
        Else
            _dutSn = TxtReworkSn.Text
        End If

        Try
            SearchRepairRecord(_dutSn)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"查询维修记录失败,原因：{ex.Message}")
            MsgBox($"查询维修记录失败,原因：{ex.Message}")
        End Try

    End Sub


    Private Sub SearchRepairRecord(sn As String)
        If _utsApp.ProcessStation Is Nothing Then
            MsgBox($"请先选择站位后再使用搜索功能")
            UpdateSearchResult(Color.OrangeRed, "站位未选择")
            Return
        End If

        If String.IsNullOrEmpty(sn) Then
            MsgBox($"条码不能为空，请扫码后重试")
            UpdateSearchResult(Color.OrangeRed, "条码为空")
            Return
        End If

        If _dutSnLst.Contains(sn) Then
            MsgBox($"条码与已录入重复，请确认后重试")
            Return
        End If

        If _barcodeIndex > _dutCount Then
            MsgBox($"超过条码录入上限{_dutCount},请提交后重试！")
            Return
        End If

        '获取SN总表中信息
        'Dim barcodeInfo As SnListResult = GetLocalBarcodeInfo(sn)’仅获取本地数据
        Dim barcodeInfo As SnListResult = GetBarcodeInfo2(sn) '获取两段数据，以最近更新时间作为依据
        If barcodeInfo Is Nothing Then
            MsgBox($"未查询到条码[{sn}]相关的信息")
            UpdateSearchResult(Color.Red, "无条码信息")
            Return
        End If

        '校验条码MO
        If CurrentRecordType = RecordTypes.Production AndAlso CboMoList.SelectedIndex >= 1 Then
            If moDic.ContainsKey(_mo) Then
                If barcodeInfo.OrderInternalID <> moDic(_mo) Then
                    '错误提示
                    If _stationPlan.CheckSnMO = StationPackagePlan.CheckStatus.Fail Then
                        MsgBox($"当前条码[{sn}]与选定MO不匹配,请切换条码")
                        Return
                    ElseIf _stationPlan.CheckSnMO = StationPackagePlan.CheckStatus.Lock Then
                        Dim msg As String = $"检测到与选定MO不匹配条码[{_dutSn}]"
                        WriteAppLockedToRegostry(1)
                        WriteLockedMsgToRegostry(msg)
                        ShowUnlockFrom(msg)
                    ElseIf _stationPlan.CheckSnMO = StationPackagePlan.CheckStatus.None Then
                        If MsgBox($"当前条码[{sn}]与选定MO不匹配,是否继续组装", MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then
                            UpdateSearchResult(Color.Blue, "MO不匹配产品组装")
                            Return
                        End If
                    End If
                End If
            Else
                '错误提示
                If _stationPlan.CheckSnMO = StationPackagePlan.CheckStatus.Fail Then
                    MsgBox($"当前条码[{sn}]与选定MO不匹配,请切换条码")
                    Return
                ElseIf _stationPlan.CheckSnMO = StationPackagePlan.CheckStatus.Lock Then

                    Dim msg As String = $"检测到与选定MO不匹配条码[{_dutSn}]"
                    WriteAppLockedToRegostry(1)
                    WriteLockedMsgToRegostry(msg)
                    ShowUnlockFrom(msg)
                ElseIf _stationPlan.CheckSnMO = StationPackagePlan.CheckStatus.None Then
                    If MsgBox($"当前条码[{sn}]与选定MO不匹配,是否继续组装", MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then
                        UpdateSearchResult(Color.Blue, "MO不匹配产品组装")
                        Return
                    End If
                End If
            End If
        End If

        '获取条码所属项目与站位信息
        Dim pInfo As New Project.ProjectInfo(_utsApp.Account.UserId, barcodeInfo.ProductID, Project.ProjectInfo.InitializeModeEnum.LocalDatabaseLoad)

        '临时取消产品类型检测
        'If pInfo.Index <> _utsApp.ProcessStation.ParentProject.Index Then
        '    MsgBox($"当前条码[{ sn}]所属产品[{pInfo.Name}]与当前站位产品[{_utsApp.ProcessStation.ParentProject.Name}]不匹配，无法录入")
        '    UpdateSearchResult(Color.Red, "站位不匹配")
        '    Return
        'End If

        Dim pTestLog As New ProductTestLog
        pTestLog.BarCode = sn
        pTestLog.ProjectIndex = barcodeInfo.ProductID
        pTestLog.ProjectName = pInfo.Name
        pTestLog.Result = True

        UpdateSearchResult(Color.Green, "已通过")

        '获取条码所有经过站位记录
        pTestLog.StationTestLogs.Clear()
        For sIndex As Integer = 0 To pInfo.Station.Count - 1
            Dim sSnOrder As Integer = pInfo.Station(sIndex).SnListOrder
            Dim sTestLog As New StationTestLog
            sTestLog.StationIndex = pInfo.Station(sIndex).StationID
            sTestLog.StationName = pInfo.Station(sIndex).Name
            sTestLog.TimeString = barcodeInfo.TestResults(sSnOrder - 1).TestTime
            sTestLog.Result = barcodeInfo.TestResults(sSnOrder - 1).TestResult

            '根据站位顺序判定是否允许条码录入
            If pInfo.Station(sIndex).ArtworkOrder < _utsApp.ProcessStation.ArtworkOrder Then
                If sTestLog.Result Is Nothing Then
                    If pTestLog.Result IsNot Nothing AndAlso pTestLog.Result = True Then
                        pTestLog.Result = sTestLog.Result
                        UpdateSearchResult(Color.Red, $"未测试:{sTestLog.StationName}")
                    End If
                ElseIf sTestLog.Result = False Then
                    If pTestLog.Result IsNot Nothing AndAlso pTestLog.Result = True Then
                        pTestLog.Result = sTestLog.Result
                        UpdateSearchResult(Color.Red, $"未通过:{sTestLog.StationName}")
                    End If
                End If
            ElseIf pInfo.Station(sIndex).ArtworkOrder = _utsApp.ProcessStation.ArtworkOrder Then
                If sTestLog.Result IsNot Nothing Then
                    If CurrentRecordType = RecordTypes.Production Then
                        If _stationPlan.CheckSnPackaged = StationPackagePlan.CheckStatus.Fail Then
                            MsgBox($"当前条码[{sn}]已参与过组装,请切换条码")
                            Return
                        ElseIf _stationPlan.CheckSnPackaged = StationPackagePlan.CheckStatus.Lock Then
                            Dim msg As String = $"检测到已组装条码[{_dutSn}]"
                            WriteAppLockedToRegostry(1)
                            WriteLockedMsgToRegostry(msg)
                            ShowUnlockFrom(msg)
                        ElseIf _stationPlan.CheckSnPackaged = StationPackagePlan.CheckStatus.None Then
                            If MsgBox($"当前条码[{sn}]已参与过组装,是否继续组装", MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then
                                UpdateSearchResult(Color.Blue, "已组装产品再组装")
                                Return
                            End If
                        End If
                    End If
                End If
            Else
                Exit For
            End If

            pTestLog.StationTestLogs.Add(sTestLog)
        Next

        '更新测试历史
        UpdateTestLog(pTestLog)

        If CurrentRecordType = RecordTypes.Production Then
            TxtDevSn.Focus()
            TxtDevSn.SelectAll()
        Else
            TxtReworkSn.Focus()
            TxtReworkSn.SelectAll()
        End If

    End Sub

    Enum SearchRrsults

        NoTest

        TestFail

        TestPass


    End Enum

    Private Sub UpdateSearchResult(cor As Color, txt As String)
        ' LblSearchResult.ForeColor = cor
        'LblSearchResult.Text = txt
    End Sub

    Private Function GetLocalBarcodeInfo(barcode As String) As SnListResult
        Dim dtLocal As DataTable
        Try
            dtLocal = DbConnector.GetLocalBarcode(barcode)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"查询条码本地信息失败,原因：{ex.Message}")
            Return Nothing
        End Try
        If dtLocal.Rows.Count = 0 Then Return Nothing


        Dim dtRow As DataRow = dtLocal(0)
        Dim bt As New SnListResult

        bt.BarCode = barcode
        bt.ProductID = CInt(dtRow($"{SnListTable.ColNames.ProductID}"))
        bt.CreateTime = CDate(dtRow($"{SnListTable.ColNames.CreateTime}"))
        bt.OrderInternalID = CInt(dtRow($"{SnListTable.ColNames.OrderInternalID}"))

        bt.TestResults.Clear()
        Dim testTime As String
        Dim testResult As Boolean?

        Dim localTestTime As Object
        Dim localTestResult As Object
        For stationIndex As Integer = 0 To 11
            localTestTime = dtRow($"S{stationIndex + 1}")
            If IsDBNull(localTestTime) Then
                testTime = Nothing
            Else
                testTime = CDate(localTestTime).ToString("yyyy-MM-dd HH:mm:ss")
            End If

            localTestResult = dtRow($"Result{stationIndex + 1}")
            If IsDBNull(localTestResult) Then
                testResult = Nothing
            Else
                testResult = CBool(localTestResult)
            End If

            bt.TestResults.Add(New TResult(testTime, testResult))
        Next

        Return bt
    End Function

    Private Function GetRemoteBarcodeInfo(barcode As String) As SnListResult
        Dim dtTable As DataTable
        Try
            dtTable = DbConnector.GetRemoteBarcode(barcode)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"查询条码远端信息失败,原因：{ex.Message}")
            Return Nothing
        End Try
        If dtTable.Rows.Count = 0 Then Return Nothing


        Dim dtRow As DataRow = dtTable(0)
        Dim bt As New SnListResult

        bt.BarCode = barcode
        bt.ProductID = CInt(dtRow($"{SnListTable.ColNames.ProductID}"))
        bt.CreateTime = CDate(dtRow($"{SnListTable.ColNames.CreateTime}"))
        bt.OrderInternalID = CInt(dtRow($"{SnListTable.ColNames.OrderInternalID}"))

        bt.TestResults.Clear()
        Dim testTime As String
        Dim testResult As Boolean?

        Dim localTestTime As Object
        Dim localTestResult As Object
        For stationIndex As Integer = 0 To 11
            localTestTime = dtRow($"S{stationIndex + 1}")
            If IsDBNull(localTestTime) Then
                testTime = Nothing
            Else
                testTime = CDate(localTestTime).ToString("yyyy-MM-dd HH:mm:ss")
            End If

            localTestResult = dtRow($"Result{stationIndex + 1}")
            If IsDBNull(localTestResult) Then
                testResult = Nothing
            Else
                testResult = CBool(localTestResult)
            End If

            bt.TestResults.Add(New TResult(testTime, testResult))
        Next

        Return bt
    End Function


    Private Function GetBarcodeInfo2(barcode As String) As SnListResult
        Dim dt As SnListResult

        Dim remoteResult As SnListResult = GetRemoteBarcodeInfo(barcode)
        Dim localResult As SnListResult = GetLocalBarcodeInfo(barcode)

        If remoteResult Is Nothing Then
            dt = localResult
        ElseIf localResult Is Nothing Then
            dt = remoteResult
        Else
            dt = localResult

            '遍历对比时间与结果,采用最新的时间与结果(时间格式待确定)
            For i As Integer = 0 To localResult.TestResults.Count - 1
                If String.IsNullOrEmpty(remoteResult.TestResults(i).TestTime) Then
                    dt.TestResults(i).TestTime = localResult.TestResults(i).TestTime
                    dt.TestResults(i).TestResult = localResult.TestResults(i).TestResult
                ElseIf String.IsNullOrEmpty(localResult.TestResults(i).TestTime) Then
                    dt.TestResults(i).TestTime = remoteResult.TestResults(i).TestTime
                    dt.TestResults(i).TestResult = remoteResult.TestResults(i).TestResult
                Else
                    If localResult.TestResults(i).TestTime >= remoteResult.TestResults(i).TestTime Then
                        dt.TestResults(i).TestTime = localResult.TestResults(i).TestTime
                        dt.TestResults(i).TestResult = localResult.TestResults(i).TestResult
                    Else
                        dt.TestResults(i).TestTime = remoteResult.TestResults(i).TestTime
                        dt.TestResults(i).TestResult = remoteResult.TestResults(i).TestResult
                    End If
                End If
            Next
        End If

        Return dt
    End Function

    Private Sub UpdateTestLog(pTestLog As ProductTestLog)
        TvwTestLog.Nodes.Clear()
        TvwTestLog.ExpandAll()

        Dim pText As String = $"{pTestLog.ProjectName}:{pTestLog.BarCode} "
        Dim pNode As TreeNode = TvwTestLog.Nodes.Add(pText)

        Dim row As Integer
        If _inputFileds.ContainsKey($"barcode{_barcodeIndex}") Then
            row = _inputFileds($"barcode{_barcodeIndex}")
        Else
            MsgBox("模板信息有误，请联系管理员!")
            Return
        End If

        Dim f As FiledLocation
        If _tempFileds.ContainsKey($"barcode{_barcodeIndex}") Then
            f = _tempFileds($"barcode{_barcodeIndex}")
        Else
            MsgBox("模板信息有误，请联系管理员!")
            Return
        End If


        If pTestLog.Result Is Nothing Then
            pNode.Text &= "NoTest"
            pNode.ForeColor = Color.Gray

            GrdInput.Cell(row, ColNames.Value).Text = _dutSn
            GrdInput.Cell(row, ColNames.Result).Text = "NoTest"
            GrdInput.Cell(row, ColNames.Result).ForeColor = Color.Gray

            If _stationPlan.CheckSnTested = StationPackagePlan.CheckStatus.Fail Then
                MsgBox($"当前条码[{_dutSn}]未测试，请重新录入条码！")
                Return
            ElseIf _stationPlan.CheckSnTested = StationPackagePlan.CheckStatus.Lock Then
                Dim msg As String = $"检测到未测试条码[{_dutSn}]"
                WriteAppLockedToRegostry(1)
                WriteLockedMsgToRegostry(msg)
                ShowUnlockFrom(msg)
            ElseIf _stationPlan.CheckSnTested = StationPackagePlan.CheckStatus.None Then
                If MsgBox($"当前条码[{_dutSn}]未测试,是否继续组装", MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then
                    UpdateSearchResult(Color.Blue, "未测试产品组装")
                    Return
                End If
            End If
        ElseIf pTestLog.Result Then
            pNode.Text &= pTestLog.Result
            pNode.ForeColor = Color.Green

            If _barcodeIndex = 1 Then
                InitInputInfo()
                BtnCommit.Enabled = True '2022-01-08 V1.2 Momo 录入成功后锁定按钮，防止重复提交,只有新录入时才解锁
            End If
            _dutSnLst.Add(_dutSn)

            GrdInput.Cell(row, ColNames.Value).Text = _dutSn
            GrdInput.Cell(row, ColNames.Result).Text = "Pass"
            GrdInput.Cell(row, ColNames.Result).ForeColor = Color.Green

            '更新打印列表
            GrdPriview.Cell(f.Row, f.Col).Text = _dutSn
            _barcodeIndex += 1
        Else
            pNode.Text &= pTestLog.Result
            pNode.ForeColor = Color.Red

            GrdInput.Cell(row, ColNames.Value).Text = _dutSn
            GrdInput.Cell(row, ColNames.Result).Text = "Fail"
            GrdInput.Cell(row, ColNames.Result).ForeColor = Color.Red

            If _stationPlan.CheckSnTested = StationPackagePlan.CheckStatus.Fail Then
                MsgBox($"当前条码[{_dutSn}]未通过测试，请重新录入条码！")
                Return
            ElseIf _stationPlan.CheckSnTested = StationPackagePlan.CheckStatus.Lock Then
                ' MsgBox($"检测到未通过测试条码[{_dutSn}]，产品已锁定，请联系管理员！")
                Dim msg As String = $"检测到未通过测试条码[{_dutSn}]"
                WriteAppLockedToRegostry(1)
                WriteLockedMsgToRegostry(msg)
                ShowUnlockFrom(msg)
            ElseIf _stationPlan.CheckSnTested = StationPackagePlan.CheckStatus.None Then
                If MsgBox($"当前条码[{_dutSn}]未通过测试,是否继续组装", MsgBoxStyle.OkCancel) = MsgBoxResult.Cancel Then
                    UpdateSearchResult(Color.Blue, "未通过测试产品组装")
                    Return
                End If
            End If
        End If


        For Each sTestLog As StationTestLog In pTestLog.StationTestLogs
            Dim sNode As TreeNode
            If sTestLog.Result Is Nothing Then
                sNode = pNode.Nodes.Add($"{sTestLog.StationName}:NoTest")
                sNode.ForeColor = Color.Gray

            ElseIf sTestLog.Result Then
                sNode = pNode.Nodes.Add($"{sTestLog.StationName}:Pass {sTestLog.TimeString}")
                sNode.ForeColor = Color.Green
            Else
                sNode = pNode.Nodes.Add($"{sTestLog.StationName}:Fail {sTestLog.TimeString}")
                sNode.ForeColor = Color.Red
            End If


            For Each bTestLog As BarcodeTestLog In sTestLog.BarcodeTestLogs
                Dim bNode As TreeNode
                If bTestLog.Result Is Nothing Then
                    bNode = sNode.Nodes.Add($"{bTestLog.TimeString}")
                    bNode.ForeColor = Color.Gray
                ElseIf bTestLog.Result Then
                    bNode = sNode.Nodes.Add($"{bTestLog.TimeString}  Pass")
                    bNode.ForeColor = Color.Green
                Else
                    bNode = sNode.Nodes.Add($"{bTestLog.TimeString}  Fail")
                    bNode.ForeColor = Color.Red
                End If

                For Each filed As KeyValuePair(Of String, String) In bTestLog.Fileds
                    bNode.Nodes.Add($"{filed.Key} : {filed.Value}")
                Next
                bNode.Collapse()
            Next
            sNode.Expand()
        Next
        pNode.Expand()
    End Sub



    Public Class SnListResult

        Sub New()
            TestResults = New List(Of TResult)()
        End Sub

        Public Property ProductID() As Integer
        Public Property OrderInternalID() As Integer

        Public Property BarCode() As String

        Public Property CreateTime() As DateTime

        Public Property TestResults() As List(Of TResult)

    End Class


    Public Class TResult
        Sub New(time As String, result As Boolean?)
            TestTime = time
            TestResult = result
        End Sub

        Public Property TestTime As String

        Public Property TestResult() As Boolean?
    End Class




    Public Class ProductTestLog
        Sub New()
            ProjectIndex = -1
            Result = True
            StationTestLogs = New List(Of StationTestLog)
        End Sub

        Public ProjectIndex As Integer

        Public ProjectName As String

        Public BarCode As String

        Public Result As Boolean?

        Public StationTestLogs As List(Of StationTestLog)
    End Class


    Public Class StationTestLog
        Sub New()
            StationIndex = -1
            BarcodeTestLogs = New List(Of BarcodeTestLog)
        End Sub

        Public StationIndex As Integer

        Public StationName As String

        Public TimeString As String

        Public Result As Boolean?

        Public BarcodeTestLogs As List(Of BarcodeTestLog)
    End Class

    Public Class BarcodeTestLog
        Sub New()
            ErrorCode = String.Empty
            TimeString = String.Empty
            Fileds = New Dictionary(Of String, String)
        End Sub

        Public ErrorCode As String

        Public TimeString As String

        Public Result As Boolean?

        Public Fileds As Dictionary(Of String, String)
    End Class
#End Region


#Region "条码列表"
    ''' <summary>
    ''' 当前条码索引
    ''' </summary>
    Private _barcodeIndex As Integer

    Enum ColNames
        Sn
        Item
        Value
        Result
        Max
    End Enum

    Private Sub InitBarcodeGrid(Optional stationPlan As StationPackagePlan = Nothing)
        With GrdInput
            .AutoRedraw = False

            .NewFile()
            .BorderStyle = FlexCell.BorderStyleEnum.None

            .Rows = 1
            .Cols = ColNames.Max

            .ExtendLastCol = True
            .DisplayRowNumber = True

            .Cell(0, ColNames.Item).Text = "Item"
            .Cell(0, ColNames.Value).Text = "Value"
            .Cell(0, ColNames.Result).Text = "Result"

            .DefaultRowHeight = 20

            .Column(ColNames.Item).Width = 80
            .Column(ColNames.Value).Width = 160

            .AddItem("BoxNum")

            _inputFileds = New Dictionary(Of String, Integer)
            _inputFileds.Add($"boxnum", .Rows - 1)
            If stationPlan IsNot Nothing Then
                _dutCount = 0
                _boxCode = GetBoxCode()

                .Cell(.Rows - 1, ColNames.Value).Text = _boxCode
                .Cell(.Rows - 1, ColNames.Result).Text = "Pass"
                .Cell(.Rows - 1, ColNames.Result).ForeColor = Color.Green

                '遍历变量总数
                Dim tmpGrd As New FlexCell.Grid

                Dim tmpPath As String = $"{UtsPath.StationPacketResourceDirPath}\{stationPlan.TemplateFile}"

                If IO.File.Exists(tmpPath) Then
                    tmpGrd.OpenFile(tmpPath)

                    GrdPriview.OpenFile(tmpPath)
                    GrdPriview.BorderStyle = FlexCell.BorderStyleEnum.None
                    GrdPriview.Locked = True
                    GrdPriview.HideGridLines = True
                    GrdPriview.Range(0, 0, GrdPriview.Rows - 1, GrdPriview.Cols - 1).BackColor = Color.White

                    _tempFileds = New Dictionary(Of String, FiledLocation)
                    Dim cellText As String
                    Dim filed As String
                    For row As Integer = 1 To tmpGrd.Rows - 1
                        For col As Integer = 1 To tmpGrd.Cols - 1
                            cellText = tmpGrd.Cell(row, col).Text.Trim
                            If String.IsNullOrEmpty(cellText) Then Continue For
                            If cellText.StartsWith("{") And cellText.EndsWith("}") Then
                                filed = cellText.Substring(1, cellText.Length - 2).Trim.ToLower
                                If String.IsNullOrEmpty(filed) Then Continue For

                                Dim tmpstr() As String = filed.Split(New Char() {":"c}, StringSplitOptions.RemoveEmptyEntries)
                                Select Case tmpstr.Length
                                    Case 1
                                        If _tempFileds.ContainsKey(tmpstr(0)) = False Then
                                            _tempFileds.Add(tmpstr(0), New FiledLocation(row, col, tmpstr(0)))
                                            GrdPriview.Cell(row, col).Text = ""
                                        End If

                                        If _inputFileds.ContainsKey(tmpstr(0)) = False Then
                                            .AddItem(tmpstr(0))
                                            _inputFileds.Add(tmpstr(0), .Rows - 1)
                                            If tmpstr(0).ToLower.StartsWith("barcode") Then _dutCount += 1
                                        End If
                                    Case 2
                                        Dim len As Integer = -1
                                        If _tempFileds.ContainsKey(tmpstr(0)) = False Then
                                            If Integer.TryParse(tmpstr(1), len) Then
                                                _tempFileds.Add(tmpstr(0), New FiledLocation(row, col, tmpstr(0), len))
                                            Else
                                                _tempFileds.Add(tmpstr(0), New FiledLocation(row, col, tmpstr(0)))
                                            End If
                                            GrdPriview.Cell(row, col).Text = ""
                                        End If

                                        If _inputFileds.ContainsKey(tmpstr(0)) = False Then
                                            .AddItem(tmpstr(0))
                                            _inputFileds.Add(tmpstr(0), .Rows - 1)
                                            If tmpstr(0).ToLower.StartsWith("barcode") Then _dutCount += 1
                                        End If
                                    Case Else
                                        Console.WriteLine($"filed:{filed}")
                                End Select
                            End If
                        Next
                    Next

                    If _tempFileds.ContainsKey("boxnum") Then
                        GrdPriview.Cell(_tempFileds("boxnum").Row, _tempFileds("boxnum").Col).Text = _boxCode
                    End If
                Else
                    Throw New Exception("无模板文件,请联系管理员")
                End If


                '遍历图像总数
                For i As Integer = 1 To stationPlan.PictureCount
                    .AddItem($"image{i}")
                    _inputFileds.Add($"image{i}", .Rows - 1)
                    .Row(.Rows - 1).Height = 60
                Next

            End If

            GrdInput.Locked = True

            .AutoRedraw = True
            .Refresh()
        End With

        _barcodeIndex = 1
    End Sub


    Public Class FiledLocation
        Sub New(r As Integer, c As Integer, name As String, Optional len As Integer = -1)
            Row = r
            Col = c
            FiledName = name
            DestLength = len
        End Sub

        Public Row As Integer

        Public Col As Integer

        Public FiledName As String

        Public DestLength As Integer
    End Class

    Private Sub AddBarCode(code As String, result As String)
        With GrdInput
            If _barcodeIndex >= .Cols Then
                For i As Integer = _barcodeIndex To .Cols
                    .AddItem("")
                Next
            End If

            .Cell(_barcodeIndex, ColNames.Value).Text = code
            .Cell(_barcodeIndex, ColNames.Result).Text = result
        End With
    End Sub
#End Region


    Private Sub WriteBoxNumToRegostry(num As Integer)
        Try
            Microsoft.Win32.Registry.LocalMachine.CreateSubKey($"software\AUTS").SetValue("BoxNum", num, Microsoft.Win32.RegistryValueKind.String)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"保存箱号至注册表失败,原因：{ex.Message}")
            MsgBox($"保存箱号至注册表失败,原因：{ex.Message}")
        End Try
    End Sub

    Private Function ReadBoxNumFromRegostry() As Integer
        Dim num As Integer = 0

        Try
            Integer.TryParse(Microsoft.Win32.Registry.LocalMachine.OpenSubKey($"software\AUTS").GetValue("BoxNum", "0").ToString, num)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"读取注册表箱号失败,原因：{ex.Message}")
            MsgBox($"读取注册表箱号失败,原因：{ex.Message}")
        End Try
        Return num
    End Function

    Private Sub WriteAppLockedToRegostry(num As Integer)
        Try
            Microsoft.Win32.Registry.LocalMachine.CreateSubKey($"software\AUTS").SetValue("AppLocked", num, Microsoft.Win32.RegistryValueKind.String)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"保存加锁状态失败,原因：{ex.Message}")
            MsgBox($"保存加锁状态失败,原因：{ex.Message}")
        End Try
    End Sub

    Private Function ReadAppLockedFromRegostry() As Integer
        Dim num As Integer = 0

        Try
            Integer.TryParse(Microsoft.Win32.Registry.LocalMachine.OpenSubKey($"software\AUTS").GetValue("AppLocked", 0).ToString, num)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"读取加锁状态失败,原因：{ex.Message}")
            MsgBox($"读取加锁状态失败,原因：{ex.Message}")
        End Try
        Return num
    End Function


    Private Sub WriteLockedMsgToRegostry(str As String)
        Try
            Microsoft.Win32.Registry.LocalMachine.CreateSubKey($"software\AUTS").SetValue("LockedMsg", str, Microsoft.Win32.RegistryValueKind.String)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"写入加锁信息失败,原因：{ex.Message}")
            MsgBox($"写入加锁信息失败,原因：{ex.Message}")
        End Try
    End Sub


    Private Function ReadLockedMsgFromRegostry() As String
        Dim msg As String = ""

        Try
            msg = Microsoft.Win32.Registry.LocalMachine.OpenSubKey($"software\AUTS").GetValue("LockedMsg", "").ToString
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"读取加锁信息失败,原因：{ex.Message}")
            MsgBox($"读取加锁信息失败,原因：{ex.Message}")
        End Try
        Return msg
    End Function



    ''' <summary>
    ''' 替换测试命令参数中的变量(变量格式：{var})
    ''' </summary>
    ''' <returns></returns>
    Private Function GetBoxCode() As String
        Dim strBuilder As New StringBuilder
        Dim varName As New StringBuilder
        Dim findVar As Boolean
        Dim findDsc As Boolean

        Dim dec As New StringBuilder
        If _stationPlan Is Nothing Then Return ""
        If String.IsNullOrEmpty(_stationPlan.BoxNumText) Then Return ""

        For Each c As Char In _stationPlan.BoxNumText
            If c = "{"c Then
                If findVar Then
                    findVar = False
                    strBuilder.Append("{")
                Else
                    findVar = True
                End If
            ElseIf c = "}"c Then
                If findVar Then
                    strBuilder.Append(ReplaceVar(varName.ToString(), dec.ToString()))
                    varName.Clear()
                    dec.Clear()
                    findVar = False
                    findDsc = False
                Else
                    strBuilder.Append("}")
                End If
            ElseIf c = ":" Then
                If findVar Then
                    findDsc = True
                Else
                    strBuilder.Append(c)
                End If
            Else
                If findVar Then
                    If findDsc Then
                        dec.Append(c)
                    Else
                        varName.Append(c)
                    End If
                Else
                    strBuilder.Append(c)
                End If
            End If
        Next

        Return strBuilder.ToString
    End Function

    ''' <summary>
    ''' 从测试记录中或则全局变量中获取指定变量名的变量值
    ''' </summary>
    ''' <param name="varName"></param>
    ''' <returns></returns>
    Private Function ReplaceVar(varName As String, dsc As String) As String
        varName = varName.ToLower
        dsc = dsc.ToLower

        Dim result As String = ""
        Dim i As Integer

        Select Case varName
            Case "mo"
                If Integer.TryParse(dsc, i) Then
                    result = _mo.PadLeft(i, "0"c)
                Else
                    result = _mo
                End If
            Case "po"
                If Integer.TryParse(dsc, i) Then
                    result = _po.PadRight(i, "0"c)
                Else
                    result = _po
                End If
            Case "year"
                If Integer.TryParse(dsc, i) Then
                    If i = 2 Then
                        result = Now.ToString("yy")
                    Else
                        result = Now.ToString("yyyy")
                    End If
                Else
                    result = Now.ToString("yyyy")
                End If
            Case "month"
                If Integer.TryParse(dsc, i) Then
                    result = Now.ToString("MM")
                Else
                    If dsc = "en" Then
                        result = Now.ToString("MMM", CultureInfo.GetCultureInfo("en-US"))
                    ElseIf dsc = "cn" Then
                        result = Now.ToString("MMM", CultureInfo.GetCultureInfo("zh-CN"))
                    Else
                        result = Now.ToString("MM")
                    End If
                End If
            Case "day"
                result = Now.ToString("dd")
            Case "count"
                If Integer.TryParse(dsc, i) Then
                    result = _boxNum.ToString.PadLeft(i, "0"c)
                Else
                    result = _boxNum.ToString
                End If
            Case Else
                MsgBox($"未知的字段名：{varName},为确保软件正常运行，请联系管理员")
        End Select

        Return result
    End Function

#Region "拍照"
    ''' <summary>
    ''' 摄像头持续抓取图片标志位
    ''' </summary>
    Private _useCamera As Boolean

    ''' <summary>
    ''' 摄像头对象
    ''' </summary>
    Private _camera As VideoCapture

    ''' <summary>
    ''' 截图标志位
    ''' </summary>
    Private _stop As Boolean

    ''' <summary>
    ''' 当前操作图像索引,从1开始
    ''' </summary>
    Private _imageIndex As Integer

    ''' <summary>
    ''' 窗体加载完成
    ''' </summary>
    Private _frmShowed As Boolean

    Private Sub FrmStationTest_Shown(sender As Object, e As EventArgs) Handles Me.Shown
        _imageIndex = 1
        _useCamera = True
        ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf OpenVideoThread), 0)

        If ReadAppLockedFromRegostry() <> 0 Then
            ShowUnlockFrom(ReadLockedMsgFromRegostry)
        End If

        _frmShowed = True
    End Sub

    Private Sub ShowUnlockFrom(Optional str As String = "")
        Dim tipString As String

        If String.IsNullOrEmpty(str) Then
            tipString = "请输入解除冻结密码"
        Else
            tipString = $"由于[{str}],请输入解除冻结密码"
        End If

        Dim pwd As String = UtsInputBox.ShowDialog(tipString, $"冻结解锁", "", True)

        If pwd Is Nothing Then
            ShowUnlockFrom(str)
        Else
            If _stationPlan Is Nothing Then
                If String.Compare(pwd, "admin", True) = 0 Then
                    WriteAppLockedToRegostry(0)
                    WriteLockedMsgToRegostry("")
                Else
                    ShowUnlockFrom(str)
                End If
            Else
                If String.Compare(pwd, _stationPlan.UnlockKey, True) = 0 Then
                    WriteAppLockedToRegostry(0)
                    WriteLockedMsgToRegostry("")
                Else
                    ShowUnlockFrom(str)
                End If
            End If
        End If
    End Sub


    ''' <summary>
    ''' 打开摄像头显示图像
    ''' </summary>
    Private Sub OpenVideoThread(state As Object)
        While _useCamera
            Thread.Sleep(10)

            If _camera Is Nothing Then
                UpdateCameraStatus(False)
                _camera = New VideoCapture(0)       '打开默认的相机使用默认为0

                '摄像头为4:3
                _camera.FrameWidth = 1024
                _camera.FrameHeight = 768

                _camera.Fps = 30 '采集率FTP

                If _camera.IsOpened() = False Then
                    Thread.Sleep(1000)
                    Continue While
                End If
            End If

            Using src As New Mat
                If _camera.Read(src) = False Then
                    _camera.Release()
                    _camera.Dispose()
                    _camera = Nothing
                    UpdateCameraStatus(False)
                    Continue While
                End If

                UpdateCameraStatus(True)
                PicBox.Image = src.ToBitmap

                If _stop Then
                    AddImage(_imageIndex, src.ToBitmap)
                    _imageIndex += 1

                    If _imageIndex > _stationPlan.PictureCount Then
#If PRINT_FIRST = 1 Then
                        '提交信息
                        SaveImage()
#End If
                        _imageIndex = 1
                    Else
                        TestStatusMonitor.TestStatus = TestStatusMonitor.TestStatusEnum.Testing
                    End If

                    _stop = False
                End If
            End Using

            GC.Collect()
        End While
    End Sub


    Private Sub AddImage(index As Integer, img As Image)
        Dim imgKey As String = $"{_boxCode}_{Now:yyyyMMdd_HHmmss}_{index}.jpg"
        GrdInput.Images.Add(img, imgKey)

        '查询当前索引是否已经存在
        Dim findImage As Boolean
        For i As Integer = 0 To _imgList.Count - 1
            If _imgList(i).Index = index Then
                _imgList(i).FileName = imgKey
                _imgList(i).InputImage = img
                findImage = True
            End If
        Next
        If findImage = False Then
            _imgList.Add(New InputImage(index, imgKey, img))
        End If

        If _inputFileds.ContainsKey($"image{index}") Then
            GrdInput.Cell(_inputFileds($"image{index}"), ColNames.Value).SetImage(imgKey)
            GrdInput.Cell(_inputFileds($"image{index}"), ColNames.Result).Text = "Pass"
            GrdInput.Cell(_inputFileds($"image{index}"), ColNames.Result).ForeColor = Color.Green
        Else
            MsgBox($"图像索引[{index}]超过预期值{_stationPlan.PictureCount}")
        End If
    End Sub


    Private Sub UpdateCameraStatus(connected As Boolean)
        Static status As Boolean = False
        If status = connected Then Return

        If InvokeRequired Then
            Invoke(New Action(Sub()
                                  If connected Then
                                      TsLblCameraStatus.Text = "摄像头已连接"
                                      TsLblCameraStatus.ForeColor = Color.Green
                                  Else
                                      TsLblCameraStatus.Text = "摄像头未连接"
                                      TsLblCameraStatus.ForeColor = Color.Red
                                  End If
                              End Sub))
        Else
            If connected Then
                TsLblCameraStatus.Text = "摄像头已连接"
                TsLblCameraStatus.ForeColor = Color.Green
            Else
                TsLblCameraStatus.Text = "摄像头未连接"
                TsLblCameraStatus.ForeColor = Color.Red
            End If
        End If

    End Sub


    Private Sub PicBox_DoubleClick(sender As Object, e As EventArgs) Handles PicBox.DoubleClick
        If _stationPlan Is Nothing Then
            MsgBox("请选择有效站位后重试")
            Return
        End If

        If _camera Is Nothing Then
            MsgBox("请确保摄像头能正常连接后重试")
            Return
        End If

        _stop = True
    End Sub


    Private _imgList As New List(Of InputImage)

    Public Class InputImage
        Public Property InputImage As Image

        Public Property Index As Integer

        Public Property FileName As String


        Sub New(idx As Integer, name As String, img As Image)
            Index = idx
            FileName = name
            InputImage = img
        End Sub
    End Class

    Private Sub BtnPrint_Click(sender As Object, e As EventArgs) Handles BtnPrint.Click
        GrdPriview.Print()

        'PDF备份
        'GrdPriview.ExportToPDF($"{Application.StartupPath}\PrintPDF\{_boxCode}.pdf")
        'GrdPriview.ExportToExcel($"{Application.StartupPath}\PrintPDF\{_boxCode}.xls")
    End Sub

    Private Sub BtnPrintPreview_Click(sender As Object, e As EventArgs) Handles BtnPrintPreview.Click
        GrdPriview.PrintPreview()
    End Sub

    Private Sub BtnStartEdit_Click(sender As Object, e As EventArgs) Handles BtnStartEdit.Click
        Static failCount As Integer = 1

        If NudBoxNum.Enabled = False Then
            If _stationPlan Is Nothing Then
                UtsMsgBox.ShowDialog("请选择项目后再解锁编辑功能！")
                Return
            End If

            Dim pwd As String = UtsInputBox.ShowDialog("请输入编辑密码", $"第{failCount}次编辑解锁", "", True)

            If pwd Is Nothing Then Return
            If String.Compare(pwd, _stationPlan.BoxMumEditKey, True) = 0 Then
                ApplicationLog.WriteInfoLog($"编辑箱号功能已解锁。")

                failCount = 0
                BtnStartEdit.Text = "编辑加锁"
                NudBoxNum.Enabled = True
            Else
                failCount += 1
                ApplicationLog.WriteWarningLog($"编辑箱号功能第[{failCount}]次解锁失败。")
                If failCount > 3 Then
                    ApplicationLog.WriteFatalLog($"编辑箱号功能第[{failCount}]次解锁失败，程序关闭。")
                    Application.Exit()
                End If
            End If
        Else
            If UtsMsgBox.ShowDialog("为防止误操作，请确定关闭编辑功能！", UtsMsgBox.UtsMsgBoxTypeEnum.YesNo) = DialogResult.OK Then
                ApplicationLog.WriteInfoLog($"编辑箱号功能已加锁")

                BtnStartEdit.Text = "编辑解锁"
                NudBoxNum.Enabled = False
            End If
        End If
    End Sub


    Private Sub NudBoxNum_ValueChanged(sender As Object, e As EventArgs) Handles NudBoxNum.ValueChanged, BtnReBox.Click
        If CurrentRecordType = RecordTypes.Rework Then
            Try
                _boxNum = CInt(TxtReworkBoxNum.Text)
            Catch ex As Exception
                ApplicationLog.WriteErrorLog($"箱号格式错误,原因：{ex.Message}")
                MsgBox($"箱号输入格式错误!")
                Return
            End Try
        Else
            _boxNum = CInt(NudBoxNum.Value)
            WriteBoxNumToRegostry(_boxNum)
            ApplicationLog.WriteInfoLog($"箱号变化，当前箱号：{_boxNum}")
        End If

        '更新箱号
        _boxCode = GetBoxCode()
        Dim r As Integer = _inputFileds("boxnum")
        GrdInput.Cell(r, ColNames.Value).Text = _boxCode
        GrdInput.Cell(r, ColNames.Result).Text = "Pass"
        GrdInput.Cell(r, ColNames.Result).ForeColor = Color.Green

        If _tempFileds.ContainsKey("boxnum") Then
            GrdPriview.Cell(_tempFileds("boxnum").Row, _tempFileds("boxnum").Col).Text = _boxCode
        End If
    End Sub


    Private Sub TxtDevSn_KeyDown(sender As Object, e As KeyEventArgs) Handles TxtDevSn.KeyDown
        If e.KeyCode = Keys.Enter Then
            _dutSn = TxtDevSn.Text
            Try
                SearchRepairRecord(_dutSn)
            Catch ex As Exception
                ApplicationLog.WriteErrorLog($"查询产品测试信息失败,原因：{ex.Message}")
                MsgBox($"查询产品测试信息失败,原因：{ex.Message}")
            End Try

            TxtDevSn.Focus()
            TxtDevSn.SelectAll()
        End If
    End Sub


    Private Sub CboMoList_SelectedIndexChanged(sender As Object, e As EventArgs) Handles CboMoList.SelectedIndexChanged
        If CboMoList.SelectedIndex < 0 Then Return
        _mo = CboMoList.Items(CboMoList.SelectedIndex).ToString
    End Sub


    Private Sub BtnClear_Click(sender As Object, e As EventArgs) Handles BtnClear.Click
        ApplicationLog.WriteInfoLog("清除已有录入信息。")

        '录入成功后处理
        _barcodeIndex = 1
        _dutSnLst.Clear()

        If _barcodeIndex = 1 Then InitInputInfo()

        If CurrentRecordType = RecordTypes.Production Then
            TxtDevSn.Focus()
            TxtDevSn.SelectAll()
        Else
            TxtReworkBoxNum.Focus()
            TxtReworkBoxNum.SelectAll()
        End If
    End Sub


    Private Sub BtnReSn_Click(sender As Object, e As EventArgs) Handles BtnReSn.Click
        _dutSn = TxtReworkSn.Text
        Try
            SearchRepairRecord(_dutSn)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"返修查询产品测试信息失败,原因：{ex.Message}")
            MsgBox($"返修查询产品测试信息失败,原因：{ex.Message}")
        End Try
    End Sub

    Private Sub TxtReworkBoxNum_KeyDown(sender As Object, e As KeyEventArgs) Handles TxtReworkBoxNum.KeyDown
        If e.KeyCode <> Keys.Enter Then Return
        If CurrentRecordType <> RecordTypes.Rework Then Return
        Try
            _boxNum = CInt(TxtReworkBoxNum.Text)
        Catch ex As Exception
            ApplicationLog.WriteErrorLog($"返修箱号格式错误,原因：{ex.Message}")
            MsgBox($"返修箱号输入格式错误!")
            Return
        End Try

        '更新箱号
        _boxCode = GetBoxCode()
        Dim r As Integer = _inputFileds("boxnum")
        GrdInput.Cell(r, ColNames.Value).Text = _boxCode
        GrdInput.Cell(r, ColNames.Result).Text = "Pass"
        GrdInput.Cell(r, ColNames.Result).ForeColor = Color.Green

        If _tempFileds.ContainsKey("boxnum") Then
            GrdPriview.Cell(_tempFileds("boxnum").Row, _tempFileds("boxnum").Col).Text = _boxCode
        End If
    End Sub

    Private Sub tb_ReworkSn_KeyDown(sender As Object, e As KeyEventArgs) Handles TxtReworkSn.KeyDown
        If e.KeyCode = Keys.Enter Then
            _dutSn = TxtReworkSn.Text
            Try
                SearchRepairRecord(_dutSn)
            Catch ex As Exception
                ApplicationLog.WriteErrorLog($"返修查询产品测试信息失败,原因：{ex.Message}")
                MsgBox($"返修查询产品测试信息失败,原因：{ex.Message}")
            End Try

            TxtReworkSn.Focus()
            TxtReworkSn.SelectAll()
        End If
    End Sub

    Private Sub RdoMassProduction_CheckedChanged(sender As Object, e As EventArgs) Handles RdoMassProduction.CheckedChanged
        If RdoMassProduction.Checked = False Then Return
        CurrentRecordType = RecordTypes.Production
        TabControl1.SelectedIndex = CurrentRecordType
    End Sub


    Private Sub RdoRework_CheckedChanged(sender As Object, e As EventArgs) Handles RdoRework.CheckedChanged
        If RdoRework.Checked = False Then Return

        Dim pwd As String = UtsInputBox.ShowDialog("请输入编辑密码", $"编辑解锁", "", True)

        If pwd Is Nothing Then
            RdoMassProduction.Checked = True
            Return
        End If

        If String.Compare(pwd, _stationPlan.BoxMumEditKey, True) <> 0 Then
            RdoMassProduction.Checked = True
            Return
        End If

        ApplicationLog.WriteInfoLog("返修功能已解锁。")

        CurrentRecordType = RecordTypes.Rework
        TabControl1.SelectedIndex = CurrentRecordType
    End Sub


    Private Sub TabControl1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles TabControl1.SelectedIndexChanged
        If _frmShowed = False Then Return

        Select Case CurrentRecordType
            Case RecordTypes.Production
                ApplicationLog.WriteInfoLog("功能模式变更,模式：量产")
                TxtDevSn.Text = ""
                _boxNum = CInt(NudBoxNum.Value)
                BtnClear_Click(Nothing, Nothing)
            Case RecordTypes.Rework
                ApplicationLog.WriteInfoLog("功能模式变更,模式：返修")
                TxtReworkBoxNum.Text = ""
                TxtReworkSn.Text = ""
                If Integer.TryParse(TxtReworkBoxNum.Text, _boxNum) = False Then
                    _boxNum = 0
                End If
                BtnClear_Click(Nothing, Nothing)
        End Select

    End Sub

#End Region
End Class
