1
0

3 Commits d26fb9b201 ... 467c66abff

Autor SHA1 Mensagem Data
  xj 467c66abff 修复Bug: 1. 作业按钮不刷新内容 2. 只有一个任务时显示问题 3. 取消"取消"按钮 há 3 meses atrás
  xj 1b2da4fbd0 Merge branch 'dev_qt5' of http://192.168.0.253:3000/xj/ISCS_LOTO_Linux into dev_qt5 há 3 meses atrás
  xj 8d0be2dd4f 1. 修复退出登录计时器Bug há 3 meses atrás

+ 215 - 82
Loto.pro.user

@@ -1,20 +1,19 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 18.0.2, 2026-01-29T02:52:57. -->
 <qtcreator>
 <qtcreator>
  <data>
  <data>
   <variable>EnvironmentId</variable>
   <variable>EnvironmentId</variable>
-  <value type="QByteArray">{a5587603-485e-486a-a1a9-dc3454e0b3d3}</value>
+  <value type="QByteArray">{a22e3eca-8c48-4235-becd-e90a9241f53a}</value>
  </data>
  </data>
  <data>
  <data>
   <variable>ProjectExplorer.Project.ActiveTarget</variable>
   <variable>ProjectExplorer.Project.ActiveTarget</variable>
-  <value type="qlonglong">0</value>
+  <value type="int">0</value>
  </data>
  </data>
  <data>
  <data>
   <variable>ProjectExplorer.Project.EditorSettings</variable>
   <variable>ProjectExplorer.Project.EditorSettings</variable>
   <valuemap type="QVariantMap">
   <valuemap type="QVariantMap">
-   <value type="bool" key="EditorConfiguration.AutoDetect">true</value>
    <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
    <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+   <value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
    <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
    <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
    <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
    <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
     <value type="QString" key="language">Cpp</value>
     <value type="QString" key="language">Cpp</value>
@@ -28,27 +27,23 @@
      <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
      <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
     </valuemap>
     </valuemap>
    </valuemap>
    </valuemap>
-   <value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
+   <value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
    <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
    <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
    <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
    <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
    <value type="int" key="EditorConfiguration.IndentSize">4</value>
    <value type="int" key="EditorConfiguration.IndentSize">4</value>
    <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
    <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
-   <value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
    <value type="int" key="EditorConfiguration.MarginColumn">80</value>
    <value type="int" key="EditorConfiguration.MarginColumn">80</value>
    <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
    <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
    <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
    <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
    <value type="int" key="EditorConfiguration.PaddingMode">1</value>
    <value type="int" key="EditorConfiguration.PaddingMode">1</value>
-   <value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
-   <value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
    <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
    <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
    <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
    <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
-   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
+   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
    <value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
    <value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
    <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
    <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
    <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
    <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
    <value type="int" key="EditorConfiguration.TabSize">8</value>
    <value type="int" key="EditorConfiguration.TabSize">8</value>
    <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
    <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
-   <value type="bool" key="EditorConfiguration.UseIndenter">false</value>
    <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
    <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
    <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
    <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
    <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
    <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
@@ -56,7 +51,6 @@
    <value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
    <value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
    <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
    <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
    <value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
    <value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
-   <value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
   </valuemap>
   </valuemap>
  </data>
  </data>
  <data>
  <data>
@@ -64,50 +58,48 @@
   <valuemap type="QVariantMap">
   <valuemap type="QVariantMap">
    <valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
    <valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
     <value type="bool" key="AutoTest.Framework.Boost">true</value>
     <value type="bool" key="AutoTest.Framework.Boost">true</value>
-    <value type="bool" key="AutoTest.Framework.CTest">false</value>
     <value type="bool" key="AutoTest.Framework.Catch">true</value>
     <value type="bool" key="AutoTest.Framework.Catch">true</value>
     <value type="bool" key="AutoTest.Framework.GTest">true</value>
     <value type="bool" key="AutoTest.Framework.GTest">true</value>
     <value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
     <value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
     <value type="bool" key="AutoTest.Framework.QtTest">true</value>
     <value type="bool" key="AutoTest.Framework.QtTest">true</value>
    </valuemap>
    </valuemap>
-   <value type="bool" key="AutoTest.ApplyFilter">false</value>
    <valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
    <valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
-   <valuelist type="QVariantList" key="AutoTest.PathFilters"/>
    <value type="int" key="AutoTest.RunAfterBuild">0</value>
    <value type="int" key="AutoTest.RunAfterBuild">0</value>
    <value type="bool" key="AutoTest.UseGlobal">true</value>
    <value type="bool" key="AutoTest.UseGlobal">true</value>
+   <valuelist type="QVariantList" key="ClangCodeModel.CustomCommandLineKey"/>
+   <value type="bool" key="ClangCodeModel.UseGlobalConfig">true</value>
+   <value type="QString" key="ClangCodeModel.WarningConfigId">Builtin.Questionable</value>
    <valuemap type="QVariantMap" key="ClangTools">
    <valuemap type="QVariantMap" key="ClangTools">
     <value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
     <value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
     <value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
     <value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
     <value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
     <value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
-    <value type="int" key="ClangTools.ParallelJobs">8</value>
-    <value type="bool" key="ClangTools.PreferConfigFile">true</value>
+    <value type="int" key="ClangTools.ParallelJobs">4</value>
     <valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
     <valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
     <valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
     <valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
     <valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
     <valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
     <value type="bool" key="ClangTools.UseGlobalSettings">true</value>
     <value type="bool" key="ClangTools.UseGlobalSettings">true</value>
    </valuemap>
    </valuemap>
-   <value type="int" key="RcSync">0</value>
   </valuemap>
   </valuemap>
  </data>
  </data>
  <data>
  <data>
   <variable>ProjectExplorer.Project.Target.0</variable>
   <variable>ProjectExplorer.Project.Target.0</variable>
   <valuemap type="QVariantMap">
   <valuemap type="QVariantMap">
-   <value type="QString" key="DeviceType">Desktop</value>
-   <value type="bool" key="HasPerBcDcs">true</value>
-   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.15.2 GCC 64bit</value>
-   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.15.2 GCC 64bit</value>
-   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5152.gcc_64_kit</value>
-   <value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
-   <value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
-   <value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+   <value type="QString" key="DeviceType">GenericLinuxOsType</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">rk3568</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">rk3568</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{4b7c7020-747d-4c4a-8e7b-c68e8d5127ef}</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+   <value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
     <value type="int" key="EnableQmlDebugging">0</value>
     <value type="int" key="EnableQmlDebugging">0</value>
-    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/fffe/ISCS_LOTO_Linuxqt5/build/Desktop_Qt_5_15_2_GCC_64bit-Debug</value>
-    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/home/fffe/ISCS_LOTO_Linuxqt5/build/Desktop_Qt_5_15_2_GCC_64bit-Debug</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/kim/Desktop/ISCS_LOTO_Linux/build/build-Loto-rk3568-Debug</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/home/kim/Desktop/ISCS_LOTO_Linux/build/build-Loto-rk3568-Debug</value>
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+      <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
       <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
       <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
       <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
       <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
      </valuemap>
      </valuemap>
@@ -115,7 +107,7 @@
       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
      </valuemap>
      </valuemap>
-     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
@@ -126,7 +118,7 @@
       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
       <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
       <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
      </valuemap>
      </valuemap>
-     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
@@ -134,52 +126,133 @@
     <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
     <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
     <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
     <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
     <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
     <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
-    <value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
     <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
     <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
-    <value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
-    <value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
-    <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
-     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
-      <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
-      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
-      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
-      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
+    <value type="int" key="RunSystemFunction">0</value>
+   </valuemap>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/kim/Desktop/ISCS_LOTO_Linux/build-Loto-rk3568-Release</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/home/kim/Desktop/ISCS_LOTO_Linux/build-Loto-rk3568-Release</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+      <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+      <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
      </valuemap>
      </valuemap>
-     <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
-     <valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
-     <value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
-     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
     </valuemap>
     </valuemap>
-    <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
-    <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
-     <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
-     <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
-     <value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
-     <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
-     <valuelist type="QVariantList" key="CustomOutputParsers"/>
-     <value type="int" key="PE.EnvironmentAspect.Base">2</value>
-     <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
-     <value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
-     <value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
-     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
-     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
-     <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/home/fffe/ISCS_LOTO_Linuxqt5/src/src.pro</value>
-     <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
-     <value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
-     <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
-     <value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
-     <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
-     <value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
     </valuemap>
     </valuemap>
-    <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
-    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
+    <value type="int" key="QtQuickCompiler">0</value>
+    <value type="int" key="RunSystemFunction">0</value>
    </valuemap>
    </valuemap>
-   <value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
+    <value type="int" key="EnableQmlDebugging">0</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/kim/Desktop/ISCS_LOTO_Linux/build-Loto-rk3568-Profile</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/home/kim/Desktop/ISCS_LOTO_Linux/build-Loto-rk3568-Profile</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+      <value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+      <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
+     </valuemap>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Profile</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
+    <value type="int" key="QtQuickCompiler">0</value>
+    <value type="int" key="RunSystemFunction">0</value>
+    <value type="int" key="SeparateDebugInfo">0</value>
+   </valuemap>
+   <value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
-     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinux.CheckForFreeDiskSpaceStep</value>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
+      <value type="QString" key="RemoteLinux.CheckForFreeDiskSpaceStep.PathToCheck">/</value>
+      <value type="qlonglong" key="RemoteLinux.CheckForFreeDiskSpaceStep.RequiredSpace">5242880</value>
+      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
+      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
+     </valuemap>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinux.KillAppStep</value>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
+      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
+      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
+     </valuemap>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.2">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinux.RsyncDeployStep</value>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
+      <valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
+      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
+      <valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
+      <value type="QString" key="RemoteLinux.RsyncDeployStep.Flags">-av</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildStepList.StepsCount">3</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
@@ -187,35 +260,95 @@
     <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
     <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
     <valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
     <valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
     <value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
     <value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
-    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">DeployToGenericLinux</value>
    </valuemap>
    </valuemap>
-   <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
+   <value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
    <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+    <value type="QString" key="Analyzer.Perf.CallgraphMode">dwarf</value>
+    <valuelist type="QVariantList" key="Analyzer.Perf.Events">
+     <value type="QString">cpu-cycles</value>
+    </valuelist>
+    <valuelist type="QVariantList" key="Analyzer.Perf.ExtraArguments"/>
+    <value type="int" key="Analyzer.Perf.Frequency">250</value>
+    <valuelist type="QVariantList" key="Analyzer.Perf.RecordArguments">
+     <value type="QString">-e</value>
+     <value type="QString">cpu-cycles</value>
+     <value type="QString">--call-graph</value>
+     <value type="QString">dwarf,4096</value>
+     <value type="QString">-F</value>
+     <value type="QString">250</value>
+    </valuelist>
+    <value type="QString" key="Analyzer.Perf.SampleMode">-F</value>
     <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
     <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
+    <value type="int" key="Analyzer.Perf.StackSize">4096</value>
+    <value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
+    <value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
+    <value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
+    <value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
     <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
     <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
-    <value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
+    <value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
+    <value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
+    <value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
+    <value type="QString" key="Analyzer.Valgrind.KCachegrindExecutable">kcachegrind</value>
+    <value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
+    <value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
+    <value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
     <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
     <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+    <value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
+    <value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
+    <value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
+    <valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
+     <value type="int">0</value>
+     <value type="int">1</value>
+     <value type="int">2</value>
+     <value type="int">3</value>
+     <value type="int">4</value>
+     <value type="int">5</value>
+     <value type="int">6</value>
+     <value type="int">7</value>
+     <value type="int">8</value>
+     <value type="int">9</value>
+     <value type="int">10</value>
+     <value type="int">11</value>
+     <value type="int">12</value>
+     <value type="int">13</value>
+     <value type="int">14</value>
+    </valuelist>
     <valuelist type="QVariantList" key="CustomOutputParsers"/>
     <valuelist type="QVariantList" key="CustomOutputParsers"/>
-    <value type="int" key="PE.EnvironmentAspect.Base">2</value>
-    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
-    <value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
-    <value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
-    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
-    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
-    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/home/fffe/ISCS_LOTO_Linuxqt5/src/src.pro</value>
-    <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
-    <value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
+    <value type="int" key="PE.EnvironmentAspect.Base">1</value>
+    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes">
+     <value type="QString">LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH</value>
+     <value type="QString">QML2_IMPORT_PATH=$QTDIR/qml:$QML2_IMPORT_PATH</value>
+     <value type="QString">QTDIR=/opt/qt5</value>
+     <value type="QString">QT_PLUGIN_PATH=$QTDIR/plugins:$QT_PLUGIN_PATH</value>
+    </valuelist>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">src (on rk3568)</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">RemoteLinuxRunConfiguration:/home/kim/Desktop/ISCS_LOTO_Linux/src/src.pro</value>
+    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/home/kim/Desktop/ISCS_LOTO_Linux/src/src.pro</value>
+    <value type="int" key="RemoteLinux.EnvironmentAspect.Version">1</value>
+    <value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
     <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
     <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
-    <value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
     <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
     <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
-    <value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
+    <value type="QString" key="RunConfiguration.X11Forwarding">:0</value>
    </valuemap>
    </valuemap>
-   <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+   <value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
   </valuemap>
   </valuemap>
  </data>
  </data>
  <data>
  <data>
   <variable>ProjectExplorer.Project.TargetCount</variable>
   <variable>ProjectExplorer.Project.TargetCount</variable>
-  <value type="qlonglong">1</value>
+  <value type="int">1</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+  <value type="int">22</value>
  </data>
  </data>
  <data>
  <data>
   <variable>Version</variable>
   <variable>Version</variable>

+ 224 - 0
Loto.pro.user.a558760

@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<!-- Written by QtCreator 18.0.2, 2026-01-28T22:18:58. -->
+<qtcreator>
+ <data>
+  <variable>EnvironmentId</variable>
+  <value type="QByteArray">{a5587603-485e-486a-a1a9-dc3454e0b3d3}</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.ActiveTarget</variable>
+  <value type="qlonglong">0</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.EditorSettings</variable>
+  <valuemap type="QVariantMap">
+   <value type="bool" key="EditorConfiguration.AutoDetect">true</value>
+   <value type="bool" key="EditorConfiguration.AutoIndent">true</value>
+   <value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
+    <value type="QString" key="language">Cpp</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
+    </valuemap>
+   </valuemap>
+   <valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
+    <value type="QString" key="language">QmlJS</value>
+    <valuemap type="QVariantMap" key="value">
+     <value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
+    </valuemap>
+   </valuemap>
+   <value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
+   <value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
+   <value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
+   <value type="int" key="EditorConfiguration.IndentSize">4</value>
+   <value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
+   <value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
+   <value type="int" key="EditorConfiguration.MarginColumn">80</value>
+   <value type="bool" key="EditorConfiguration.MouseHiding">true</value>
+   <value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
+   <value type="int" key="EditorConfiguration.PaddingMode">1</value>
+   <value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
+   <value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
+   <value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
+   <value type="bool" key="EditorConfiguration.ShowMargin">false</value>
+   <value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
+   <value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
+   <value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
+   <value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
+   <value type="int" key="EditorConfiguration.TabSize">8</value>
+   <value type="bool" key="EditorConfiguration.UseGlobal">true</value>
+   <value type="bool" key="EditorConfiguration.UseIndenter">false</value>
+   <value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
+   <value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
+   <value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
+   <value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
+   <value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
+   <value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
+   <value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
+   <value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.PluginSettings</variable>
+  <valuemap type="QVariantMap">
+   <valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
+    <value type="bool" key="AutoTest.Framework.Boost">true</value>
+    <value type="bool" key="AutoTest.Framework.CTest">false</value>
+    <value type="bool" key="AutoTest.Framework.Catch">true</value>
+    <value type="bool" key="AutoTest.Framework.GTest">true</value>
+    <value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
+    <value type="bool" key="AutoTest.Framework.QtTest">true</value>
+   </valuemap>
+   <value type="bool" key="AutoTest.ApplyFilter">false</value>
+   <valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
+   <valuelist type="QVariantList" key="AutoTest.PathFilters"/>
+   <value type="int" key="AutoTest.RunAfterBuild">0</value>
+   <value type="bool" key="AutoTest.UseGlobal">true</value>
+   <valuemap type="QVariantMap" key="ClangTools">
+    <value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
+    <value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
+    <value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
+    <value type="int" key="ClangTools.ParallelJobs">8</value>
+    <value type="bool" key="ClangTools.PreferConfigFile">true</value>
+    <valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
+    <valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
+    <valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
+    <value type="bool" key="ClangTools.UseGlobalSettings">true</value>
+   </valuemap>
+   <value type="int" key="RcSync">0</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Target.0</variable>
+  <valuemap type="QVariantMap">
+   <value type="QString" key="DeviceType">Desktop</value>
+   <value type="bool" key="HasPerBcDcs">true</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.15.2 GCC 64bit</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.15.2 GCC 64bit</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt5.5152.gcc_64_kit</value>
+   <value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
+   <value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+   <value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
+    <value type="int" key="EnableQmlDebugging">0</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/fffe/ISCS_LOTO_Linuxqt5/build/Desktop_Qt_5_15_2_GCC_64bit-Debug</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir">/home/fffe/ISCS_LOTO_Linuxqt5/build/Desktop_Qt_5_15_2_GCC_64bit-Debug</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
+      <value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
+      <valuelist type="QVariantList" key="QtProjectManager.QMakeBuildStep.SelectedAbis"/>
+     </valuemap>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
+    </valuemap>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
+      <value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
+    <value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
+    <valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
+    <value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+    <value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+      <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+     </valuemap>
+     <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+     <valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
+     <value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+    </valuemap>
+    <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+     <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
+     <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
+     <value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
+     <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+     <valuelist type="QVariantList" key="CustomOutputParsers"/>
+     <value type="int" key="PE.EnvironmentAspect.Base">2</value>
+     <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+     <value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
+     <value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
+     <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/home/fffe/ISCS_LOTO_Linuxqt5/src/src.pro</value>
+     <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
+     <value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
+     <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+     <value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
+     <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+     <value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
+    </valuemap>
+    <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+    <value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
+   </valuemap>
+   <value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
+    </valuemap>
+    <value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
+    <value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
+   </valuemap>
+   <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
+    <value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
+    <value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
+    <value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
+    <value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
+    <valuelist type="QVariantList" key="CustomOutputParsers"/>
+    <value type="int" key="PE.EnvironmentAspect.Base">2</value>
+    <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
+    <value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
+    <value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:</value>
+    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">/home/fffe/ISCS_LOTO_Linuxqt5/src/src.pro</value>
+    <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
+    <value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
+    <value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
+    <value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
+    <value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
+    <value type="QString" key="RunConfiguration.WorkingDirectory.default">%{RunConfig:Executable:Path}</value>
+   </valuemap>
+   <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.TargetCount</variable>
+  <value type="qlonglong">1</value>
+ </data>
+ <data>
+  <variable>Version</variable>
+  <value type="int">22</value>
+ </data>
+</qtcreator>

+ 1 - 0
src/httpclient/HttpCardLogin.cpp

@@ -56,6 +56,7 @@ bool HttpCardLogin::cardIDToNfc(const QString &cardId)
         for (int i = hexStr.length()/2; i > 0; i--) {
         for (int i = hexStr.length()/2; i > 0; i--) {
             m_cardNfc = m_cardNfc + hexStr.mid((i-1)*2, 2);
             m_cardNfc = m_cardNfc + hexStr.mid((i-1)*2, 2);
         }
         }
+        m_cardNfc = m_cardNfc.toUpper();
         return true;
         return true;
     }
     }
     return false;
     return false;

+ 48 - 29
src/httpclient/HttpClient.cpp

@@ -228,25 +228,25 @@ void HttpClient::run()
             m_workStat = httpWorkStat::httpWorkSleep;
             m_workStat = httpWorkStat::httpWorkSleep;
             m_mutex.unlock();
             m_mutex.unlock();
 
 
-            // GET 请求在工作线程完成,在此发射信号,避免在主线程阻塞
-            if (postUrl == Config()->jobTicketsUrl) {
-                emit signalResponseGetJobTickets(bb);
-            }
-            else if (postUrl == Config()->workNodeDetail) {
-                emit signalResponseGetWorkNodeDetail(bb);
-            }
-            else if (postUrl == Config()->workNodeDetailForm) {
-                emit signalResponseGetFormById(bb);
-            }
-            else if (postUrl == Config()->userInfoUrl) {
-                emit signalResponseGetUserInfoUrl(bb);
-            }
-            else if (postUrl == Config()->keyMACByNFC) {
-                emit signalResponseGetKeyMAC(bb);
-            }
-            else if (postUrl == Config()->isolationPointById) {
-                emit signalResponseGetIsolationPointInfo(bb);
-            }
+//            // GET 请求在工作线程完成,在此发射信号,避免在主线程阻塞
+//            if (postUrl == Config()->jobTicketsUrl) {
+//                emit signalResponseGetJobTickets(bb);
+//            }
+//            else if (postUrl == Config()->workNodeDetail) {
+//                emit signalResponseGetWorkNodeDetail(bb);
+//            }
+//            else if (postUrl == Config()->workNodeDetailForm) {
+//                emit signalResponseGetFormById(bb);
+//            }
+//            else if (postUrl == Config()->userInfoUrl) {
+//                emit signalResponseGetUserInfoUrl(bb);
+//            }
+//            else if (postUrl == Config()->keyMACByNFC) {
+//                emit signalResponseGetKeyMAC(bb);
+//            }
+//            else if (postUrl == Config()->isolationPointById) {
+//                emit signalResponseGetIsolationPointInfo(bb);
+//            }
         }
         }
 
 
         msleep(10);
         msleep(10);
@@ -559,7 +559,7 @@ QString HttpClient::putJsonRequest()
             QByteArray result = reply->readAll();
             QByteArray result = reply->readAll();
             QString strRes = QString::fromUtf8(result);
             QString strRes = QString::fromUtf8(result);
 
 
-            // qDebug() << "http post success post response=" << strRes;
+            qDebug() << "http post success post response=" << strRes;
             reply->deleteLater();
             reply->deleteLater();
             return strRes;
             return strRes;
         }
         }
@@ -592,7 +592,7 @@ void HttpClient::slotPostRequestData(quint64 id, QString postUrl, QByteArray dat
     qDebug() << "[HttpClient]   URL:" << postUrl;
     qDebug() << "[HttpClient]   URL:" << postUrl;
     qDebug() << "[HttpClient]   数据:" << QString::fromUtf8(data);
     qDebug() << "[HttpClient]   数据:" << QString::fromUtf8(data);
     
     
-    m_mutex.lock();
+//    m_mutex.lock();
     this->m_id = id;
     this->m_id = id;
     this->m_postUrl = postUrl;
     this->m_postUrl = postUrl;
     this->m_httpData = data;
     this->m_httpData = data;
@@ -609,7 +609,7 @@ void HttpClient::slotPostRequestData(quint64 id, QString postUrl, QByteArray dat
         QString res = postJsonRequest();
         QString res = postJsonRequest();
         qDebug() << "[HttpClient] postJsonRequest完成,响应:" << res.left(200);
         qDebug() << "[HttpClient] postJsonRequest完成,响应:" << res.left(200);
         QByteArray bb = res.toUtf8();
         QByteArray bb = res.toUtf8();
-        m_mutex.unlock();
+//        m_mutex.unlock();
 
 
         if(m_postUrl == Config()->usernameLogin_url) {
         if(m_postUrl == Config()->usernameLogin_url) {
             emit signalResponsePasswordLoginData(bb);
             emit signalResponsePasswordLoginData(bb);
@@ -648,21 +648,40 @@ void HttpClient::slotPostRequestData(quint64 id, QString postUrl, QByteArray dat
 
 
 void HttpClient::slotGetRequestData(quint64 id, QString postUrl, QByteArray data, QString token)
 void HttpClient::slotGetRequestData(quint64 id, QString postUrl, QByteArray data, QString token)
 {
 {
-    // 不在主线程执行同步 getRequest(),否则会阻塞 UI 导致“无响应”
-    // 将参数交给工作线程,由 run() 中执行 getRequest() 并发射信号
-    m_mutex.lock();
+//    m_mutex.lock();
     this->m_id = id;
     this->m_id = id;
     this->m_postUrl = postUrl;
     this->m_postUrl = postUrl;
     this->m_httpData = data;
     this->m_httpData = data;
     this->m_token = token;
     this->m_token = token;
     HttpClient::sToken = token;
     HttpClient::sToken = token;
-    this->m_workStat = httpWorkStat::httpWorkGet;
-    m_mutex.unlock();
+
+    QString res = getRequest();
+    QByteArray bb = res.toUtf8();
+//    m_mutex.unlock();
+
+    if (m_postUrl == Config()->jobTicketsUrl) {
+        emit signalResponseGetJobTickets(bb);
+    }
+    else if (m_postUrl == Config()->workNodeDetail) {
+        emit signalResponseGetWorkNodeDetail(bb);
+    }
+    else if (m_postUrl == Config()->workNodeDetailForm) {
+        emit signalResponseGetFormById(bb);
+    }
+    else if (m_postUrl == Config()->userInfoUrl) {
+        emit signalResponseGetUserInfoUrl(bb);
+    }
+    else if (m_postUrl == Config()->keyMACByNFC) {
+        emit signalResponseGetKeyMAC(bb);
+    }
+    else if (m_postUrl == Config()->isolationPointById) {
+        emit signalResponseGetIsolationPointInfo(bb);
+    }
 }
 }
 
 
 void HttpClient::slotPutRequestData(quint64 id, QString postUrl, QByteArray data, QByteArray file, QString token)
 void HttpClient::slotPutRequestData(quint64 id, QString postUrl, QByteArray data, QByteArray file, QString token)
 {
 {
-    m_mutex.lock();
+//    m_mutex.lock();
     this->m_id = id;
     this->m_id = id;
     this->m_postUrl = postUrl;
     this->m_postUrl = postUrl;
     this->m_httpData = data;
     this->m_httpData = data;
@@ -677,7 +696,7 @@ void HttpClient::slotPutRequestData(quint64 id, QString postUrl, QByteArray data
     {
     {
         QString res = putJsonRequest();
         QString res = putJsonRequest();
         QByteArray bb = res.toUtf8();
         QByteArray bb = res.toUtf8();
-        m_mutex.unlock();
+//        m_mutex.unlock();
 
 
         if(m_postUrl == Config()->updateUserInfoUrl) {
         if(m_postUrl == Config()->updateUserInfoUrl) {
             emit signalReponseUpdateUserInfoUrl(bb);
             emit signalReponseUpdateUserInfoUrl(bb);

+ 21 - 0
src/httpclient/JobTicketsModel.cpp

@@ -186,3 +186,24 @@ int JobTicketModel::getFirstRunningIndex() const
     }
     }
     return -1;
     return -1;
 }
 }
+
+QVariantMap JobTicketModel::getSingleJobTicket() const
+{
+    QVariantMap jobTicket;
+
+    for (int i = 0; i < m_dataList.count(); i++) {
+        if (m_dataList[i].m_approvalStatus == "进行中") {
+            JobTicket ticket = m_dataList[i];
+            jobTicket.insert("nodeId", QString::number(ticket.m_nodeId));
+            jobTicket.insert("name", ticket.m_name);
+            jobTicket.insert("orderNo", ticket.m_orderNo);
+            jobTicket.insert("approvalStatus", ticket.m_approvalStatus);
+            jobTicket.insert("workTime", ticket.m_workTime);
+            jobTicket.insert("workerUserName", ticket.m_workerUserName);
+            jobTicket.insert("currentNodeName", ticket.m_currentNodeName);
+            return jobTicket;
+        }
+    }
+
+    return jobTicket;
+}

+ 1 - 0
src/httpclient/JobTicketsModel.h

@@ -85,6 +85,7 @@ public:
     Q_INVOKABLE int getFirstRunningNodeId() const;
     Q_INVOKABLE int getFirstRunningNodeId() const;
     // 获取第一个"进行中"作业的索引,如果没有返回-1
     // 获取第一个"进行中"作业的索引,如果没有返回-1
     Q_INVOKABLE int getFirstRunningIndex() const;
     Q_INVOKABLE int getFirstRunningIndex() const;
+    Q_INVOKABLE QVariantMap getSingleJobTicket() const;
     virtual QHash<int, QByteArray> roleNames() const override;
     virtual QHash<int, QByteArray> roleNames() const override;
     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
 private:
 private:

+ 2 - 1
src/httpclient/WorkNodeFormModel.h

@@ -36,7 +36,7 @@ class WorkNodeFormModel : public QAbstractListModel
     QML_SINGLETON
     QML_SINGLETON
     QML_NAMED_ELEMENT(WorkNodeFormModel)
     QML_NAMED_ELEMENT(WorkNodeFormModel)
 
 
-    Q_PROPERTY(QString modelType READ modelType WRITE setModelType)
+    Q_PROPERTY(QString modelType READ modelType WRITE setModelType NOTIFY modelTypeChanged)
     Q_PROPERTY(QString formJsonInfo READ formJsonInfo WRITE setFormJsonInfo NOTIFY formJsonInfoChanged)
     Q_PROPERTY(QString formJsonInfo READ formJsonInfo WRITE setFormJsonInfo NOTIFY formJsonInfoChanged)
     Q_PROPERTY(QJsonArray nodeUserList READ nodeUserList WRITE setNodeUserList NOTIFY nodeUserListChanged)
     Q_PROPERTY(QJsonArray nodeUserList READ nodeUserList WRITE setNodeUserList NOTIFY nodeUserListChanged)
     Q_PROPERTY(int workId READ workId WRITE setWorkId NOTIFY workIdChanged)
     Q_PROPERTY(int workId READ workId WRITE setWorkId NOTIFY workIdChanged)
@@ -142,6 +142,7 @@ public:
         emit descriptionChanged();
         emit descriptionChanged();
     }
     }
 signals:
 signals:
+    void modelTypeChanged();
     void formJsonInfoChanged();
     void formJsonInfoChanged();
     void nodeUserListChanged();
     void nodeUserListChanged();
     void workIdChanged();
     void workIdChanged();

+ 95 - 16
src/interactive/InteractiveCAN.cpp

@@ -6,17 +6,17 @@
 #include <QDebug>
 #include <QDebug>
 
 
 // ============ 临时禁用CAN通讯日志 (可撤回) ============
 // ============ 临时禁用CAN通讯日志 (可撤回) ============
-#define CAN_LOG_DISABLED
-#ifdef CAN_LOG_DISABLED
-#undef qDebug
-#undef qInfo
-#undef qWarning
-#undef qCritical
-#define qDebug() QNoDebug()
-#define qInfo() QNoDebug()
-#define qWarning() QNoDebug()
-#define qCritical() QNoDebug()
-#endif
+//#define CAN_LOG_DISABLED
+//#ifdef CAN_LOG_DISABLED
+//#undef qDebug
+//#undef qInfo
+//#undef qWarning
+//#undef qCritical
+//#define qDebug() QNoDebug()
+//#define qInfo() QNoDebug()
+//#define qWarning() QNoDebug()
+//#define qCritical() QNoDebug()
+//#endif
 // ====================================================
 // ====================================================
 
 
 InteractiveCAN* InteractiveCAN::pInstance = nullptr;
 InteractiveCAN* InteractiveCAN::pInstance = nullptr;
@@ -60,6 +60,8 @@ InteractiveCAN::InteractiveCAN()
 
 
     connect(m_canClient, &CANClient::keyBaseChargeControlWritten, this, &InteractiveCAN::slotUnlockEKey);
     connect(m_canClient, &CANClient::keyBaseChargeControlWritten, this, &InteractiveCAN::slotUnlockEKey);
     connect(m_canClient, &CANClient::lockBuckleWritten, this, &InteractiveCAN::slotUnlockLocks);
     connect(m_canClient, &CANClient::lockBuckleWritten, this, &InteractiveCAN::slotUnlockLocks);
+    connect(m_canClient, &CANClient::signalReturnKey, this, &InteractiveCAN::slotGetReturnCANDevices);
+    connect(m_canClient, &CANClient::signalLockNfcDeviceDetected, this, &InteractiveCAN::slotDeviceDetected);
 
 
     m_bleClient = new BLEClient(this);
     m_bleClient = new BLEClient(this);
 //    m_bleClient->start();
 //    m_bleClient->start();
@@ -102,6 +104,7 @@ InteractiveCAN::InteractiveCAN()
     });
     });
     connect(m_bleClient, &BLEClient::signalSendJobTicketStatus, this, &InteractiveCAN::slotSendJobTicketStatus);
     connect(m_bleClient, &BLEClient::signalSendJobTicketStatus, this, &InteractiveCAN::slotSendJobTicketStatus);
     connect(m_bleClient, &BLEClient::workTicketResultReceived, this, &InteractiveCAN::slotReceivedJobTicketResult);
     connect(m_bleClient, &BLEClient::workTicketResultReceived, this, &InteractiveCAN::slotReceivedJobTicketResult);
+    connect(m_bleClient, &BLEClient::signalFailConnect, this, &InteractiveCAN::slotReConnectBLE);
 
 
     m_checkHasKeyTimer = new QTimer(this);
     m_checkHasKeyTimer = new QTimer(this);
     connect(m_checkHasKeyTimer, &QTimer::timeout, this, &InteractiveCAN::checkEKeyStatus);
     connect(m_checkHasKeyTimer, &QTimer::timeout, this, &InteractiveCAN::checkEKeyStatus);
@@ -336,7 +339,7 @@ void InteractiveCAN::httpRequestPostUpdateBackLock(const QList<QString> &lockNfc
 
 
     QJsonDocument jsonDoc(locksInfo);
     QJsonDocument jsonDoc(locksInfo);
     QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Compact);
     QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Compact);
-    qDebug() << jsonDoc;
+    qDebug() << "[httpRequestPostUpdateBackLock] " << jsonDoc;
 
 
     emit signalPostRequestData(timestampSeconds, url, jsonData, NULL, GetInteractiveData()->m_token);
     emit signalPostRequestData(timestampSeconds, url, jsonData, NULL, GetInteractiveData()->m_token);
 }
 }
@@ -400,13 +403,14 @@ void InteractiveCAN::slotHttpResponseGetKeyMAC(QByteArray data)
 {
 {
     QJsonParseError error;
     QJsonParseError error;
     QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
     QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
+//    qDebug() << "[slotHttpResponseGetKeyMAC]: " << jsonDoc;
     if (error.error != QJsonParseError::NoError) {
     if (error.error != QJsonParseError::NoError) {
         return;
         return;
     }
     }
     if (jsonDoc.isNull() || jsonDoc.isEmpty()) {
     if (jsonDoc.isNull() || jsonDoc.isEmpty()) {
         return;
         return;
     }
     }
-    qDebug() << jsonDoc;
+
     QJsonObject rootObj = jsonDoc.object();
     QJsonObject rootObj = jsonDoc.object();
     if(rootObj.contains("code")) {
     if(rootObj.contains("code")) {
         int codeValue = rootObj.value("code").toInt();
         int codeValue = rootObj.value("code").toInt();
@@ -427,13 +431,17 @@ void InteractiveCAN::slotHttpResponseGetIsolationPointInfo(QByteArray data)
 {
 {
     QJsonParseError error;
     QJsonParseError error;
     QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
     QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
+
     if (error.error != QJsonParseError::NoError) {
     if (error.error != QJsonParseError::NoError) {
         return;
         return;
     }
     }
     if (jsonDoc.isNull() || jsonDoc.isEmpty()) {
     if (jsonDoc.isNull() || jsonDoc.isEmpty()) {
         return;
         return;
     }
     }
-    ;
+    else {
+        qDebug() << "[InteractiveCAN::slotHttpResponseGetIsolationPointInfo]: " << jsonDoc;
+    }
+
     QJsonObject rootObj = jsonDoc.object();
     QJsonObject rootObj = jsonDoc.object();
     if(rootObj.contains("code")) {
     if(rootObj.contains("code")) {
         int codeValue = rootObj.value("code").toInt();
         int codeValue = rootObj.value("code").toInt();
@@ -590,6 +598,57 @@ void InteractiveCAN::slotUpdateColockStatus(const QString& cardNfc)
     }
     }
 }
 }
 
 
+void InteractiveCAN::slotGetReturnCANDevices()
+{
+    // 传入qml端的消息JSON结构:
+    /*
+     * {
+     *      "tasks": [
+     *          {
+     *              "key": {"status": "", "nfc": ""},
+     *              "workName": "",
+     *              "workId": "",
+     *              "username": "",
+     *              "locks": [{"status": "", "nfc": ""}]
+     *          },
+     *      ],
+     *      "errorDevices": [{"status": "", "nfc": ""}],
+     *      "noTaskDevices": [{"status": "", "nfc": ""}]
+     * }
+    */
+    QMap<QString, quint8> keyInfo = CANClient::returnDevicesInfo.keysMap;
+    QMap<QString, quint8> lockInfo = CANClient::returnDevicesInfo.locksMap;
+
+    QJsonArray taskArray;
+
+    for (auto keyIter = keyInfo.begin(); keyIter != keyInfo.end(); ++keyIter) {
+        // TODO: 根据钥匙NFC获取当前作业票
+    }
+
+    QJsonArray errDevicesArr;
+    QJsonArray noTaskDevicesArr;
+    for (auto lockIter = lockInfo.begin(); lockIter != lockInfo.end(); ++lockIter) {
+        // TODO: 如果锁存在某个任务中,但此时没有钥匙放入,进入异常;否则无关联任务
+    }
+
+    QJsonObject rootObject;
+    rootObject.insert("tasks", taskArray);
+    rootObject.insert("errorDevices", errDevicesArr);
+    rootObject.insert("noTaskDevices", noTaskDevicesArr);
+
+    QJsonDocument doc(rootObject);
+    QByteArray info = doc.toJson(QJsonDocument::Compact);
+
+    emit signalReturnDevicesInfo(info);
+}
+
+void InteractiveCAN::slotReConnectBLE()
+{
+    if (m_bleClient) {
+        m_bleClient->connectDevice(m_currentKeyMAC, "keyLock");
+    }
+}
+
 InteractiveCAN *InteractiveCAN::instance()
 InteractiveCAN *InteractiveCAN::instance()
 {
 {
     if (!pInstance) {
     if (!pInstance) {
@@ -625,7 +684,7 @@ void InteractiveCAN::openEKey()
             break;
             break;
         }
         }
     }
     }
-
+    qDebug() << "[InteractiveCAN] key nfc: " << m_keyNFC;
     if (!m_keyNFC.isEmpty()) {
     if (!m_keyNFC.isEmpty()) {
         QJsonObject jsonRoot;
         QJsonObject jsonRoot;
         QDateTime currentDateTime = QDateTime::currentDateTime();
         QDateTime currentDateTime = QDateTime::currentDateTime();
@@ -798,10 +857,29 @@ void InteractiveCAN::slotUnlockLocks(bool success, const QList<QString>& lockRfi
                 });
                 });
             }
             }
         }
         }
+//        qDebug() << "[slotUnlockLocks]: " << lockRfids << WorkNodeFormModel::instance()->modelType();
+//        if (WorkNodeFormModel::instance()->modelType() == QString("releaseIsolation")) {
+//            if (!m_getLockedRfidFlag) {
+//                m_getLockedRfidFlag = true;
+//                qDebug() << "[slotUnlockLocks]: " << lockRfids;
+//                httpRequestPostUpdateBackLock(lockRfids);
+
+//                emit signalUpdateBackLockStatus(lockRfids);
+//            }
+//        }
+    }
+}
+
+void InteractiveCAN::slotDeviceDetected(const QString &nfcId)
+{
+    if (!nfcId.isEmpty()) {
         if (WorkNodeFormModel::instance()->modelType() == QString("releaseIsolation")) {
         if (WorkNodeFormModel::instance()->modelType() == QString("releaseIsolation")) {
             if (!m_getLockedRfidFlag) {
             if (!m_getLockedRfidFlag) {
                 m_getLockedRfidFlag = true;
                 m_getLockedRfidFlag = true;
-                qDebug() << "[slotUnlockLocks]: " << lockRfids;
+
+                QList<QString> lockRfids;
+                lockRfids << nfcId;
+                qDebug() << "[slotDeviceDetected]: " << nfcId << lockRfids;
                 httpRequestPostUpdateBackLock(lockRfids);
                 httpRequestPostUpdateBackLock(lockRfids);
 
 
                 emit signalUpdateBackLockStatus(lockRfids);
                 emit signalUpdateBackLockStatus(lockRfids);
@@ -824,6 +902,7 @@ void InteractiveCAN::slotOkSearchedBLE(bool success)
 {
 {
     if (success) {
     if (success) {
         if (m_bleClient->isConnected()) {
         if (m_bleClient->isConnected()) {
+            qDebug() << "[InteractiveCAN::slotOkSearchedBLE]";
             createColockJobTicket();
             createColockJobTicket();
         }
         }
         else {
         else {

+ 5 - 0
src/interactive/InteractiveCAN.h

@@ -81,6 +81,7 @@ public:
 public slots:
 public slots:
     void slotUnlockEKey(const CANKeyBaseChargeStatus& status);
     void slotUnlockEKey(const CANKeyBaseChargeStatus& status);
     void slotUnlockLocks(bool success, const QList<QString>& lockRfids);
     void slotUnlockLocks(bool success, const QList<QString>& lockRfids);
+    void slotDeviceDetected(const QString& nfcId);
     void slotSearchBLE();
     void slotSearchBLE();
     void slotOkSearchedBLE(bool success);
     void slotOkSearchedBLE(bool success);
 
 
@@ -113,7 +114,11 @@ public slots:
     void slotHttpResponseUpdateBackLock(QByteArray data);
     void slotHttpResponseUpdateBackLock(QByteArray data);
 
 
     void slotUpdateColockStatus(const QString& cardNfc);
     void slotUpdateColockStatus(const QString& cardNfc);
+
+    void slotGetReturnCANDevices();
+    void slotReConnectBLE();
 signals:
 signals:
+    void signalReturnDevicesInfo(const QByteArray& info);
     void signalOkSearchedBLE(bool success);
     void signalOkSearchedBLE(bool success);
 
 
     void cardNoChanged();
     void cardNoChanged();

+ 1 - 1
src/main.cpp

@@ -24,7 +24,7 @@ int main(int argc, char **argv)
 
 
     QQmlApplicationEngine engine;
     QQmlApplicationEngine engine;
 
 
-    // 注册C++类/对象到QML123
+    // 注册C++类/对象到QML
     LotoQmlTypes::registerTypes();
     LotoQmlTypes::registerTypes();
 
 
     const QUrl url = QUrl(QStringLiteral("qrc:/qml/main.qml"));
     const QUrl url = QUrl(QStringLiteral("qrc:/qml/main.qml"));

+ 0 - 1
src/qml/JobTicketPage.qml

@@ -6,7 +6,6 @@ import Loto 1.0
 
 
 Rectangle {
 Rectangle {
     id: control
     id: control
-    objectName: "__JobTicketPage__"
 
 
     property string pageTitleIconCharacter: "\uf0ae"
     property string pageTitleIconCharacter: "\uf0ae"
     property string pageTitleText: "我的作业"
     property string pageTitleText: "我的作业"

+ 115 - 14
src/qml/Login.qml

@@ -147,24 +147,111 @@ Rectangle {
 
 
     // 作业票请求状态标志
     // 作业票请求状态标志
     property bool isRequestingJobTickets: false
     property bool isRequestingJobTickets: false
+    HttpGetWorkNodeDetail {
+        id: httpGetWorkNodeDetail
+    }
 
 
-    // 作业票
-    HttpGetJobTickets {
-        id: httpGetJobTickets
-
-        Component.onCompleted: {
-            httpGetJobTickets.signalGetRequestData.connect(httpClientThread.slotGetRequestData);
-            httpClientThread.signalResponseGetJobTickets.connect(httpGetJobTickets.slotHttpResponseGetJobTickets);
-        }
+    Connections {
+        target: httpGetWorkNodeDetail
+        function onSignalWorkNodeDetailReturnStat(state, msg) {
+            httpGetWorkNodeDetail.signalGetRequestData.disconnect(httpClientThread.slotGetRequestData);
+            httpClientThread.signalResponseGetWorkNodeDetail.disconnect(httpGetWorkNodeDetail.slotHttpResponseGetWorkNodeDetail);
+            httpClientThread.signalResponseGetFormById.disconnect(httpGetWorkNodeDetail.slotHttpResponseGetFormById);
+
+            var isShowNegativeBtn = false;
+            var isShowOpsitiveBtn = false;
+            var textNegativeBtnStr = "";
+            var textOpsitiveBtnStr = "";
+            var showJobTicketProcess = false;
+            var showFormCard = false;
+            var showJobTicketColockProcess = false;
+            var jobTicketinfo = JobTicketModel.getSingleJobTicket();
+
+            if (state !== 0) {
+                if (WorkNodeFormModel.modelType === "isolation") {
+                    // 隔离/方案
+                    showJobTicketProcess = true;
+                } else if (WorkNodeFormModel.modelType === "releaseIsolation" ||
+                            WorkNodeFormModel.modelType === "returnLock") {
+                    // 还锁 || 解除隔离
+                    showJobTicketColockProcess = true;
+                } else {
+                    showAlertDialog("提示", msg, "\uf071", negativeAlertDialogCallback);
+                    return;
+                }
+            } else {
+                if (WorkNodeFormModel.modelType === "inputInfo") {
+                    // 录入信息
+                    isShowNegativeBtn = false;
+                    isShowOpsitiveBtn = true;
+//                    textNegativeBtnStr = "取消";
+                    textOpsitiveBtnStr = "确认"
+                    showFormCard= true;
+                } else if (WorkNodeFormModel.modelType === "review") {
+                    // 审核
+                    isShowNegativeBtn = true;
+                    isShowOpsitiveBtn = true;
+                    textNegativeBtnStr = "审核不通过";
+                    textOpsitiveBtnStr = "审核通过";
+                    showFormCard= true;
+                } else if (WorkNodeFormModel.modelType === "confirm") {
+                    // 通过
+                    isShowNegativeBtn = false;
+                    isShowOpsitiveBtn = true;
+//                    textNegativeBtnStr = "取消";
+                    textOpsitiveBtnStr = "提交";
+                    showFormCard= true;
+                } else if (WorkNodeFormModel.modelType === "isolation") {
+                    // 隔离/方案
+                    showJobTicketProcess = true;
+                } else if (WorkNodeFormModel.modelType === "releaseIsolation" ||
+                           WorkNodeFormModel.modelType === "returnLock") {
+                    // 还锁 || 解除隔离
+                    showJobTicketColockProcess = true;
+                } else if (WorkNodeFormModel.modelType === "complete") {
+                    // 完成/结束
+                    isShowNegativeBtn = false;
+                    isShowOpsitiveBtn = true;
+//                    textNegativeBtnStr = "取消";
+                    textOpsitiveBtnStr = "完成";
+                    showFormCard= true;
+                }
+            }
 
 
-        Component.onDestruction: {
-            httpGetJobTickets.signalGetRequestData.disconnect(httpClientThread.slotGetRequestData);
-            httpClientThread.signalResponseGetJobTickets.disconnect(httpGetJobTickets.slotHttpResponseGetJobTickets);
+            // 如果状态是"已完成",隐藏操作按钮(仅查看模式)
+            if (jobTicketinfo.approvalStatus === "已完成") {
+                isShowNegativeBtn = false;
+                isShowOpsitiveBtn = false;
+            }
+            control.cardLoginLoading = false;
+            appStackView.push("WorkingPage.qml", {
+                                    titleIconCharacter: "\uf023",
+                                    titleText: jobTicketinfo.name,
+                                    sopIconCharacter: '\uf292',
+                                    sopInfoText: jobTicketinfo.orderNo,
+                                    workingStateCharacter: "\uf02b",
+                                    workingStateText: jobTicketinfo.approvalStatus,
+                                    workingTimeCharacter: "\uf1da",
+                                    workingTimeText: jobTicketinfo.workTime,
+                                    userIconCharacter: "\uf406",
+                                    userName: jobTicketinfo.workerUserName,
+
+                                    showJobTicketColockProcess: showJobTicketColockProcess,
+                                    showJobTicketProcess: showJobTicketProcess,
+                                    showFormCard: showFormCard,
+                                    showNegativeBtn: isShowNegativeBtn,
+                                    showOpsitiveBtn: isShowOpsitiveBtn,
+                                    textNegativeBtn: textNegativeBtnStr,
+                                    textOpsitiveBtn: textOpsitiveBtnStr,
+
+                                    currentNodeId: jobTicketinfo.nodeId,
+                                    currentNodeName: jobTicketinfo.currentNodeName
+                              });
         }
         }
     }
     }
 
 
     Connections {
     Connections {
-        target: httpGetJobTickets
+        target: appHttpGetJobTickets
         function onSignalJobTicketsReturnStat(stat, msg) {
         function onSignalJobTicketsReturnStat(stat, msg) {
             // 只有在本页面发起请求时才处理
             // 只有在本页面发起请求时才处理
             if (!isRequestingJobTickets) {
             if (!isRequestingJobTickets) {
@@ -177,9 +264,23 @@ Rectangle {
             if (stat !== 0 || JobTicketModel.rowCount() === 0) {
             if (stat !== 0 || JobTicketModel.rowCount() === 0) {
                 appStackView.push("components/NoJobTicketDialog.qml");
                 appStackView.push("components/NoJobTicketDialog.qml");
             } else {
             } else {
-                if (JobTicketModel.rowCount() === 1) {
+                var runningCount = JobTicketModel.runningCount();
+                if (runningCount === 1) {
                     // 直接跳转到作业票页面
                     // 直接跳转到作业票页面
-                    appStackView.push("JobTicketPage.qml");
+//                    appStackView.push("JobTicketPage.qml");
+                    var jobTicketinfo = JobTicketModel.getSingleJobTicket();
+                    if (jobTicketinfo.length === 0) {
+                        appStackView.push("JobTicketPage.qml");
+                    } else {
+                        control.cardLoginLoading = true;
+                        cardLoginLoadingDialog.loadingText = "正在查询作业任务..."
+                        httpGetWorkNodeDetail.nodeId = jobTicketinfo.nodeId;
+                        // 防止Repeater复制槽函数
+                        httpGetWorkNodeDetail.signalGetRequestData.connect(httpClientThread.slotGetRequestData);
+                        httpClientThread.signalResponseGetWorkNodeDetail.connect(httpGetWorkNodeDetail.slotHttpResponseGetWorkNodeDetail);
+                        httpClientThread.signalResponseGetFormById.connect(httpGetWorkNodeDetail.slotHttpResponseGetFormById);
+                        httpGetWorkNodeDetail.start();
+                    }
                 } else {
                 } else {
                     appStackView.push("JobTicketPage.qml");
                     appStackView.push("JobTicketPage.qml");
                 }
                 }

+ 37 - 30
src/qml/WorkingPage.qml

@@ -64,6 +64,8 @@ Rectangle {
             if (stat !== 0) {
             if (stat !== 0) {
                 showAlertDialog("提示", msg, "\uf071", negativeAlertDialogCallback);
                 showAlertDialog("提示", msg, "\uf071", negativeAlertDialogCallback);
             } else {
             } else {
+                // 任务提交成功后,再次访问"我的任务"用于刷新作业页面
+                appHttpGetJobTickets.start();
                 // 提交成功统一提示
                 // 提交成功统一提示
                 showSuccessConfirmDialog("提交成功,继续操作?");
                 showSuccessConfirmDialog("提交成功,继续操作?");
             }
             }
@@ -275,28 +277,28 @@ Rectangle {
             }
             }
 
 
             // 作业内容(仅审核界面显示,字段为 description)
             // 作业内容(仅审核界面显示,字段为 description)
-            Column {
-                id: __jobDescriptionArea
-                width: parent.width - 92
-                visible: control.showFormCard && WorkNodeFormModel.modelType === "review"
-                spacing: 8
-                anchors.left: parent.left
-                anchors.top: parent.top
-
-                Text {
-                    text: "作业内容:"
-                    color: "#888888"
-                    font.pixelSize: 16
-                }
-                Text {
-                    width: parent.width - 20
-                    text: WorkNodeFormModel.description
-                    color: "white"
-                    font.pixelSize: 15
-                    wrapMode: Text.Wrap
-                    visible: WorkNodeFormModel.description !== ""
-                }
-            }
+//            Column {
+//                id: __jobDescriptionArea
+//                width: parent.width - 92
+//                visible: control.showFormCard && WorkNodeFormModel.modelType === "review"
+//                spacing: 8
+//                anchors.left: parent.left
+//                anchors.top: parent.top
+
+//                Text {
+//                    text: "作业内容:"
+//                    color: "#888888"
+//                    font.pixelSize: 16
+//                }
+//                Text {
+//                    width: parent.width - 20
+//                    text: WorkNodeFormModel.description
+//                    color: "white"
+//                    font.pixelSize: 15
+//                    wrapMode: Text.Wrap
+//                    visible: WorkNodeFormModel.description !== ""
+//                }
+//            }
 
 
             FormCard {
             FormCard {
                 id: formCard
                 id: formCard
@@ -401,13 +403,13 @@ Rectangle {
 
 
                         onClicked: {
                         onClicked: {
                             // 审核不通过 - 也需要表单校验
                             // 审核不通过 - 也需要表单校验
-                            var formInfo = formCard.collectFormInputInfo();
-                            if (validateFormInfo(formInfo)) {
-                                httpUpdateNodeApproval.nodeId = control.currentNodeId;
-                                httpUpdateNodeApproval.approvalStatus = "rejected";
-                                httpUpdateNodeApproval.formData = formInfo;
-                                httpUpdateNodeApproval.start();
-                            }
+//                            var formInfo = formCard.collectFormInputInfo();
+//                            if (validateFormInfo(formInfo)) {
+//                                httpUpdateNodeApproval.nodeId = control.currentNodeId;
+//                                httpUpdateNodeApproval.approvalStatus = "rejected";
+//                                httpUpdateNodeApproval.formData = formInfo;
+//                                httpUpdateNodeApproval.start();
+//                            }
                         }
                         }
                     }
                     }
                 }
                 }
@@ -520,7 +522,12 @@ Rectangle {
         componentObj.visible = false;
         componentObj.visible = false;
         appAlertDialog.sourceComponent = null;
         appAlertDialog.sourceComponent = null;
         componentObj.destroy();
         componentObj.destroy();
-        // 不调用 refreshDataAndGoToList(),留在当前页
+        // 返回"我的作业"页面
+        if (JobTicketModel.rowCount() === 0) {
+            stackView.replace("components/NoJobTicketDialog.qml");
+        } else {
+            stackView.replace("JobTicketPage.qml", { autoNavigateToDetail: false });
+        }
     }
     }
     
     
     // 成功后退出系统 - 返回首页
     // 成功后退出系统 - 返回首页

+ 6 - 6
src/qml/components/JobTicketCard.qml

@@ -89,9 +89,9 @@ Rectangle {
             } else {
             } else {
                 if (WorkNodeFormModel.modelType === "inputInfo") {
                 if (WorkNodeFormModel.modelType === "inputInfo") {
                     // 录入信息
                     // 录入信息
-                    isShowNegativeBtn = true;
+                    isShowNegativeBtn = false;
                     isShowOpsitiveBtn = true;
                     isShowOpsitiveBtn = true;
-                    textNegativeBtnStr = "取消";
+//                    textNegativeBtnStr = "取消";
                     textOpsitiveBtnStr = "确认"
                     textOpsitiveBtnStr = "确认"
                     showFormCard= true;
                     showFormCard= true;
                 } else if (WorkNodeFormModel.modelType === "review") {
                 } else if (WorkNodeFormModel.modelType === "review") {
@@ -103,9 +103,9 @@ Rectangle {
                     showFormCard= true;
                     showFormCard= true;
                 } else if (WorkNodeFormModel.modelType === "confirm") {
                 } else if (WorkNodeFormModel.modelType === "confirm") {
                     // 通过
                     // 通过
-                    isShowNegativeBtn = true;
+                    isShowNegativeBtn = false;
                     isShowOpsitiveBtn = true;
                     isShowOpsitiveBtn = true;
-                    textNegativeBtnStr = "取消";
+//                    textNegativeBtnStr = "取消";
                     textOpsitiveBtnStr = "提交";
                     textOpsitiveBtnStr = "提交";
                     showFormCard= true;
                     showFormCard= true;
                 } else if (WorkNodeFormModel.modelType === "isolation") {
                 } else if (WorkNodeFormModel.modelType === "isolation") {
@@ -117,9 +117,9 @@ Rectangle {
                     showJobTicketColockProcess = true;
                     showJobTicketColockProcess = true;
                 } else if (WorkNodeFormModel.modelType === "complete") {
                 } else if (WorkNodeFormModel.modelType === "complete") {
                     // 完成/结束
                     // 完成/结束
-                    isShowNegativeBtn = true;
+                    isShowNegativeBtn = false;
                     isShowOpsitiveBtn = true;
                     isShowOpsitiveBtn = true;
-                    textNegativeBtnStr = "取消";
+//                    textNegativeBtnStr = "取消";
                     textOpsitiveBtnStr = "完成";
                     textOpsitiveBtnStr = "完成";
                     showFormCard= true;
                     showFormCard= true;
                 }
                 }

+ 15 - 3
src/qml/components/JobTicketColockProcess.qml

@@ -422,6 +422,9 @@ Rectangle {
                         anchors.horizontalCenter: parent.horizontalCenter
                         anchors.horizontalCenter: parent.horizontalCenter
                         width: 801
                         width: 801
                         height: 99
                         height: 99
+
+                        jobTicketStatusTypeName: "分配钥匙"
+                        jobTicketStatusValue: "正在分配钥匙>>"
                     }
                     }
 
 
                     JobTicketSubProcess {
                     JobTicketSubProcess {
@@ -429,6 +432,9 @@ Rectangle {
                         anchors.horizontalCenter: parent.horizontalCenter
                         anchors.horizontalCenter: parent.horizontalCenter
                         width: 801
                         width: 801
                         height: 99
                         height: 99
+
+                        jobTicketStatusTypeName: "下发作业票"
+                        jobTicketStatusValue: "正在下发作业票>>"
                     }
                     }
 
 
                     JobTicketSubProcess {
                     JobTicketSubProcess {
@@ -436,6 +442,9 @@ Rectangle {
                         anchors.horizontalCenter: parent.horizontalCenter
                         anchors.horizontalCenter: parent.horizontalCenter
                         width: 801
                         width: 801
                         height: 99
                         height: 99
+
+                        jobTicketStatusTypeName: "取出钥匙"
+                        jobTicketStatusValue: "打开钥匙扣>>"
                     }
                     }
 
 
                     JobTicketSubProcess {
                     JobTicketSubProcess {
@@ -443,6 +452,9 @@ Rectangle {
                         anchors.horizontalCenter: parent.horizontalCenter
                         anchors.horizontalCenter: parent.horizontalCenter
                         width: 801
                         width: 801
                         height: 99
                         height: 99
+
+                        jobTicketStatusTypeName: "放回钥匙"
+                        jobTicketStatusValue: "放回钥匙>>"
                     }
                     }
 
 
                     Rectangle {
                     Rectangle {
@@ -635,7 +647,7 @@ Rectangle {
 
 
     Connections {
     Connections {
         target: control.colockModel
         target: control.colockModel
-        onDataChanged: {
+        function onDataChanged() {
             var allColocked = true;
             var allColocked = true;
             for (var i = 0; i < control.colockModel.count; i++) {
             for (var i = 0; i < control.colockModel.count; i++) {
                 if (!control.colockModel.get(i).colocked) {
                 if (!control.colockModel.get(i).colocked) {
@@ -653,7 +665,7 @@ Rectangle {
 
 
     Connections {
     Connections {
         target: InteractiveCAN
         target: InteractiveCAN
-        onSignalJobTicketResult: {
+        function onSignalJobTicketResult(jsonResult, pointInfo) {
             var lockInfo = JSON.parse(jsonResult);
             var lockInfo = JSON.parse(jsonResult);
             if (!lockInfo.hasOwnProperty("data") || !Array.isArray(lockInfo.data)) {
             if (!lockInfo.hasOwnProperty("data") || !Array.isArray(lockInfo.data)) {
                 return;
                 return;
@@ -700,7 +712,7 @@ Rectangle {
             }
             }
         }
         }
         
         
-        onSignalUpdateBackLockStatus: {
+        function onSignalUpdateBackLockStatus(lockRfidList) {
             for (var i = 0; i < control.lockModel.count; i++) {
             for (var i = 0; i < control.lockModel.count; i++) {
                 for (var j = 0; j < lockRfidList.length; j++) {
                 for (var j = 0; j < lockRfidList.length; j++) {
                     if (control.lockModel.get(i).lockNfc === lockRfidList[j]) {
                     if (control.lockModel.get(i).lockNfc === lockRfidList[j]) {

+ 15 - 2
src/qml/components/JobTicketProcess.qml

@@ -211,6 +211,9 @@ Rectangle {
                         anchors.horizontalCenter: parent.horizontalCenter
                         anchors.horizontalCenter: parent.horizontalCenter
                         width: 801
                         width: 801
                         height: 99
                         height: 99
+
+                        jobTicketStatusTypeName: "分配钥匙"
+                        jobTicketStatusValue: "正在分配钥匙>>"
                     }
                     }
 
 
                     JobTicketSubProcess {
                     JobTicketSubProcess {
@@ -218,6 +221,9 @@ Rectangle {
                         anchors.horizontalCenter: parent.horizontalCenter
                         anchors.horizontalCenter: parent.horizontalCenter
                         width: 801
                         width: 801
                         height: 99
                         height: 99
+
+                        jobTicketStatusTypeName: "下发作业票"
+                        jobTicketStatusValue: "正在下发作业票>>"
                     }
                     }
 
 
                     JobTicketSubProcess {
                     JobTicketSubProcess {
@@ -225,6 +231,9 @@ Rectangle {
                         anchors.horizontalCenter: parent.horizontalCenter
                         anchors.horizontalCenter: parent.horizontalCenter
                         width: 801
                         width: 801
                         height: 99
                         height: 99
+
+                        jobTicketStatusTypeName: "取出锁"
+                        jobTicketStatusValue: "打开锁扣>>"
                     }
                     }
 
 
                     JobTicketSubProcess {
                     JobTicketSubProcess {
@@ -232,6 +241,9 @@ Rectangle {
                         anchors.horizontalCenter: parent.horizontalCenter
                         anchors.horizontalCenter: parent.horizontalCenter
                         width: 801
                         width: 801
                         height: 99
                         height: 99
+
+                        jobTicketStatusTypeName: "取出钥匙"
+                        jobTicketStatusValue: "打开钥匙扣>>"
                     }
                     }
 
 
                     Rectangle {
                     Rectangle {
@@ -609,7 +621,7 @@ Rectangle {
 
 
     Connections {
     Connections {
         target: control.colockModel
         target: control.colockModel
-        onDataChanged: {
+        function onDataChanged() {
             var allColocked = true;
             var allColocked = true;
             for (var i = 0; i < control.colockModel.count; i++) {
             for (var i = 0; i < control.colockModel.count; i++) {
                 if (!control.colockModel.get(i).colocked) {
                 if (!control.colockModel.get(i).colocked) {
@@ -627,7 +639,7 @@ Rectangle {
 
 
     Connections {
     Connections {
         target: InteractiveCAN
         target: InteractiveCAN
-        onSignalJobTicketResult: {
+        function onSignalJobTicketResult(jsonResult, pointInfo) {
             var lockInfo = JSON.parse(jsonResult);
             var lockInfo = JSON.parse(jsonResult);
             if (!lockInfo.hasOwnProperty("data") || !Array.isArray(lockInfo.data)) {
             if (!lockInfo.hasOwnProperty("data") || !Array.isArray(lockInfo.data)) {
                 return;
                 return;
@@ -759,6 +771,7 @@ Rectangle {
                 subProcess4.showSuccessfulColor = true;
                 subProcess4.showSuccessfulColor = true;
                 __sleepTimer.stop();
                 __sleepTimer.stop();
                 __successFirstStep.visible = true;
                 __successFirstStep.visible = true;
+                tabBar.currentIndex = 1;
             }
             }
         }
         }
     }
     }

+ 2 - 2
src/qml/components/JobTicketSubProcess.qml

@@ -55,7 +55,7 @@ Rectangle {
         Text {
         Text {
             id: __settingKey
             id: __settingKey
             height: 25
             height: 25
-            text: jobTicketStatusTypeName
+            text: qsTr(jobTicketStatusTypeName)
             visible: jobTicketStatusTypeName !== ""
             visible: jobTicketStatusTypeName !== ""
             color: processingColor ? showSuccessfulColor ? "green" : "#40a9ff" : iconColor
             color: processingColor ? showSuccessfulColor ? "green" : "#40a9ff" : iconColor
             font.pixelSize: 18
             font.pixelSize: 18
@@ -69,7 +69,7 @@ Rectangle {
             id: __settingValue
             id: __settingValue
             y: 32
             y: 32
             height: 26
             height: 26
-            text: jobTicketStatusValue
+            text: qsTr(jobTicketStatusValue)
             visible: jobTicketStatusValue !== ""
             visible: jobTicketStatusValue !== ""
             color: "#b3c1d1"
             color: "#b3c1d1"
             font.pixelSize: 16
             font.pixelSize: 16

+ 1 - 1
src/qml/components/MTextArea.qml

@@ -102,7 +102,7 @@ Item {
                 inputMethodHints: Qt.ImhNoPredictiveText  // 禁用系统预测输入
                 inputMethodHints: Qt.ImhNoPredictiveText  // 禁用系统预测输入
 
 
                 onActiveFocusChanged: {
                 onActiveFocusChanged: {
-                    appKeyboardVisible = activeFocus;
+//                    appKeyboardVisible = activeFocus;
                 }
                 }
 
 
                 onTextChanged: {
                 onTextChanged: {

+ 51 - 608
src/qml/main.qml

@@ -2,6 +2,7 @@ import QtQuick 2.15
 import QtQuick.Controls 2.12
 import QtQuick.Controls 2.12
 import QtQuick.Layouts 1.12
 import QtQuick.Layouts 1.12
 import QtQuick.VirtualKeyboard 2.12
 import QtQuick.VirtualKeyboard 2.12
+import QtQuick.Window 2.12
 import "."
 import "."
 import "./components"
 import "./components"
 import Loto 1.0
 import Loto 1.0
@@ -12,11 +13,11 @@ ApplicationWindow {
     width: 1920
     width: 1920
     height: 1080
     height: 1080
 
 
-    //visibility: Window.FullScreen       // 设置窗口为全屏
+    visibility: Window.FullScreen       // 设置窗口为全屏
     flags: Qt.FramelessWindowHint       // 设置窗口无边框
     flags: Qt.FramelessWindowHint       // 设置窗口无边框
 
 
     property int defaultLogoutSeconds: 120 + 1
     property int defaultLogoutSeconds: 120 + 1
-    property int startLogoutInterval: 10
+    property int startLogoutInterval: 20
 
 
     // 访问StackView
     // 访问StackView
     default property alias appStackView: stackView
     default property alias appStackView: stackView
@@ -28,6 +29,7 @@ ApplicationWindow {
     property int appLogoutSeconds: defaultLogoutSeconds
     property int appLogoutSeconds: defaultLogoutSeconds
     property bool appControlLogoutSecondsFlag: false
     property bool appControlLogoutSecondsFlag: false
     property string appLogoutText: "退出登录"
     property string appLogoutText: "退出登录"
+    property alias appHttpGetJobTickets: httpGetJobTickets
 
 
     property string logoLabelText: "博士能量隔离系统"
     property string logoLabelText: "博士能量隔离系统"
     property var advertisementImageModel: [
     property var advertisementImageModel: [
@@ -37,6 +39,8 @@ ApplicationWindow {
     ]
     ]
     property int currentIndex: 0
     property int currentIndex: 0
     property bool showHome: true
     property bool showHome: true
+    property int pressX: 0      // 记录鼠标上次位置,目的是模仿onPositionChanged事件
+    property int pressY: 0
 
 
     // ============ 首页刷卡登录相关属性 ============
     // ============ 首页刷卡登录相关属性 ============
     property bool homeCardLoginLoading: false           // 首页刷卡登录loading状态
     property bool homeCardLoginLoading: false           // 首页刷卡登录loading状态
@@ -351,6 +355,21 @@ ApplicationWindow {
         }
         }
     }
     }
 
 
+    // 作业票
+    HttpGetJobTickets {
+        id: httpGetJobTickets
+
+        Component.onCompleted: {
+            httpGetJobTickets.signalGetRequestData.connect(httpClientThread.slotGetRequestData);
+            httpClientThread.signalResponseGetJobTickets.connect(httpGetJobTickets.slotHttpResponseGetJobTickets);
+        }
+
+        Component.onDestruction: {
+            httpGetJobTickets.signalGetRequestData.disconnect(httpClientThread.slotGetRequestData);
+            httpClientThread.signalResponseGetJobTickets.disconnect(httpGetJobTickets.slotHttpResponseGetJobTickets);
+        }
+    }
+
     Item {
     Item {
         id: contentWrapper
         id: contentWrapper
         anchors.fill: parent
         anchors.fill: parent
@@ -553,612 +572,25 @@ ApplicationWindow {
         // anchors.verticalCenter: parent.verticalCenter
         // anchors.verticalCenter: parent.verticalCenter
         // anchors.horizontalCenter: parent.horizontalCenter
         // anchors.horizontalCenter: parent.horizontalCenter
     }
     }
-    
-    // ========== 归还钥匙和锁处理页面(纯静态测试)==========
-    property bool showReturnPage: false
-    
-    Rectangle {
-        id: __returnKeyLockProcess
-        x: 0
-        y: 0
-        width: 1920
-        height: 1080
-        z: 99999
-        color: "#CC000000"
-        visible: showReturnPage
-        
-        // 主容器
-        Rectangle {
-            x: 235
-            y: 106
-            width: 1450
-            height: 868
-            color: "#0D1B2A"
-            radius: 12
-            border.color: "#1E90FF"
-            border.width: 2
-            
-            // 标题栏
-            Rectangle {
-                x: 0
-                y: 0
-                width: parent.width
-                height: 60
-                color: "transparent"
-                
-                Text {
-                    anchors.centerIn: parent
-                    text: "归还锁具设备"
-                    color: "#1E90FF"
-                    font.pixelSize: 28
-                    font.bold: true
-                }
-                
-                // 关闭按钮
-                Rectangle {
-                    x: parent.width - 50
-                    y: 10
-                    width: 40
-                    height: 40
-                    radius: 8
-                    color: "#FF4D4F"
-                    Text {
-                        anchors.centerIn: parent
-                        text: "×"
-                        color: "white"
-                        font.pixelSize: 24
-                        font.bold: true
-                    }
-                    MouseArea {
-                        anchors.fill: parent
-                        onClicked: showReturnPage = false
-                    }
-                }
-            }
-            
-            // 标题分割线
-            Rectangle {
-                x: 20
-                y: 60
-                width: parent.width - 40
-                height: 1
-                color: "#1E90FF"
-                opacity: 0.5
-            }
-            
-            // 内容区域 - 可滚动
-            Flickable {
-                x: 20
-                y: 70
-                width: parent.width - 40
-                height: 580
-                clip: true
-                contentHeight: contentCol.height
-                flickableDirection: Flickable.VerticalFlick
-                
-                Column {
-                    id: contentCol
-                    width: parent.width
-                    spacing: 15
-                    
-                    // 小标题
-                    Text {
-                        text: "归还状态(按作业任务分组)"
-                        color: "#FF6B6B"
-                        font.pixelSize: 16
-                        font.bold: true
-                    }
-                    
-                    // ===== 作业任务卡片1 - 进行中(蓝色) =====
-                    Rectangle {
-                        width: parent.width
-                        height: 130
-                        color: "#1A1E90FF"
-                        radius: 8
-                        border.color: "#1E90FF"
-                        border.width: 1
-                        
-                        Column {
-                            x: 15
-                            y: 12
-                            width: parent.width - 30
-                            spacing: 10
-                            
-                            // 标题行:作业名称(主标题) + 任务名称(副标题) + 作业编号 + 发起人 + 发起时间
-                            Row {
-                                width: parent.width
-                                spacing: 20
-                                
-                                // 作业名称 - 主标题
-                                Text {
-                                    text: "1号产线停机维修作业"
-                                    color: "#1E90FF"
-                                    font.pixelSize: 16
-                                    font.bold: true
-                                }
-                                
-                                // 任务名称 - 副标题
-                                Text {
-                                    text: "电机隔离"
-                                    color: "#AAAAAA"
-                                    font.pixelSize: 14
-                                }
-                                
-                                // 作业编号 - 小号字体
-                                Text {
-                                    text: "ZY-2024-001234"
-                                    color: "#888888"
-                                    font.pixelSize: 12
-                                }
-                                
-                                // 发起人 - 小号字体
-                                Text {
-                                    text: "张三"
-                                    color: "#888888"
-                                    font.pixelSize: 12
-                                }
-                                
-                                // 发起时间 - 小号字体
-                                Text {
-                                    text: "2024-01-28 10:00"
-                                    color: "#888888"
-                                    font.pixelSize: 12
-                                }
-                                
-                                // 状态标签
-                                Rectangle {
-                                    width: 55
-                                    height: 20
-                                    radius: 3
-                                    color: "#1E90FF"
-                                    Text {
-                                        anchors.centerIn: parent
-                                        text: "进行中"
-                                        color: "white"
-                                        font.pixelSize: 11
-                                    }
-                                }
-                            }
-                            
-                            // 设备列表 - 横向排列
-                            Row {
-                                width: parent.width
-                                spacing: 25
-                                y: 5
-                                
-                                // 钥匙1
-                                Row {
-                                    spacing: 8
-                                    Rectangle {
-                                        width: 22; height: 22; radius: 11; color: "#FF4D4F"
-                                        Text { anchors.centerIn: parent; text: "✗"; color: "white"; font.pixelSize: 12; font.bold: true }
-                                    }
-                                    Text { text: "钥匙"; color: "white"; font.pixelSize: 13; font.bold: true }
-                                    Text { text: "归还失败"; color: "#FF4D4F"; font.pixelSize: 12 }
-                                }
-                                
-                                // 锁1
-                                Row {
-                                    spacing: 8
-                                    Rectangle {
-                                        width: 22; height: 22; radius: 11; color: "#FF4D4F"
-                                        Text { anchors.centerIn: parent; text: "✗"; color: "white"; font.pixelSize: 12; font.bold: true }
-                                    }
-                                    Text { text: "锁1"; color: "white"; font.pixelSize: 13; font.bold: true }
-                                    Text { text: "归还失败"; color: "#FF4D4F"; font.pixelSize: 12 }
-                                }
-                                
-                                // 锁2
-                                Row {
-                                    spacing: 8
-                                    Rectangle {
-                                        width: 22; height: 22; radius: 11; color: "#FF4D4F"
-                                        Text { anchors.centerIn: parent; text: "✗"; color: "white"; font.pixelSize: 12; font.bold: true }
-                                    }
-                                    Text { text: "锁2"; color: "white"; font.pixelSize: 13; font.bold: true }
-                                    Text { text: "归还失败"; color: "#FF4D4F"; font.pixelSize: 12 }
-                                }
-                            }
-                        }
-                    }
-                    
-                    // ===== 作业任务卡片2 - 已完成(绿色) =====
-                    Rectangle {
-                        width: parent.width
-                        height: 130
-                        color: "#1A52C41A"
-                        radius: 8
-                        border.color: "#52C41A"
-                        border.width: 1
-                        
-                        Column {
-                            x: 15
-                            y: 12
-                            width: parent.width - 30
-                            spacing: 10
-                            
-                            // 标题行
-                            Row {
-                                width: parent.width
-                                spacing: 20
-                                
-                                Text {
-                                    text: "2号产线设备维护作业"
-                                    color: "#52C41A"
-                                    font.pixelSize: 16
-                                    font.bold: true
-                                }
-                                
-                                Text {
-                                    text: "开关柜检修"
-                                    color: "#AAAAAA"
-                                    font.pixelSize: 14
-                                }
-                                
-                                Text {
-                                    text: "ZY-2024-005678"
-                                    color: "#888888"
-                                    font.pixelSize: 12
-                                }
-                                
-                                Text {
-                                    text: "李四"
-                                    color: "#888888"
-                                    font.pixelSize: 12
-                                }
-                                
-                                Text {
-                                    text: "2024-01-28 09:30"
-                                    color: "#888888"
-                                    font.pixelSize: 12
-                                }
-                                
-                                Rectangle {
-                                    width: 55
-                                    height: 20
-                                    radius: 3
-                                    color: "#52C41A"
-                                    Text {
-                                        anchors.centerIn: parent
-                                        text: "已完成"
-                                        color: "white"
-                                        font.pixelSize: 11
-                                    }
-                                }
-                            }
-                            
-                            Row {
-                                width: parent.width
-                                spacing: 25
-                                y: 5
-                                
-                                Row {
-                                    spacing: 8
-                                    Rectangle {
-                                        width: 22; height: 22; radius: 11; color: "#52C41A"
-                                        Text { anchors.centerIn: parent; text: "✓"; color: "white"; font.pixelSize: 12; font.bold: true }
-                                    }
-                                    Text { text: "钥匙"; color: "white"; font.pixelSize: 13; font.bold: true }
-                                    Text { text: "归还成功"; color: "#52C41A"; font.pixelSize: 12 }
-                                }
-                                
-                                Row {
-                                    spacing: 8
-                                    Rectangle {
-                                        width: 22; height: 22; radius: 11; color: "#52C41A"
-                                        Text { anchors.centerIn: parent; text: "✓"; color: "white"; font.pixelSize: 12; font.bold: true }
-                                    }
-                                    Text { text: "锁1"; color: "white"; font.pixelSize: 13; font.bold: true }
-                                    Text { text: "归还成功"; color: "#52C41A"; font.pixelSize: 12 }
-                                }
-                            }
-                        }
-                    }
-                    
-                    // ===== 设备异常卡片 (橙色) =====
-                    Rectangle {
-                        width: parent.width
-                        height: 100
-                        color: "#1AFF9800"
-                        radius: 8
-                        border.color: "#FF9800"
-                        border.width: 1
-                        
-                        Column {
-                            x: 15
-                            y: 12
-                            width: parent.width - 30
-                            spacing: 10
-                            
-                            Row {
-                                width: parent.width
-                                spacing: 20
-                                
-                                Text {
-                                    text: "设备异常"
-                                    color: "#FF9800"
-                                    font.pixelSize: 16
-                                    font.bold: true
-                                }
-                                
-                                Text {
-                                    text: "无法读取NFC信息"
-                                    color: "#AAAAAA"
-                                    font.pixelSize: 14
-                                }
-                                
-                                Rectangle {
-                                    width: 70
-                                    height: 20
-                                    radius: 3
-                                    color: "#FF9800"
-                                    Text {
-                                        anchors.centerIn: parent
-                                        text: "需处理"
-                                        color: "white"
-                                        font.pixelSize: 11
-                                    }
-                                }
-                            }
-                            
-                            Row {
-                                width: parent.width
-                                spacing: 25
-                                y: 5
-                                
-                                Row {
-                                    spacing: 8
-                                    Rectangle {
-                                        width: 22; height: 22; radius: 11; color: "#FF9800"
-                                        Text { anchors.centerIn: parent; text: "!"; color: "white"; font.pixelSize: 12; font.bold: true }
-                                    }
-                                    Text { text: "插槽3"; color: "white"; font.pixelSize: 13; font.bold: true }
-                                    Text { text: "归还失败"; color: "#FF9800"; font.pixelSize: 12 }
-                                }
-                            }
-                        }
-                    }
-                    
-                    // ===== 无作业任务卡片 (灰色) =====
-                    Rectangle {
-                        width: parent.width
-                        height: 100
-                        color: "#1A888888"
-                        radius: 8
-                        border.color: "#888888"
-                        border.width: 1
-                        
-                        Column {
-                            x: 15
-                            y: 12
-                            width: parent.width - 30
-                            spacing: 10
-                            
-                            Row {
-                                width: parent.width
-                                spacing: 20
-                                
-                                Text {
-                                    text: "无作业任务"
-                                    color: "#888888"
-                                    font.pixelSize: 16
-                                    font.bold: true
-                                }
-                                
-                                Text {
-                                    text: "未关联到任何作业"
-                                    color: "#AAAAAA"
-                                    font.pixelSize: 14
-                                }
-                                
-                                Rectangle {
-                                    width: 70
-                                    height: 20
-                                    radius: 3
-                                    color: "#888888"
-                                    Text {
-                                        anchors.centerIn: parent
-                                        text: "无关联"
-                                        color: "white"
-                                        font.pixelSize: 11
-                                    }
-                                }
-                            }
-                            
-                            Row {
-                                width: parent.width
-                                spacing: 25
-                                y: 5
-                                
-                                Row {
-                                    spacing: 8
-                                    Rectangle {
-                                        width: 22; height: 22; radius: 11; color: "#52C41A"
-                                        Text { anchors.centerIn: parent; text: "✓"; color: "white"; font.pixelSize: 12; font.bold: true }
-                                    }
-                                    Text { text: "钥匙"; color: "white"; font.pixelSize: 13; font.bold: true }
-                                    Text { text: "归还成功"; color: "#52C41A"; font.pixelSize: 12 }
-                                }
-                                
-                                Row {
-                                    spacing: 8
-                                    Rectangle {
-                                        width: 22; height: 22; radius: 11; color: "#52C41A"
-                                        Text { anchors.centerIn: parent; text: "✓"; color: "white"; font.pixelSize: 12; font.bold: true }
-                                    }
-                                    Text { text: "锁1"; color: "white"; font.pixelSize: 13; font.bold: true }
-                                    Text { text: "归还成功"; color: "#52C41A"; font.pixelSize: 12 }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-            
-            // 底部分割线
-            Rectangle {
-                x: 20
-                y: 660
-                width: parent.width - 40
-                height: 1
-                color: "#1E90FF"
-                opacity: 0.3
-            }
-            
-            // 底部统计
-            Row {
-                x: 30
-                y: 675
-                spacing: 50
-                
-                Column {
-                    Text { text: "作业任务"; color: "#888888"; font.pixelSize: 12 }
-                    Text { text: "2"; color: "white"; font.pixelSize: 26; font.bold: true }
-                }
-                Column {
-                    Text { text: "钥匙总数"; color: "#888888"; font.pixelSize: 12 }
-                    Text { text: "3"; color: "white"; font.pixelSize: 26; font.bold: true }
-                }
-                Column {
-                    Text { text: "钥匙成功"; color: "#888888"; font.pixelSize: 12 }
-                    Text { text: "3"; color: "#52C41A"; font.pixelSize: 26; font.bold: true }
-                }
-                Column {
-                    Text { text: "钥匙失败"; color: "#888888"; font.pixelSize: 12 }
-                    Text { text: "0"; color: "#FF4D4F"; font.pixelSize: 26; font.bold: true }
-                }
-                Column {
-                    Text { text: "锁总数"; color: "#888888"; font.pixelSize: 12 }
-                    Text { text: "4"; color: "white"; font.pixelSize: 26; font.bold: true }
-                }
-                Column {
-                    Text { text: "锁成功"; color: "#888888"; font.pixelSize: 12 }
-                    Text { text: "3"; color: "#52C41A"; font.pixelSize: 26; font.bold: true }
-                }
-                Column {
-                    Text { text: "锁失败"; color: "#888888"; font.pixelSize: 12 }
-                    Text { text: "1"; color: "#FF4D4F"; font.pixelSize: 26; font.bold: true }
-                }
-                Column {
-                    Text { text: "设备异常"; color: "#888888"; font.pixelSize: 12 }
-                    Text { text: "1"; color: "#FF9800"; font.pixelSize: 26; font.bold: true }
-                }
-            }
-            
-            // 底部按钮
-            Row {
-                anchors.bottom: parent.bottom
-                anchors.bottomMargin: 20
-                anchors.horizontalCenter: parent.horizontalCenter
-                spacing: 25
-                
-                // 取出失败设备按钮
-                Rectangle {
-                    width: 240
-                    height: 45
-                    radius: 6
-                    color: "transparent"
-                    border.color: "#FF4D4F"
-                    border.width: 2
-                    
-                    Text {
-                        anchors.centerIn: parent
-                        text: "取出归还失败的设备"
-                        color: "#FF4D4F"
-                        font.pixelSize: 16
-                    }
-                    
-                    MouseArea {
-                        anchors.fill: parent
-                        onClicked: console.log("取出失败设备")
-                    }
-                }
-                
-                // 确认归还按钮
-                Rectangle {
-                    width: 180
-                    height: 45
-                    radius: 6
-                    color: "#1890FF"
-                    
-                    Row {
-                        anchors.centerIn: parent
-                        spacing: 8
-                        
-                        Text {
-                            text: "确认归还"
-                            color: "white"
-                            font.pixelSize: 16
-                        }
-                        
-                        Rectangle {
-                            width: 40
-                            height: 24
-                            radius: 12
-                            color: "#FF6B6B"
-                            
-                            Text {
-                                anchors.centerIn: parent
-                                text: "10s"
-                                color: "white"
-                                font.pixelSize: 11
-                            }
-                        }
-                    }
-                    
-                    MouseArea {
-                        anchors.fill: parent
-                        onClicked: showReturnPage = false
-                    }
-                }
-            }
-        }
-        
-        // 背景点击阻止穿透
-        MouseArea {
-            anchors.fill: parent
-            z: -1
-            onClicked: {}
-        }
-    }
-    
-    // ESC关闭弹窗
-    Shortcut {
-        sequence: "Escape"
-        onActivated: {
-            if (showReturnPage) {
-                console.log("[main.qml] ESC关闭静态弹窗");
-                showReturnPage = false;
-            }
-        }
-    }
-    
-    // F1 显示静态页面
-    Shortcut {
-        sequence: "F1"
-        onActivated: {
-            console.log("[main.qml] F1 显示静态归还页面");
-            showReturnPage = true;
-        }
-    }
-    // F2 也显示
-    Shortcut {
-        sequence: "F2"
-        onActivated: {
-            console.log("[main.qml] F2 显示静态归还页面");
-            showReturnPage = true;
-        }
-    }
-    // F3 关闭
-    Shortcut {
-        sequence: "F3"
-        onActivated: {
-            console.log("[main.qml] F3 关闭静态归还页面");
-            showReturnPage = false;
-        }
-    }
-    // ============================================
 
 
+//    Loader {
+//        id: __returnKeyLockProcess
+//        visible: false
+
+//        anchors.fill: parent
+//        source: "components/ReturnKeyLockProcess.qml"
+//    }
+
+//    Connections {
+//        target: InteractiveCAN
+//        function onSignalReturnDevicesInfo(info) {
+//            if (!__returnKeyLockProcess.visible) {
+//                __returnKeyLockProcess.visible = true;
+//            }
+//            __returnKeyLockProcess.item.deviceInfo = info;
+//        }
+//    }
+    
     Timer {
     Timer {
         id: swipeTimer
         id: swipeTimer
         interval: 3000
         interval: 3000
@@ -1244,13 +676,24 @@ ApplicationWindow {
         hoverEnabled: true
         hoverEnabled: true
 
 
         onPositionChanged: {
         onPositionChanged: {
+            // 滑动屏幕重新计时
             __startLogoutTimer.restart();
             __startLogoutTimer.restart();
             appControlLogoutSecondsFlag = false
             appControlLogoutSecondsFlag = false
             appLogoutSeconds = defaultLogoutSeconds;
             appLogoutSeconds = defaultLogoutSeconds;
         }
         }
 
 
         onClicked: function(mouse) {mouse.accepted = false;}
         onClicked: function(mouse) {mouse.accepted = false;}
-        onPressed: function(mouse) {mouse.accepted = false;}
+        onPressed: function(mouse) {
+            if (appWindow.pressX !== mouse.x || appWindow.pressY !== mouse.y) {
+                // 模仿onPositionChanged事件
+                __startLogoutTimer.restart();
+                appControlLogoutSecondsFlag = false
+                appLogoutSeconds = defaultLogoutSeconds;
+            }
+            appWindow.pressX = mouse.x;
+            appWindow.pressY = mouse.y;
+            mouse.accepted = false;
+        }
         onReleased: function(mouse) {mouse.accepted = false;}
         onReleased: function(mouse) {mouse.accepted = false;}
         onWheel: function(mouse) {mouse.accepted = false;}
         onWheel: function(mouse) {mouse.accepted = false;}
         onDoubleClicked: function(mouse) {mouse.accepted = false;}
         onDoubleClicked: function(mouse) {mouse.accepted = false;}

+ 5 - 2
src/usr/BluetoothClient.cpp

@@ -204,11 +204,10 @@ void BLEClient::connectDevice(const QString& macAddress, const QString& name)
     // 释放旧控制器
     // 释放旧控制器
     if (m_leController) {
     if (m_leController) {
         m_leController->disconnectFromDevice();
         m_leController->disconnectFromDevice();
-        delete m_leController;
         m_leController = nullptr;
         m_leController = nullptr;
     }
     }
     if (m_targetService) {
     if (m_targetService) {
-        delete m_targetService;
+//        delete m_targetService;
         m_targetService = nullptr;
         m_targetService = nullptr;
     }
     }
 
 
@@ -222,6 +221,7 @@ void BLEClient::connectDevice(const QString& macAddress, const QString& name)
     m_leController = QLowEnergyController::createCentral(addr, localDev.address(), this);
     m_leController = QLowEnergyController::createCentral(addr, localDev.address(), this);
 
 
     if (!m_leController) {
     if (!m_leController) {
+        qDebug() << "[BLEClient::connectDevice]: 创建蓝牙控制器失败";
         emit connectStateChanged(QLowEnergyController::UnconnectedState, "创建蓝牙控制器失败");
         emit connectStateChanged(QLowEnergyController::UnconnectedState, "创建蓝牙控制器失败");
         return;
         return;
     }
     }
@@ -248,6 +248,9 @@ void BLEClient::connectDevice(const QString& macAddress, const QString& name)
                                          .arg(m_leController->errorString());
                                          .arg(m_leController->errorString());
                     qWarning() << "[BLE] 控制器错误:" << errMsg;
                     qWarning() << "[BLE] 控制器错误:" << errMsg;
 //                    releaseBluetoothResource();
 //                    releaseBluetoothResource();
+                    disconnectDevice();
+                    msleep(3000);
+                    emit signalFailConnect();
                     emit connectStateChanged(QLowEnergyController::UnconnectedState, errMsg);
                     emit connectStateChanged(QLowEnergyController::UnconnectedState, errMsg);
                 });
                 });
 
 

+ 1 - 0
src/usr/BluetoothClient.h

@@ -173,6 +173,7 @@ signals:
     void cmdSendResult(bool success, const QString& cmdName, const QString& msg);
     void cmdSendResult(bool success, const QString& cmdName, const QString& msg);
 signals:
 signals:
     void signalSendJobTicketStatus(bool success);
     void signalSendJobTicketStatus(bool success);
+    void signalFailConnect();
 private slots:
 private slots:
     // 蓝牙扫描结果
     // 蓝牙扫描结果
     void onDeviceDiscovered(const QBluetoothDeviceInfo& device);
     void onDeviceDiscovered(const QBluetoothDeviceInfo& device);

+ 42 - 71
src/usr/CANClient.cpp

@@ -46,12 +46,14 @@ std::string hexToString(uint16_t hex) {
 
 
 // 模式2: 虚拟CAN(无硬件纯软件测试)
 // 模式2: 虚拟CAN(无硬件纯软件测试)
 //        使用前需执行: sudo modprobe vcan && sudo ip link add dev can0 type vcan && sudo ip link set up can0
 //        使用前需执行: sudo modprobe vcan && sudo ip link add dev can0 type vcan && sudo ip link set up can0
-#define CAN_MODE_VIRTUAL
+//#define CAN_MODE_VIRTUAL
 
 
 // 模式3: 物理CAN(生产环境,板载CAN控制器)
 // 模式3: 物理CAN(生产环境,板载CAN控制器)
-// #define CAN_MODE_PHYSICAL
+ #define CAN_MODE_PHYSICAL
 // ============================================
 // ============================================
 
 
+CANReturnKeyDevices CANClient::returnDevicesInfo;
+
 CANClient::CANClient(QObject *parent)
 CANClient::CANClient(QObject *parent)
     : QThread(parent)
     : QThread(parent)
 {
 {
@@ -257,31 +259,19 @@ void CANClient::bitrateItemInit()
 
 
 void CANClient::receivedFrames()
 void CANClient::receivedFrames()
 {
 {
-    qDebug() << "[CAN] receivedFrames() 被调用";
-    
-    // 先收集所有帧(在锁内)
-    QList<QCanBusFrame> frames;
-    {
-        QMutexLocker locker(&m_mutex);
-        if (!m_CanDevice || m_CanDevice->state() == QCanBusDevice::UnconnectedState) {
-            qWarning() << "[CAN] 设备未连接,忽略帧";
-            return;
-        }
-
-        while (m_CanDevice && m_CanDevice->framesAvailable()) {
-            frames.append(m_CanDevice->readFrame());
-        }
+//    qDebug() << "[CAN] receivedFrames() 被调用";
+    QMutexLocker locker(&m_mutex);
+    if (!m_CanDevice || m_CanDevice->state() == QCanBusDevice::UnconnectedState) {
+        return;
     }
     }
-    
-    // 处理帧(在锁外,避免死锁)
-    for (const QCanBusFrame& respFrame : frames) {
-        qDebug() << "[CAN] 读取到帧";
-        
+
+    // 异步读取所有帧,无阻塞
+    while (m_CanDevice && m_CanDevice->framesAvailable()) {
+        QCanBusFrame respFrame = m_CanDevice->readFrame();
         // ========== 检测设备主动上报的NFC数据(归还流程) ==========
         // ========== 检测设备主动上报的NFC数据(归还流程) ==========
         // 当CAN设备检测到钥匙/锁插入时,会主动发送包含NFC卡号的帧
         // 当CAN设备检测到钥匙/锁插入时,会主动发送包含NFC卡号的帧
-        handleDeviceInsertionFrame(respFrame);
+//        handleDeviceInsertionFrame(respFrame);
         // =========================================================
         // =========================================================
-
         // 匹配请求并执行回调
         // 匹配请求并执行回调
         QMutexLocker reqLocker(&m_requestMutex);
         QMutexLocker reqLocker(&m_requestMutex);
         if (!m_requestMap.isEmpty()) {
         if (!m_requestMap.isEmpty()) {
@@ -404,47 +394,7 @@ void CANClient::slotUpdateKeyBaseStatus(quint8 nodeId, const CANKeyBaseStatus &s
     if (!status.success) return;
     if (!status.success) return;
 
 
     QMutexLocker locker(&m_insertDataMutex);
     QMutexLocker locker(&m_insertDataMutex);
-    
-    // ========== 检测钥匙插入(用于归还流程) ==========
-    bool prevLeftHasKey = false;
-    bool prevRightHasKey = false;
-    
-    if (m_keyBaseStatus.find(nodeId) != m_keyBaseStatus.end()) {
-        prevLeftHasKey = m_keyBaseStatus[nodeId].leftHasKey;
-        prevRightHasKey = m_keyBaseStatus[nodeId].rightHasKey;
-    }
-    
-    // 检测左钥匙插入(从无到有)
-    if (!prevLeftHasKey && status.leftHasKey) {
-        qInfo() << "[归还检测] 检测到左钥匙插入!";
-        // 获取左钥匙NFC卡号
-        if (m_keyRFIDStatus.find(nodeId) != m_keyRFIDStatus.end() && 
-            !m_keyRFIDStatus[nodeId].leftKeyRFID.isEmpty() &&
-            m_keyRFIDStatus[nodeId].leftKeyRFID != "00000000") {
-            qInfo() << "[归还检测] 左钥匙NFC卡号:" << m_keyRFIDStatus[nodeId].leftKeyRFID;
-            emit nfcDeviceDetected(m_keyRFIDStatus[nodeId].leftKeyRFID, "key", 0);
-        } else {
-            qWarning() << "[归还检测] 左钥匙存在但无法读取NFC";
-            emit nfcDeviceError("key", 0);
-        }
-    }
-    
-    // 检测右钥匙插入(从无到有)
-    if (!prevRightHasKey && status.rightHasKey) {
-        qInfo() << "[归还检测] 检测到右钥匙插入!";
-        // 获取右钥匙NFC卡号
-        if (m_keyRFIDStatus.find(nodeId) != m_keyRFIDStatus.end() && 
-            !m_keyRFIDStatus[nodeId].rightKeyRFID.isEmpty() &&
-            m_keyRFIDStatus[nodeId].rightKeyRFID != "00000000") {
-            qInfo() << "[归还检测] 右钥匙NFC卡号:" << m_keyRFIDStatus[nodeId].rightKeyRFID;
-            emit nfcDeviceDetected(m_keyRFIDStatus[nodeId].rightKeyRFID, "key", 1);
-        } else {
-            qWarning() << "[归还检测] 右钥匙存在但无法读取NFC";
-            emit nfcDeviceError("key", 1);
-        }
-    }
-    // ====================================================
-    
+
     if (m_keyBaseStatus.find(nodeId) == m_keyBaseStatus.end()) {
     if (m_keyBaseStatus.find(nodeId) == m_keyBaseStatus.end()) {
         m_keyBaseStatus.insert(nodeId, status);
         m_keyBaseStatus.insert(nodeId, status);
     }
     }
@@ -471,6 +421,12 @@ void CANClient::slotUpdateKeyBaseControl(quint8 nodeId, const CANKeyBaseControlS
         writeStatus.leftChargeEnable = true;
         writeStatus.leftChargeEnable = true;
         writeStatus.leftChargeState = ChargeState::Charging;
         writeStatus.leftChargeState = ChargeState::Charging;
         isWrite = true;
         isWrite = true;
+
+        if (m_keyRFIDStatus.find(nodeId) != m_keyRFIDStatus.end()) {
+            QString rightKeyRFID = m_keyRFIDStatus[nodeId].rightKeyRFID;
+            returnDevicesInfo.keysMap.insert(rightKeyRFID, nodeId);
+            emit signalReturnKey();
+        }
     }
     }
     if (m_keyBaseStatus[nodeId].rightHasKey && !status.rightLocked) {
     if (m_keyBaseStatus[nodeId].rightHasKey && !status.rightLocked) {
         writeStatus.rightLocked = true;
         writeStatus.rightLocked = true;
@@ -478,6 +434,12 @@ void CANClient::slotUpdateKeyBaseControl(quint8 nodeId, const CANKeyBaseControlS
         writeStatus.rightChargeEnable = true;
         writeStatus.rightChargeEnable = true;
         writeStatus.rightChargeState = ChargeState::Charging;
         writeStatus.rightChargeState = ChargeState::Charging;
         isWrite = true;
         isWrite = true;
+
+        if (m_keyRFIDStatus.find(nodeId) != m_keyRFIDStatus.end()) {
+            QString rightKeyRFID = m_keyRFIDStatus[nodeId].rightKeyRFID;
+            returnDevicesInfo.keysMap.insert(rightKeyRFID, nodeId);
+            emit signalReturnKey();
+        }
     }
     }
 
 
     if (isWrite) {
     if (isWrite) {
@@ -492,7 +454,6 @@ void CANClient::slotUpdateLockedStatus(quint8 nodeId, const CANLocksControl &sta
 
 
     QMutexLocker locker(&m_insertDataMutex);
     QMutexLocker locker(&m_insertDataMutex);
     m_locksControl.insert(nodeId, status);
     m_locksControl.insert(nodeId, status);
-
     if (m_locksControlStatus.find(nodeId) == m_locksControlStatus.end()) return;
     if (m_locksControlStatus.find(nodeId) == m_locksControlStatus.end()) return;
 
 
     bool isWrite = false;
     bool isWrite = false;
@@ -507,6 +468,14 @@ void CANClient::slotUpdateLockedStatus(quint8 nodeId, const CANLocksControl &sta
             writeStatus.lockLockedMap.insert(lockNum, true);
             writeStatus.lockLockedMap.insert(lockNum, true);
             writeStatus.lockWorkMap.insert(lockNum, true);
             writeStatus.lockWorkMap.insert(lockNum, true);
             isWrite = true;
             isWrite = true;
+
+            if (m_locksRFIDStatus.find(nodeId) != m_locksRFIDStatus.end()) {
+                QMap<int, QString> lockRFIDInfo = m_locksRFIDStatus[nodeId].lockRFIDMap;
+                if (lockRFIDInfo.find(lockNum) != lockRFIDInfo.end()) {
+                    returnDevicesInfo.locksMap.insert(lockRFIDInfo[lockNum], nodeId);
+                    emit signalReturnKey();
+                }
+            }
         }
         }
     }
     }
     if (isWrite) {
     if (isWrite) {
@@ -573,14 +542,14 @@ void CANClient::sendFrameAsync(const QCanBusFrame& frame, CANResponseCallback ca
 
 
     // 发送帧(异步,无阻塞)
     // 发送帧(异步,无阻塞)
     if (!m_CanDevice->writeFrame(frame)) {
     if (!m_CanDevice->writeFrame(frame)) {
-        qWarning() << "[Send] 发送失败:" << m_CanDevice->errorString();
+        qWarning() << "[Send] 发送失败:" << m_CanDevice->errorString() << QString::number(frame.frameId(), 16) << frame.payload().toHex().toUpper();
         m_requestMap.remove(requestKey);
         m_requestMap.remove(requestKey);
         callback(QCanBusFrame());
         callback(QCanBusFrame());
         return;
         return;
     }
     }
 
 
-    // 存储帧ID和请求ID的映射(简化版:实际可扩展为帧+ID映射)
-    Q_UNUSED(requestId); // 此处简化,实际可通过帧内容关联requestId
+    // 存储帧ID和请求ID的映射
+    Q_UNUSED(requestId);
 }
 }
 
 
 QCanBusFrame CANClient::buildReadFrame(quint8 nodeId, quint16 index, quint8 subIndex)
 QCanBusFrame CANClient::buildReadFrame(quint8 nodeId, quint16 index, quint8 subIndex)
@@ -962,7 +931,9 @@ void CANClient::readLockStatusAsync()
                         !m_locksRFIDStatus[nodeId].lockRFIDMap[i].isEmpty() &&
                         !m_locksRFIDStatus[nodeId].lockRFIDMap[i].isEmpty() &&
                         m_locksRFIDStatus[nodeId].lockRFIDMap[i] != "00000000") {
                         m_locksRFIDStatus[nodeId].lockRFIDMap[i] != "00000000") {
                         qInfo() << "[归还检测]" << (i+1) << "号锁NFC卡号:" << m_locksRFIDStatus[nodeId].lockRFIDMap[i];
                         qInfo() << "[归还检测]" << (i+1) << "号锁NFC卡号:" << m_locksRFIDStatus[nodeId].lockRFIDMap[i];
+
                         emit nfcDeviceDetected(m_locksRFIDStatus[nodeId].lockRFIDMap[i], "lock", i);
                         emit nfcDeviceDetected(m_locksRFIDStatus[nodeId].lockRFIDMap[i], "lock", i);
+                        emit signalLockNfcDeviceDetected(m_locksRFIDStatus[nodeId].lockRFIDMap[i]);
                     } else {
                     } else {
                         qWarning() << "[归还检测]" << (i+1) << "号锁存在但无法读取NFC";
                         qWarning() << "[归还检测]" << (i+1) << "号锁存在但无法读取NFC";
                         emit nfcDeviceError("lock", i);
                         emit nfcDeviceError("lock", i);
@@ -1125,9 +1096,9 @@ void CANClient::writeLockBuckleAsync(const CANLocksControl &status)
                     lockRfids.append(lockRfidMap[lockNum]);
                     lockRfids.append(lockRfidMap[lockNum]);
                 }
                 }
             }
             }
-//            for (int i = 0 ; i < status.lockNums.length(); i++) {
-//                qInfo() << "[Lock] " << status.lockNums[i] << "号锁扣:" << (status.lockLockedMap[status.lockNums[i]] ? "锁住" : "解锁");
-//            }
+            for (int i = 0 ; i < status.lockNums.length(); i++) {
+                qInfo() << "[Lock] " << status.lockNums[i] << "号锁扣:" << (status.lockLockedMap[status.lockNums[i]] ? "锁住" : "解锁");
+            }
         }
         }
         else {
         else {
             for (int i = 0 ; i < status.lockNums.length(); i++) {
             for (int i = 0 ; i < status.lockNums.length(); i++) {

+ 10 - 0
src/usr/CANClient.h

@@ -99,6 +99,12 @@ typedef struct {
 } CANKeyBaseChargeStatus;
 } CANKeyBaseChargeStatus;
 Q_DECLARE_METATYPE(CANKeyBaseChargeStatus)
 Q_DECLARE_METATYPE(CANKeyBaseChargeStatus)
 
 
+typedef struct {
+    QMap<QString, quint8> keysMap;
+    QMap<QString, quint8> locksMap;
+} CANReturnKeyDevices;
+Q_DECLARE_METATYPE(CANReturnKeyDevices)
+
 class CANClient : public QThread
 class CANClient : public QThread
 {
 {
     Q_OBJECT
     Q_OBJECT
@@ -205,10 +211,12 @@ signals:
     // ========== 归还钥匙和锁检测信号 ==========
     // ========== 归还钥匙和锁检测信号 ==========
     // 当检测到NFC设备插入时发出(用于归还流程)
     // 当检测到NFC设备插入时发出(用于归还流程)
     void nfcDeviceDetected(const QString& nfcId, const QString& deviceType, int slotIndex);
     void nfcDeviceDetected(const QString& nfcId, const QString& deviceType, int slotIndex);
+    void signalLockNfcDeviceDetected(const QString& nfcId);
     // 当检测到设备异常时发出(无法读取NFC)
     // 当检测到设备异常时发出(无法读取NFC)
     void nfcDeviceError(const QString& deviceType, int slotIndex);
     void nfcDeviceError(const QString& deviceType, int slotIndex);
     // ==========================================
     // ==========================================
     
     
+    void signalReturnKey();
 private:
 private:
     // 处理设备主动上报的插入帧(归还流程)
     // 处理设备主动上报的插入帧(归还流程)
     void handleDeviceInsertionFrame(const QCanBusFrame& frame);
     void handleDeviceInsertionFrame(const QCanBusFrame& frame);
@@ -291,6 +299,8 @@ public:
     bool unlockLocks(const QList<int>& lockNums);
     bool unlockLocks(const QList<int>& lockNums);
 
 
     bool lockingEKey(quint8 nodeId, bool leftKey, bool rightKey);
     bool lockingEKey(quint8 nodeId, bool leftKey, bool rightKey);
+public:
+    static CANReturnKeyDevices returnDevicesInfo;
 private:
 private:
     bool m_threadstatus = true;          // 线程运行状态标志
     bool m_threadstatus = true;          // 线程运行状态标志
     mutable QMutex m_mutex;              // 线程安全锁(mutable允许const函数修改)
     mutable QMutex m_mutex;              // 线程安全锁(mutable允许const函数修改)