wzbs hace 1 mes
padre
commit
90b28d835b
Se han modificado 100 ficheros con 12929 adiciones y 0 borrados
  1. 1 0
      .gitignore
  2. 165 0
      CMakeLists.txt
  3. 755 0
      CMakeLists.txt.user
  4. 143 0
      CMakeLists.txt.xIkHXX
  5. 142 0
      Interactive/DataListModel.cpp
  6. 42 0
      Interactive/DataListModel.h
  7. 64 0
      Interactive/InteractiveConf.cpp
  8. 33 0
      Interactive/InteractiveConf.h
  9. 97 0
      Interactive/InteractiveCore.cpp
  10. 37 0
      Interactive/InteractiveCore.h
  11. 99 0
      Interactive/InteractiveData.cpp
  12. 156 0
      Interactive/InteractiveData.h
  13. 413 0
      Interactive/InteractiveFace.cpp
  14. 129 0
      Interactive/InteractiveFace.h
  15. 129 0
      Interactive/InteractiveHand.cpp
  16. 91 0
      Interactive/InteractiveHand.h
  17. 595 0
      Interactive/InteractiveHttp.cpp
  18. 133 0
      Interactive/InteractiveHttp.h
  19. 6 0
      Interactive/InteractiveTask.cpp
  20. 73 0
      Interactive/InteractiveTask.h
  21. 244 0
      Interactive/InteractiveWork.cpp
  22. 35 0
      Interactive/InteractiveWork.h
  23. 37 0
      Interactive/RunAbstract.cpp
  24. 34 0
      Interactive/RunAbstract.h
  25. 542 0
      Interactive/RunDataCacheRefresh.cpp
  26. 36 0
      Interactive/RunDataCacheRefresh.h
  27. 69 0
      Interactive/RunHttpGet_exception_type.cpp
  28. 16 0
      Interactive/RunHttpGet_exception_type.h
  29. 78 0
      Interactive/RunHttpGet_getCabinetHomePage.cpp
  30. 15 0
      Interactive/RunHttpGet_getCabinetHomePage.h
  31. 71 0
      Interactive/RunHttpGet_getInfo.cpp
  32. 15 0
      Interactive/RunHttpGet_getInfo.h
  33. 13 0
      Interactive/RunHttpGet_getInstructionsList.cpp
  34. 15 0
      Interactive/RunHttpGet_getInstructionsList.h
  35. 147 0
      Interactive/RunHttpGet_getIsMaterialsLoanExceptionPage.cpp
  36. 17 0
      Interactive/RunHttpGet_getIsMaterialsLoanExceptionPage.h
  37. 87 0
      Interactive/RunHttpGet_getIsMaterialsPage.cpp
  38. 15 0
      Interactive/RunHttpGet_getIsMaterialsPage.h
  39. 70 0
      Interactive/RunHttpGet_getLastCheckPlanByCabinetCode.cpp
  40. 16 0
      Interactive/RunHttpGet_getLastCheckPlanByCabinetCode.h
  41. 25 0
      Interactive/RunHttpGet_getSysUserCharacteristicPage.cpp
  42. 16 0
      Interactive/RunHttpGet_getSysUserCharacteristicPage.h
  43. 14 0
      Interactive/RunHttpGet_selectExMaterialTypeById.cpp
  44. 16 0
      Interactive/RunHttpGet_selectExMaterialTypeById.h
  45. 50 0
      Interactive/RunHttpGet_selectIsMaterialsCabinetByCode.cpp
  46. 16 0
      Interactive/RunHttpGet_selectIsMaterialsCabinetByCode.h
  47. 70 0
      Interactive/RunHttpGet_severity_level.cpp
  48. 15 0
      Interactive/RunHttpGet_severity_level.h
  49. 17 0
      Interactive/RunHttpPost_deleteSysUserCharacteristicByRecordIds.cpp
  50. 17 0
      Interactive/RunHttpPost_deleteSysUserCharacteristicByRecordIds.h
  51. 19 0
      Interactive/RunHttpPost_insertCheckRecord.cpp
  52. 15 0
      Interactive/RunHttpPost_insertCheckRecord.h
  53. 64 0
      Interactive/RunHttpPost_insertIsException.cpp
  54. 15 0
      Interactive/RunHttpPost_insertIsException.h
  55. 19 0
      Interactive/RunHttpPost_insertSubmitPlan.cpp
  56. 15 0
      Interactive/RunHttpPost_insertSubmitPlan.h
  57. 43 0
      Interactive/RunHttpPost_insertUserFace.cpp
  58. 15 0
      Interactive/RunHttpPost_insertUserFace.h
  59. 16 0
      Interactive/RunHttpPost_insertUserFingerprintDat.cpp
  60. 15 0
      Interactive/RunHttpPost_insertUserFingerprintDat.h
  61. 73 0
      Interactive/RunHttpPost_loginByFace.cpp
  62. 15 0
      Interactive/RunHttpPost_loginByFace.h
  63. 72 0
      Interactive/RunHttpPost_loginByFingerprintDat.cpp
  64. 15 0
      Interactive/RunHttpPost_loginByFingerprintDat.h
  65. 15 0
      Interactive/RunHttpPost_startCheckPlan.cpp
  66. 14 0
      Interactive/RunHttpPost_startCheckPlan.h
  67. 42 0
      Interactive/RunMaterialExceptionRefreshListModel.cpp
  68. 15 0
      Interactive/RunMaterialExceptionRefreshListModel.h
  69. 40 0
      Interactive/RunMaterialExceptionReport.cpp
  70. 15 0
      Interactive/RunMaterialExceptionReport.h
  71. 17 0
      Interactive/RunMaterialInfoListRefresh.cpp
  72. 21 0
      Interactive/RunMaterialInfoListRefresh.h
  73. 116 0
      Interactive/RunMaterialManualReplaceRefreshListModel.cpp
  74. 15 0
      Interactive/RunMaterialManualReplaceRefreshListModel.h
  75. 176 0
      Interactive/RunMaterialManualReplaceSubmit.cpp
  76. 15 0
      Interactive/RunMaterialManualReplaceSubmit.h
  77. 82 0
      Interactive/RunMaterialReplaceRefreshListModel.cpp
  78. 15 0
      Interactive/RunMaterialReplaceRefreshListModel.h
  79. 38 0
      Interactive/RunViewRefresh_AbnormalReport.cpp
  80. 15 0
      Interactive/RunViewRefresh_AbnormalReport.h
  81. 17 0
      Interactive/RunViewWait.cpp
  82. 15 0
      Interactive/RunViewWait.h
  83. 65 0
      Interactive/template_singleton.h
  84. 35 0
      content/App.qml
  85. 14 0
      content/CMakeLists.txt
  86. 237 0
      content/FacialRecognition.qml
  87. 128 0
      content/HangPromptBox.qml
  88. 196 0
      content/InfoPromptBox.qml
  89. 862 0
      content/Login.qml
  90. 645 0
      content/MainScreen.qml
  91. 1387 0
      content/MaterialCheckForm.qml
  92. 743 0
      content/MaterialCheckPlan.qml
  93. 464 0
      content/MaterialCheckSave.qml
  94. 391 0
      content/MaterialCheckSign.qml
  95. 488 0
      content/MaterialCheckUpdate.qml
  96. 89 0
      content/MaterialDialog.qml
  97. 142 0
      content/MaterialDialogBack.qml
  98. 239 0
      content/MaterialDialogMisplace.qml
  99. 142 0
      content/MaterialDialogTake.qml
  100. 437 0
      content/MaterialException.qml

+ 1 - 0
.gitignore

@@ -27,4 +27,5 @@
 *.exe
 *.out
 *.app
+build/
 

+ 165 - 0
CMakeLists.txt

@@ -0,0 +1,165 @@
+cmake_minimum_required(VERSION 3.16)
+
+project(Cabinet VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_AUTORCC ON)
+
+find_package(Qt6 6.7 COMPONENTS Quick Network SerialPort Multimedia Pdf Xml REQUIRED)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+
+# 查找静态库
+find_library(ZKFP_LIB
+    NAMES zkfp libzkfp
+    PATHS libs/x64lib
+    NO_DEFAULT_PATH
+)
+
+# 查找虹软SDK
+find_library(ARCSOFT_FACE_LIB
+    NAMES libarcsoft_face_engine
+    PATHS sdk/hrsdk/lib/X64
+    NO_DEFAULT_PATH
+)
+
+set(APP_ICON_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/logo.rc")
+
+qt_add_executable(appCabinet
+    main.cpp resource.qrc ${RESOURCES} ${APP_ICON_WINDOWS}
+)
+
+qt_add_qml_module(appCabinet
+    URI Cabinet
+    VERSION 1.0
+    QML_FILES main.qml
+    RESOURCES resource.qrc
+    QML_FILES content/Login.qml content/MainScreen.qml
+    SOURCES user/config.cpp
+    SOURCES user/config.h user/define.h
+    SOURCES user/lock.h user/lock.cpp
+    SOURCES user/httpclient.cpp user/httpclient.h
+    SOURCES user/rfid.h user/rfid.cpp
+    SOURCES user/ModuleReader.h
+    SOURCES user/pro.cpp user/pro.h
+    QML_FILES content/MaterialSelModel.qml
+    QML_FILES content/MaterialTakeBack.qml
+    QML_FILES content/MaterialStatistics.qml
+    QML_FILES content/MaterialInstructions.qml
+    QML_FILES content/MaterialCheckPlan.qml
+    QML_FILES content/MaterialCheckForm.qml
+    SOURCES user/finger.h user/finger.cpp
+    SOURCES user/logoutput.cpp user/logoutput.h
+    QML_FILES content/SetView.qml
+    SOURCES libs/include/libzkfp.h libs/include/libzkfperrdef.h libs/include/libzkfptype.h libs/include/zkinterface.h
+    RESOURCES logo.rc
+    QML_FILES content/MaterialCheckSign.qml
+    QML_FILES content/PromptInfo.qml
+    QML_FILES content/MaterialReplace.qml
+    QML_FILES content/ReuseTextField.qml
+    QML_FILES content/ReuseComboBox.qml
+    QML_FILES content/ReuseDateField.qml
+    SOURCES sdk/hrsdk/inc/amcomdef.h sdk/hrsdk/inc/arcsoft_face_sdk.h sdk/hrsdk/inc/asvloffscreen.h sdk/hrsdk/inc/merror.h
+    SOURCES Interactive/template_singleton.h
+    SOURCES Interactive/InteractiveCore.cpp Interactive/InteractiveCore.h
+    SOURCES Interactive/InteractiveData.cpp Interactive/InteractiveData.h
+    SOURCES Interactive/InteractiveTask.cpp Interactive/InteractiveTask.h
+    SOURCES Interactive/InteractiveWork.cpp Interactive/InteractiveWork.h
+    SOURCES Interactive/DataListModel.cpp Interactive/DataListModel.h
+    SOURCES Interactive/RunAbstract.cpp Interactive/RunAbstract.h
+    SOURCES Interactive/RunDataCacheRefresh.h Interactive/RunDataCacheRefresh.cpp
+    SOURCES Interactive/RunMaterialInfoListRefresh.cpp Interactive/RunMaterialInfoListRefresh.h
+    SOURCES Interactive/RunMaterialReplaceRefreshListModel.h Interactive/RunMaterialReplaceRefreshListModel.cpp
+    SOURCES Interactive/RunMaterialManualReplaceRefreshListModel.h Interactive/RunMaterialManualReplaceRefreshListModel.cpp
+    SOURCES Interactive/RunMaterialManualReplaceSubmit.h Interactive/RunMaterialManualReplaceSubmit.cpp
+    QML_FILES content/MaterialReplaceHand.qml
+    QML_FILES content/MaterialReplaceAuto.qml
+    QML_FILES content/MaterialException.qml
+    QML_FILES content/ReuseMaterialInfo.qml
+    QML_FILES content/MaterialExceptionReport.qml
+    QML_FILES
+    SOURCES Interactive/RunMaterialExceptionReport.h Interactive/RunMaterialExceptionReport.cpp
+    SOURCES Interactive/RunMaterialExceptionRefreshListModel.h Interactive/RunMaterialExceptionRefreshListModel.cpp
+    QML_FILES content/MaterialExceptionFinish.qml
+    SOURCES user/timeout.h user/timeout.cpp
+    QML_FILES content/MaterialDialog.qml
+    SOURCES Interactive/RunHttpGet_getIsMaterialsLoanExceptionPage.h Interactive/RunHttpGet_getIsMaterialsLoanExceptionPage.cpp
+    QML_FILES content/MaterialDialogMisplace.qml
+    QML_FILES content/MaterialDialogTake.qml
+    QML_FILES content/MaterialDialogBack.qml
+    SOURCES Interactive/InteractiveFace.h Interactive/InteractiveFace.cpp
+    QML_FILES content/FacialRecognition.qml
+    SOURCES Interactive/InteractiveHttp.h Interactive/InteractiveHttp.cpp
+    SOURCES Interactive/RunHttpGet_getSysUserCharacteristicPage.h Interactive/RunHttpGet_getSysUserCharacteristicPage.cpp
+    SOURCES Interactive/RunHttpPost_insertUserFace.h Interactive/RunHttpPost_insertUserFace.cpp
+    SOURCES Interactive/RunHttpPost_loginByFace.h Interactive/RunHttpPost_loginByFace.cpp
+    SOURCES Interactive/InteractiveConf.h Interactive/InteractiveConf.cpp
+    QML_FILES content/MaterialCheckUpdate.qml
+    SOURCES Interactive/RunHttpGet_getIsMaterialsPage.h Interactive/RunHttpGet_getIsMaterialsPage.cpp
+    QML_FILES content/MaterialStocktaking.qml
+    SOURCES Interactive/RunHttpGet_selectExMaterialTypeById.h Interactive/RunHttpGet_selectExMaterialTypeById.cpp
+    QML_FILES content/WaitPromptBox.qml
+    SOURCES Interactive/RunHttpGet_getInfo.h Interactive/RunHttpGet_getInfo.cpp
+    QML_FILES content/InfoPromptBox.qml
+    SOURCES Interactive/RunHttpPost_startCheckPlan.h Interactive/RunHttpPost_startCheckPlan.cpp
+    SOURCES Interactive/RunHttpGet_getLastCheckPlanByCabinetCode.h Interactive/RunHttpGet_getLastCheckPlanByCabinetCode.cpp
+    SOURCES Interactive/RunHttpGet_getCabinetHomePage.h Interactive/RunHttpGet_getCabinetHomePage.cpp
+    SOURCES Interactive/RunHttpPost_insertSubmitPlan.h Interactive/RunHttpPost_insertSubmitPlan.cpp
+    SOURCES Interactive/RunHttpGet_getInstructionsList.h Interactive/RunHttpGet_getInstructionsList.cpp
+    SOURCES Interactive/RunHttpPost_insertCheckRecord.h Interactive/RunHttpPost_insertCheckRecord.cpp
+    SOURCES Interactive/RunHttpPost_deleteSysUserCharacteristicByRecordIds.h Interactive/RunHttpPost_deleteSysUserCharacteristicByRecordIds.cpp
+    SOURCES Interactive/InteractiveHand.h Interactive/InteractiveHand.cpp
+    SOURCES Interactive/RunHttpPost_insertUserFingerprintDat.h Interactive/RunHttpPost_insertUserFingerprintDat.cpp
+    SOURCES Interactive/RunHttpGet_exception_type.h Interactive/RunHttpGet_exception_type.cpp
+    SOURCES Interactive/RunHttpGet_severity_level.h Interactive/RunHttpGet_severity_level.cpp
+    SOURCES Interactive/RunViewRefresh_AbnormalReport.h Interactive/RunViewRefresh_AbnormalReport.cpp
+    SOURCES Interactive/RunHttpPost_insertIsException.h Interactive/RunHttpPost_insertIsException.cpp
+    SOURCES Interactive/RunHttpGet_selectIsMaterialsCabinetByCode.h Interactive/RunHttpGet_selectIsMaterialsCabinetByCode.cpp
+    QML_FILES content/HangPromptBox.qml
+    SOURCES Interactive/RunViewWait.h Interactive/RunViewWait.cpp
+    SOURCES Interactive/RunHttpPost_loginByFingerprintDat.h Interactive/RunHttpPost_loginByFingerprintDat.cpp
+    QML_FILES content/MaterialManualReplace.qml
+    SOURCES user/filelogger.h user/filelogger.cpp
+)
+
+# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
+# If you are developing for iOS or macOS you should consider setting an
+# explicit, fixed bundle identifier manually though.
+set_target_properties(appCabinet PROPERTIES
+    #    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appCabinet
+    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
+    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
+    MACOSX_BUNDLE TRUE
+    WIN32_EXECUTABLE TRUE
+)
+
+# add_subdirectory(MediaPlayer)
+# add_subdirectory(MediaControls)
+
+# 链接静态库
+target_link_libraries(appCabinet PRIVATE ${ZKFP_LIB} ${ARCSOFT_FACE_LIB})
+
+target_link_libraries(appCabinet
+    PRIVATE Qt6::Quick
+    Qt6::Network
+    Qt6::SerialPort
+    Qt6::Multimedia
+    Qt6::Pdf
+    Qt6::Xml
+)
+target_link_libraries(appCabinet PRIVATE Qt6::Core)
+target_link_libraries(appCabinet PRIVATE Qt6::Core)
+target_link_libraries(appCabinet PRIVATE Qt6::Core)
+target_link_libraries(appCabinet PRIVATE Qt6::Core)
+target_link_libraries(appCabinet PRIVATE Qt6::Core)
+
+include(GNUInstallDirs)
+install(TARGETS appCabinet
+    BUNDLE DESTINATION .
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)

+ 755 - 0
CMakeLists.txt.user

@@ -0,0 +1,755 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE QtCreatorProject>
+<!-- Written by QtCreator 17.0.0, 2025-09-15T15:48:47. -->
+<qtcreator>
+ <data>
+  <variable>EnvironmentId</variable>
+  <value type="QByteArray">{483d7956-7334-4636-a31f-b5bb8202532c}</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">10</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>
+  </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 6.7.3 MSVC2019 64bit</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.7.3 MSVC2019 64bit</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.673.win64_msvc2019_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="QString" key="CMake.Build.Type">Debug</value>
+    <value type="int" key="CMake.Configure.BaseEnvironment">2</value>
+    <value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
+    <value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
+-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
+-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
+-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
+-DCMAKE_BUILD_TYPE:STRING=Debug
+-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
+-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
+-DQT_MAINTENANCE_TOOL:FILEPATH=D:/TechApp/Qt/MaintenanceTool.exe
+-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
+-DCMAKE_GENERATOR:STRING=Ninja</value>
+    <value type="int" key="EnableQmlDebugging">0</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:\Work\WXH\ISCS_Cabinet_WIN\Cabinet\build\Desktop_Qt_6_7_3_MSVC2019_64bit-Debug</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">all</value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</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="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">clean</value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清除</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">清除</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">CMakeProjectManager.CMakeBuildConfiguration</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">部署</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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>
+    <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+       <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+       <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+        <value type="QString"></value>
+       </valuelist>
+       <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+       <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
+      </valuemap>
+      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+       <value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
+       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</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>
+      <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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">ApplicationManagerPlugin.Deploy.Configuration</value>
+    </valuemap>
+    <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</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 &quot;dwarf,4096&quot; -F 250</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">appCabinet</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
+     <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">appCabinet</value>
+     <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</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">D:/Work/WXH/ISCS_Cabinet_WIN/Cabinet/build/Desktop_Qt_6_7_3_MSVC2019_64bit-Debug</value>
+    </valuemap>
+    <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+   </valuemap>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
+    <value type="QString" key="CMake.Build.Type">Release</value>
+    <value type="int" key="CMake.Configure.BaseEnvironment">2</value>
+    <value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
+    <value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
+-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
+-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
+-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
+-DCMAKE_BUILD_TYPE:STRING=Release
+-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
+-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
+-DQT_MAINTENANCE_TOOL:FILEPATH=D:/TechApp/Qt/MaintenanceTool.exe
+-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
+-DCMAKE_GENERATOR:STRING=Ninja</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:\Work\WXH\ISCS_Cabinet_WIN\Cabinet\build\Desktop_Qt_6_7_3_MSVC2019_64bit-Release</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">all</value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</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="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">clean</value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清除</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">清除</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">Release</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</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">部署</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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>
+    <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+       <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+       <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+        <value type="QString"></value>
+       </valuelist>
+       <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+       <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
+      </valuemap>
+      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+       <value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
+       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</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>
+      <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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">ApplicationManagerPlugin.Deploy.Configuration</value>
+    </valuemap>
+    <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</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 &quot;dwarf,4096&quot; -F 250</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">appCabinet</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
+     <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">appCabinet</value>
+     <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</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>
+    </valuemap>
+    <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+   </valuemap>
+   <value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">2</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">部署</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString"></value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
+     </valuemap>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+      <value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</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>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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">ApplicationManagerPlugin.Deploy.Configuration</value>
+   </valuemap>
+   <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</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 &quot;dwarf,4096&quot; -F 250</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">appCabinet</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
+    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">appCabinet</value>
+    <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</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">D:/Work/WXH/ISCS_Cabinet_WIN/Cabinet/build/Desktop_Qt_6_7_3_MSVC2019_64bit-Debug</value>
+   </valuemap>
+   <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Target.1</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 6.7.3 MinGW 64-bit</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 6.7.3 MinGW 64-bit</value>
+   <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.qt6.673.win64_mingw_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="QString" key="CMake.Build.Type">Debug</value>
+    <value type="int" key="CMake.Configure.BaseEnvironment">2</value>
+    <value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
+    <value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
+-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
+-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
+-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
+-DCMAKE_BUILD_TYPE:STRING=Debug
+-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
+-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
+-DQT_MAINTENANCE_TOOL:FILEPATH=D:/TechApp/Qt/MaintenanceTool.exe
+-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
+-DCMAKE_GENERATOR:STRING=Ninja</value>
+    <value type="int" key="EnableQmlDebugging">0</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:\Work\WXH\ISCS_Cabinet_WIN\Cabinet\build\Desktop_Qt_6_7_3_MinGW_64_bit-Debug</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">all</value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</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="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">clean</value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清除</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">清除</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">CMakeProjectManager.CMakeBuildConfiguration</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">部署</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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>
+    <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+       <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+       <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+        <value type="QString"></value>
+       </valuelist>
+       <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+       <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
+      </valuemap>
+      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+       <value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
+       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</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>
+      <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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">ApplicationManagerPlugin.Deploy.Configuration</value>
+    </valuemap>
+    <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</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 &quot;dwarf,4096&quot; -F 250</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">appCabinet</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
+     <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">appCabinet</value>
+     <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">true</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="bool" key="RunConfiguration.UseTerminal">true</value>
+    </valuemap>
+    <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+   </valuemap>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
+    <value type="QString" key="CMake.Build.Type">Release</value>
+    <value type="int" key="CMake.Configure.BaseEnvironment">2</value>
+    <value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
+    <valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
+    <value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
+-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
+-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
+-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
+-DCMAKE_BUILD_TYPE:STRING=Release
+-DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG}
+-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
+-DQT_MAINTENANCE_TOOL:FILEPATH=D:/TechApp/Qt/MaintenanceTool.exe
+-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
+-DCMAKE_GENERATOR:STRING=Ninja</value>
+    <value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:\Work\WXH\ISCS_Cabinet_WIN\Cabinet\build\Desktop_Qt_6_7_3_MinGW_64_bit-Release</value>
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">all</value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</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="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString">clean</value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">构建</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
+     </valuemap>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清除</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">清除</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">Release</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
+    <value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
+    <value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">-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">部署</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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>
+    <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+       <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+       <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+        <value type="QString">install</value>
+       </valuelist>
+       <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+       <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
+      </valuemap>
+      <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+       <value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
+       <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
+       <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</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>
+      <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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">ApplicationManagerPlugin.Deploy.Configuration</value>
+    </valuemap>
+    <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
+    <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">0</value>
+   </valuemap>
+   <value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">2</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">部署</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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>
+   <valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
+    <valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
+      <value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
+       <value type="QString"></value>
+      </valuelist>
+      <value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
+      <valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
+     </valuemap>
+     <valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
+      <value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
+      <value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Install Application Manager package</value>
+      <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</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>
+     <value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
+     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">部署</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">ApplicationManagerPlugin.Deploy.Configuration</value>
+   </valuemap>
+   <value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</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 &quot;dwarf,4096&quot; -F 250</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">appCabinet</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
+    <value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">appCabinet</value>
+    <value type="bool" key="ProjectExplorer.RunConfiguration.Customized">true</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="bool" key="RunConfiguration.UseTerminal">true</value>
+   </valuemap>
+   <value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
+  </valuemap>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.TargetCount</variable>
+  <value type="qlonglong">2</value>
+ </data>
+ <data>
+  <variable>ProjectExplorer.Project.Updater.FileVersion</variable>
+  <value type="int">22</value>
+ </data>
+ <data>
+  <variable>Version</variable>
+  <value type="int">22</value>
+ </data>
+</qtcreator>

+ 143 - 0
CMakeLists.txt.xIkHXX

@@ -0,0 +1,143 @@
+cmake_minimum_required(VERSION 3.16)
+
+project(Cabinet VERSION 0.1 LANGUAGES CXX)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_AUTORCC ON)
+
+find_package(Qt6 6.7 COMPONENTS Quick Network SerialPort Multimedia Pdf REQUIRED)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+find_package(Qt6 REQUIRED COMPONENTS Core)
+
+# 查找静态库
+find_library(ZKFP_LIB
+    NAMES zkfp libzkfp
+    PATHS libs/x64lib
+    NO_DEFAULT_PATH
+)
+
+# 查找虹软SDK
+find_library(ARCSOFT_FACE_LIB
+    NAMES libarcsoft_face_engine
+    PATHS sdk/hrsdk/lib/X64
+    NO_DEFAULT_PATH
+)
+
+set(APP_ICON_WINDOWS "${CMAKE_CURRENT_SOURCE_DIR}/logo.rc")
+
+qt_add_executable(appCabinet
+    main.cpp resource.qrc ${RESOURCES} ${APP_ICON_WINDOWS}
+)
+
+qt_add_qml_module(appCabinet
+    URI Cabinet
+    VERSION 1.0
+    QML_FILES main.qml
+    RESOURCES resource.qrc
+    QML_FILES content/Login.qml content/MainScreen.qml
+    SOURCES user/config.cpp
+    SOURCES user/config.h user/define.h
+    SOURCES
+    SOURCES user/lock.h user/lock.cpp
+    SOURCES user/httpclient.cpp user/httpclient.h
+    SOURCES user/rfid.h user/rfid.cpp
+    SOURCES user/ModuleReader.h
+    SOURCES user/pro.cpp user/pro.h
+    QML_FILES content/MaterialSelModel.qml
+    QML_FILES content/MaterialTakeBack.qml
+    QML_FILES content/MaterialStatistics.qml
+    QML_FILES content/MaterialInstructions.qml
+    QML_FILES content/MaterialCheckPlan.qml
+    QML_FILES content/MaterialCheckForm.qml
+    SOURCES
+    SOURCES user/finger.h user/finger.cpp
+    SOURCES user/logoutput.cpp user/logoutput.h
+    QML_FILES content/SetView.qml
+    SOURCES libs/include/libzkfp.h libs/include/libzkfperrdef.h libs/include/libzkfptype.h libs/include/zkinterface.h
+    RESOURCES logo.rc
+    QML_FILES content/MaterialCheckSign.qml
+    QML_FILES
+    QML_FILES content/PromptInfo.qml
+    QML_FILES content/MaterialReplace.qml
+    QML_FILES content/ReuseTextField.qml
+    QML_FILES content/ReuseComboBox.qml
+    QML_FILES content/ReuseDateField.qml
+
+    SOURCES sdk/hrsdk/inc/amcomdef.h sdk/hrsdk/inc/arcsoft_face_sdk.h sdk/hrsdk/inc/asvloffscreen.h sdk/hrsdk/inc/merror.h
+
+    SOURCES Interactive/template_singleton.h
+    SOURCES Interactive/InteractiveCore.cpp Interactive/InteractiveCore.h
+    SOURCES Interactive/InteractiveData.cpp Interactive/InteractiveData.h
+    SOURCES Interactive/InteractiveTask.cpp Interactive/InteractiveTask.h
+    SOURCES Interactive/InteractiveWork.cpp Interactive/InteractiveWork.h
+    SOURCES Interactive/InteractiveListModel.cpp Interactive/InteractiveListModel.h
+
+    SOURCES Interactive/RunAbstract.cpp Interactive/RunAbstract.h
+    SOURCES Interactive/RunDataCacheRefresh.h Interactive/RunDataCacheRefresh.cpp
+    SOURCES Interactive/RunHttpGetMaterialInfoList.cpp Interactive/RunHttpGetMaterialInfoList.h
+    SOURCES Interactive/RunMaterialReplaceRefreshListModel.h Interactive/RunMaterialReplaceRefreshListModel.cpp
+    SOURCES Interactive/RunMaterialManualReplaceRefreshListModel.h Interactive/RunMaterialManualReplaceRefreshListModel.cpp
+    SOURCES Interactive/RunMaterialManualReplaceSubmit.h Interactive/RunMaterialManualReplaceSubmit.cpp
+    QML_FILES content/MaterialReplaceHand.qml
+    QML_FILES content/MaterialReplaceAuto.qml
+    QML_FILES content/MaterialException.qml
+    QML_FILES content/ReuseMaterialInfo.qml
+    QML_FILES content/MaterialExceptionReport.qml
+    QML_FILES content/MaterialExceptionUpdate.qml
+    SOURCES Interactive/RunHttpGetIsMaterialsPropertyValuePage.h Interactive/RunHttpGetIsMaterialsPropertyValuePage.cpp
+    SOURCES Interactive/RunMaterialExceptionReport.h Interactive/RunMaterialExceptionReport.cpp
+    SOURCES Interactive/RunMaterialExceptionRefreshListModel.h Interactive/RunMaterialExceptionRefreshListModel.cpp
+    QML_FILES content/MaterialExceptionFinish.qml
+    SOURCES user/timeout.h user/timeout.cpp
+    QML_FILES content/MaterialDialog.qml
+    SOURCES Interactive/RunHttpGet_getIsMaterialsLoanExceptionPage.h Interactive/RunHttpGet_getIsMaterialsLoanExceptionPage.cpp
+    QML_FILES content/MaterialDialogMisplace.qml
+    QML_FILES content/MaterialDialogTake.qml
+    QML_FILES content/MaterialDialogBack.qml
+    SOURCES
+    SOURCES
+    SOURCES Interactive/InteractiveFace.h Interactive/InteractiveFace.cpp
+    QML_FILES
+    QML_FILES content/FacialRecognition.qml
+    SOURCES Interactive/InteractiveHttp.h Interactive/InteractiveHttp.cpp
+    SOURCES Interactive/RunHttpGet_getSysUserCharacteristicPage.h Interactive/RunHttpGet_getSysUserCharacteristicPage.cpp
+)
+
+# Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1.
+# If you are developing for iOS or macOS you should consider setting an
+# explicit, fixed bundle identifier manually though.
+set_target_properties(appCabinet PROPERTIES
+    #    MACOSX_BUNDLE_GUI_IDENTIFIER com.example.appCabinet
+    MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}
+    MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
+    MACOSX_BUNDLE TRUE
+    WIN32_EXECUTABLE TRUE
+)
+
+# add_subdirectory(MediaPlayer)
+# add_subdirectory(MediaControls)
+
+# 链接静态库
+target_link_libraries(appCabinet PRIVATE ${ZKFP_LIB} ${ARCSOFT_FACE_LIB})
+
+target_link_libraries(appCabinet
+    PRIVATE Qt6::Quick
+    Qt6::Network
+    Qt6::SerialPort
+    Qt6::Multimedia
+    Qt6::Pdf
+)
+target_link_libraries(appCabinet PRIVATE Qt6::Core)
+target_link_libraries(appCabinet PRIVATE Qt6::Core)
+target_link_libraries(appCabinet PRIVATE Qt6::Core)
+target_link_libraries(appCabinet PRIVATE Qt6::Core)
+
+include(GNUInstallDirs)
+install(TARGETS appCabinet
+    BUNDLE DESTINATION .
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+)

+ 142 - 0
Interactive/DataListModel.cpp

@@ -0,0 +1,142 @@
+#include "DataListModel.h"
+
+
+DataListModel::DataListModel(QObject *parent)
+    : QAbstractListModel(parent), m_nextRole(Qt::UserRole + 1)
+{
+    // 初始化一些默认角色
+}
+
+int DataListModel::rowCount(const QModelIndex &parent) const
+{
+    Q_UNUSED(parent);
+    return m_data.size();
+}
+
+QVariant DataListModel::data(const QModelIndex &index, int role) const
+{
+    if (!index.isValid() || index.row() >= m_data.size())
+    {
+        return QVariant();
+    }
+
+    const QVariantMap &entry = m_data.at(index.row());
+    QString roleName = m_roles.value(role);
+
+    return entry.value(roleName);
+}
+
+QHash<int, QByteArray> DataListModel::roleNames() const
+{
+    return m_roles;
+}
+
+bool DataListModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+    if (!index.isValid() || index.row() >= m_data.size())
+    {
+        return false;
+    }
+
+    QString roleName = m_roles.value(role);
+    if (roleName.isEmpty())
+    {
+        return false;
+    }
+
+    m_data[index.row()][roleName] = value;
+    emit dataChanged(index, index, {role});
+    return true;
+}
+
+Qt::ItemFlags DataListModel::flags(const QModelIndex &index) const
+{
+    if (!index.isValid())
+    {
+        return Qt::NoItemFlags;
+    }
+
+    return Qt::ItemIsEditable | QAbstractListModel::flags(index);
+}
+
+void DataListModel::append(const QVariantMap &entry)
+{
+    beginInsertRows(QModelIndex(), m_data.size(), m_data.size());
+    m_data.append(entry);
+    endInsertRows();
+}
+
+void DataListModel::insert(int index, const QVariantMap &entry)
+{
+    if (index < 0 || index > m_data.size())
+    {
+        return;
+    }
+
+    beginInsertRows(QModelIndex(), index, index);
+    m_data.insert(index, entry);
+    endInsertRows();
+}
+
+void DataListModel::remove(int index)
+{
+    if (index < 0 || index >= m_data.size())
+    {
+        return;
+    }
+
+    beginRemoveRows(QModelIndex(), index, index);
+    m_data.remove(index);
+    endRemoveRows();
+}
+
+void DataListModel::clear()
+{
+    beginResetModel();
+    m_data.clear();
+    endResetModel();
+}
+
+void DataListModel::setProperty(int index, const QString &property, const QVariant &value)
+{
+    if (index < 0 || index >= m_data.size())
+    {
+        return;
+    }
+
+    // 如果属性不存在,自动添加角色
+    if (!m_roles.key(property.toUtf8())) {
+        addRole(property);
+    }
+
+    m_data[index][property] = value;
+    QModelIndex modelIndex = createIndex(index, 0);
+    int role = m_roles.key(property.toUtf8());
+    emit dataChanged(modelIndex, modelIndex, {role});
+}
+
+QVariantMap DataListModel::get(int index) const
+{
+    if (index < 0 || index >= m_data.size())
+    {
+        return QVariantMap();
+    }
+
+    return m_data.at(index);
+}
+
+int DataListModel::count() const
+{
+    return m_data.size();
+}
+
+void DataListModel::addRole(const QString &roleName)
+{
+    if (m_roles.values().contains(roleName.toUtf8()))
+    {
+        return;
+    }
+
+    m_roles[m_nextRole++] = roleName.toUtf8();
+    // emit roleNamesChanged();
+}

+ 42 - 0
Interactive/DataListModel.h

@@ -0,0 +1,42 @@
+#ifndef DATALISTMODEL_H
+#define DATALISTMODEL_H
+
+#include <QAbstractListModel>
+#include <QVector>
+#include <QVariantMap>
+
+#include <QMutex>
+#include <QMutexLocker>
+
+class DataListModel : public QAbstractListModel
+{
+    Q_OBJECT
+public:
+    explicit DataListModel(QObject *parent = nullptr);
+
+    // 基本模型接口
+    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+    QHash<int, QByteArray> roleNames() const override;
+    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
+    Qt::ItemFlags flags(const QModelIndex &index) const override;
+
+    // 类似 QML ListModel 的接口
+    Q_INVOKABLE void append(const QVariantMap &entry);
+    Q_INVOKABLE void insert(int index, const QVariantMap &entry);
+    Q_INVOKABLE void remove(int index);
+    Q_INVOKABLE void clear();
+    Q_INVOKABLE void setProperty(int index, const QString &property, const QVariant &value);
+    Q_INVOKABLE QVariantMap get(int index) const;
+    Q_INVOKABLE int count() const;
+
+    // 动态属性支持
+    Q_INVOKABLE void addRole(const QString &roleName);
+
+private:
+    QVector<QVariantMap> m_data;
+    QHash<int, QByteArray> m_roles;
+    int m_nextRole;
+};
+
+#endif // DATALISTMODEL_H

+ 64 - 0
Interactive/InteractiveConf.cpp

@@ -0,0 +1,64 @@
+#include "InteractiveConf.h"
+
+InteractiveConf::InteractiveConf(QObject *parent)
+    : QObject{parent}
+{}
+
+
+void InteractiveConf::confSaveElseMaterials(QStringList &elseMaterials)
+{
+    QDomDocument doc;
+
+    QDomElement root = doc.createElement("Config");
+    doc.appendChild(root);
+
+    QDomElement colorsElement = doc.createElement("Rfids");
+    root.appendChild(colorsElement);
+
+    for (const QString &rfid : elseMaterials)
+    {
+        QDomElement item = doc.createElement("Rfid");
+        item.appendChild(doc.createTextNode(rfid));
+        colorsElement.appendChild(item);
+    }
+
+    QFile file(INTERACTIVE_CONF_FILE);
+    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
+        QTextStream stream(&file);
+        doc.save(stream, 4);
+        file.close();
+    }
+}
+
+QStringList InteractiveConf::confReadElseMaterials(void)
+{
+    QStringList elseMaterials;
+
+    QFile file(INTERACTIVE_CONF_FILE);
+    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+    {
+        return elseMaterials;
+    }
+
+    QDomDocument doc;
+    if (!doc.setContent(&file))
+    {
+        file.close();
+        return elseMaterials;
+    }
+    file.close();
+
+    QDomElement root = doc.documentElement();
+
+
+    QDomElement colorsElement = root.firstChildElement("Rfids");
+    QDomNodeList colorItems = colorsElement.elementsByTagName("Rfid");
+
+    for (int i = 0; i < colorItems.count(); ++i)
+    {
+        QDomElement item = colorItems.at(i).toElement();
+        elseMaterials.append(item.text());
+    }
+
+    return elseMaterials;
+}

+ 33 - 0
Interactive/InteractiveConf.h

@@ -0,0 +1,33 @@
+#ifndef INTERACTIVECONF_H
+#define INTERACTIVECONF_H
+
+#include <QObject>
+#include <QString>
+#include <QList>
+#include <QCoreApplication>
+#include <QDomDocument>
+#include <QTextStream>
+#include <QFile>
+
+#include "template_singleton.h"
+
+#define INTERACTIVE_CONF_FILE qApp->applicationDirPath() + QString("/materialsRfid.conf")
+
+class InteractiveConf : public QObject
+{
+    SINGLETON_DEFINE(InteractiveConf)
+    Q_OBJECT
+public:
+    explicit InteractiveConf(QObject *parent = nullptr);
+
+    // 暂时先读写文件,后续整体配置优化
+    static void confSaveElseMaterials(QStringList &elseMaterials);
+    static QStringList confReadElseMaterials(void);
+
+private:
+    // QStringList m_elseMaterial; // 其他柜子的物资
+
+signals:
+};
+
+#endif // INTERACTIVECONF_H

+ 97 - 0
Interactive/InteractiveCore.cpp

@@ -0,0 +1,97 @@
+#include "InteractiveCore.h"
+#include "InteractiveWork.h"
+
+InteractiveCore::InteractiveCore(QObject *parent)
+    : QObject(parent)
+{
+    m_timerDataChcheRefresh = startTimer(TIMER_DATA_CHCHE_REFRESH);
+
+    connect(SINGLETON_CREATE(InteractiveWork)(), &InteractiveWork::signal_completed,
+            this, &InteractiveCore::slot_completed);
+    connect(SINGLETON_CREATE(InteractiveWork)(), &InteractiveWork::signal_failstart,
+            this, &InteractiveCore::slot_failstart);
+
+    SINGLETON_CREATE(InteractiveWork)()->start();
+}
+
+void InteractiveCore::appendTask(InteractiveTask::TaskType type, QVariant request, QJSValue callback)
+{
+    InteractiveTask* task = new InteractiveTask();
+    task->type = type;
+    task->request = request;
+    task->callback = callback;
+    SINGLETON_CREATE(InteractiveWork)()->appendTask(task);
+}
+
+void InteractiveCore::slot_completed(InteractiveTask *task)
+{
+    if (qobject_cast<InteractiveTask*>(task))
+    {
+        if (task->callback.isCallable())
+        {
+            QJSValueList args;
+            // 如果是string类型
+            if (task->respond.typeId() == QMetaType::QString)
+            {
+                args << task->respond.toString();
+            }
+            // 如果是bytearray类型
+            else if(task->respond.typeId() == QMetaType::QByteArray)
+            {
+                args << QString(task->respond.toByteArray());
+            }
+            // 如果是int类型
+            else if (task->respond.typeId() == QMetaType::Int)
+            {
+                args << task->respond.toInt();
+            }
+            // 如果是其他类型
+            else
+            {
+                // ...
+            }
+
+            task->callback.call(args);
+        }
+    }
+
+    delete task;
+}
+
+void InteractiveCore::slot_failstart(InteractiveTask *task)
+{
+    delete task;
+}
+
+void InteractiveCore::timerEvent(QTimerEvent *event)
+{
+    // 定时刷新服务缓存
+    if (event->timerId() == m_timerDataChcheRefresh)
+    {
+        // 获取异常类型字典值
+        appendTask(InteractiveTask::TypeHttpGet_exception_type, QVariant(), QJSValue());
+        // 获取严重等级字典值
+        appendTask(InteractiveTask::TypeHttpGet_severity_level, QVariant(), QJSValue());
+
+        // 获取物资柜id
+        appendTask(InteractiveTask::TypeHttpGet_selectIsMaterialsCabinetByCode, QVariant(), QJSValue());
+
+        // 查询物资信息All
+        appendTask(InteractiveTask::TypeHttpGet_getIsMaterialsPage, QVariant(), QJSValue());
+    }
+
+}
+
+
+// void InteractiveCore::slot_tid_update_Ex(quint16 count, QList<QString> tidList, const QVariant &user)
+// {
+//     QString strType = user.toString();
+//     if (strType == "物资取还" || strType == "物资检查" || strType == "手动更换" || strType == "异常处理")
+//     {
+
+//     }
+//     else if (strType == "自动更换")
+//     {
+
+//     }
+// }

+ 37 - 0
Interactive/InteractiveCore.h

@@ -0,0 +1,37 @@
+#ifndef INTERACTIVECORE_H
+#define INTERACTIVECORE_H
+
+#include <QObject>
+#include <QVariant>
+#include <QTimerEvent>
+#include "template_singleton.h"
+#include "InteractiveTask.h"
+
+#define TIMER_DATA_CHCHE_REFRESH 1000 * 10  // 定时刷新数据缓存,间隔10秒
+
+class InteractiveCore : public QObject
+{
+    SINGLETON_DEFINE(InteractiveCore)       // 定义为单例类
+    Q_OBJECT
+private:
+    explicit InteractiveCore(QObject *parent = nullptr);
+
+public:
+    Q_INVOKABLE void appendTask(InteractiveTask::TaskType type, QVariant request, QJSValue callback);
+
+public slots:
+    void slot_completed(InteractiveTask *task);
+    void slot_failstart(InteractiveTask *task);
+
+    // 临时槽函数,实现原有开关柜门功能
+    // void slot_tid_update_Ex(quint16 count, QList<QString> tidList, const QVariant &user);
+
+protected:
+    void timerEvent(QTimerEvent *event);
+
+private:
+
+    int m_timerDataChcheRefresh;
+};
+
+#endif // INTERACTIVECORE_H

+ 99 - 0
Interactive/InteractiveData.cpp

@@ -0,0 +1,99 @@
+#include "InteractiveData.h"
+
+InteractiveData::InteractiveData()
+{
+    // 物资类型
+    m_modelMaterialType.addRole("materialsTypeId");
+    m_modelMaterialType.addRole("materialsTypeName");
+    m_modelMaterialType.addRole("materialsTypeIcon");
+    m_modelMaterialType.addRole("materialsTypeError");
+    m_modelMaterialType.addRole("materialsTypePicture");
+    m_modelMaterialType.addRole("materialsTypeSelected");
+
+
+    // 物资信息
+    m_modelMaterialInfo.addRole("materialsId");
+    m_modelMaterialInfo.addRole("materialsName");
+    m_modelMaterialInfo.addRole("materialsRfid");
+    m_modelMaterialInfo.addRole("expirationDate");
+    m_modelMaterialInfo.addRole("status");
+    m_modelMaterialInfo.addRole("materialsTypePicture");
+
+
+    // 手动更换
+    m_modelMaterialManualReplace.addRole("oldMaterialsId");
+    m_modelMaterialManualReplace.addRole("oldMaterialsId");
+    m_modelMaterialManualReplace.addRole("materialsName");
+    m_modelMaterialManualReplace.addRole("materialsRfid");
+    m_modelMaterialManualReplace.addRole("expirationDate");
+    m_modelMaterialManualReplace.addRole("propertiesValue");
+    m_modelMaterialManualReplace.addRole("materialsTypeName");
+    m_modelMaterialManualReplace.addRole("materialsTypePicture");
+
+    m_modelMaterialManualReplace.addRole("oldMaterialsName");
+    m_modelMaterialManualReplace.addRole("oldMaterialsRfid");
+    m_modelMaterialManualReplace.addRole("oldExpirationDate");
+    m_modelMaterialManualReplace.addRole("oldPropertiesValue");
+    m_modelMaterialManualReplace.addRole("oldMaterialsTypeName");
+    m_modelMaterialManualReplace.addRole("oldMaterialsTypePicture");
+
+    m_modelMaterialManualReplace.addRole("status");
+    m_modelMaterialManualReplace.addRole("types");
+    m_modelMaterialManualReplace.addRole("click");
+
+    // 异常上报
+    m_modelMaterialException.addRole("materialsId");
+    m_modelMaterialException.addRole("materialsName");
+    m_modelMaterialException.addRole("materialsRfid");
+    m_modelMaterialException.addRole("expirationDate");
+    m_modelMaterialException.addRole("status");
+    m_modelMaterialException.addRole("materialsTypePicture");
+}
+
+bool InteractiveData::isHavePower(const QString &operation)
+{
+    // 物资领取归还 iscs:receive-return
+    // 物资使用说明 iscs:Instructions
+    // 物资检查计划 iscs:Inspection-plan
+    // 物资更换 iscs:replacement
+    // 异常处理 iscs:exception
+
+    // 如果角色包含超级管理员
+    if (m_roles.contains(QString("admin")))
+    {
+        return true;
+    }
+    // 如果是其他用户,判断是否有执行该操作的权利
+    else if (m_permissions.contains(operation))
+    {
+        return true;
+    }
+    // 如果没有权利执行该操作
+    else
+    {
+        return false;
+    }
+}
+
+QSet<QString> InteractiveData::roles()
+{
+    return m_roles;
+}
+
+void InteractiveData::setRoles(const QSet<QString> &roles)
+{
+    m_roles = roles;
+    emit rolesChanged();
+}
+
+QSet<QString> InteractiveData::permissions()
+{
+    return m_permissions;
+}
+
+void InteractiveData::setPermissions(const QSet<QString> &permissions)
+{
+    m_permissions = permissions;
+    emit permissionsChanged();
+}
+

+ 156 - 0
Interactive/InteractiveData.h

@@ -0,0 +1,156 @@
+#ifndef INTERACTIVEDATA_H
+#define INTERACTIVEDATA_H
+
+#include <QMap>
+#include <QList>
+#include <QVector>
+#include <QString>
+
+#include <QReadWriteLock>
+#include <QReadLocker>
+#include <QWriteLocker>
+
+#include "template_singleton.h"
+#include "DataListModel.h"
+
+#define MATERIALS_TYPE_ALL "0"
+
+class InteractiveData : public QObject
+{
+    SINGLETON_DEFINE(InteractiveData)       // 定义为单例类
+    Q_OBJECT
+
+    Q_PROPERTY(QSet<QString> roles READ roles WRITE setRoles NOTIFY rolesChanged)
+    Q_PROPERTY(QSet<QString> permissions READ permissions WRITE setPermissions NOTIFY permissionsChanged)
+
+
+signals:
+    void rolesChanged();
+    void permissionsChanged();
+
+public:
+
+    Q_INVOKABLE bool isHavePower(const QString &operation);
+
+    QSet<QString> roles();
+    void setRoles(const QSet<QString> &roles);
+    QSet<QString> permissions();
+    void setPermissions(const QSet<QString> &permissions);
+
+private:
+    explicit InteractiveData();
+
+public:
+    QReadWriteLock m_dataCacheLock;         // 数据缓存锁
+
+    int m_checkPlanStatus = -1;             // 当前物资柜检查计划ID
+
+    QString m_token;                        // token存储
+    QString m_cabinetId;                    // 物资柜ID
+
+    QString m_userName;                     // 用户名
+    QSet<QString> m_roles;                  // 用户角色
+    QSet<QString> m_permissions;            // 用户许可
+
+
+    // 用于http返回重复消息性能优化的json临时存储
+    QByteArray m_jsonCacheExceptionTypeDict;     // 异常类型字典缓存Json
+    QByteArray m_jsonCacheSeverityLevelDict;     // 严重程度字典缓存Json
+
+    QByteArray m_jsonCacheMaterialProp;     // 物资属性数据缓存Json
+    QByteArray m_jsonCacheMaterialType;     // 物资类型数据缓存Json
+    QByteArray m_jsonCacheMaterialInfo;     // 物资信息数据缓存Json
+    QByteArray m_jsonCacheExMaterialInfo;   // 异常物资数据缓存Json
+    QByteArray m_jsonCacheMaterialsLoanExceptionInfo;   // 物资借出异常缓存Json
+
+
+    // 数据缓存列表
+
+
+    // 异常类型字典值
+    QList<QString> m_dataCacheExceptionTypeDictCode;            // 异常类型字典 Code 列表
+    QHash<QString, QString> m_dataCacheExceptionTypeDictLabel;  // 异常类型字典 Code Label 绑定关系
+    QHash<QString, QString> m_dataCacheExceptionTypeDictValue;  // 异常类型字典 Code Value 绑定关系
+
+    // 严重程度字典值
+    QList<QString> m_dataCacheSeverityLevelDictCode;            // 严重程度字典 Code 列表
+    QHash<QString, QString> m_dataCacheSeverityLevelDictLabel;  // 严重程度字典 Code Label 绑定关系
+    QHash<QString, QString> m_dataCacheSeverityLevelDictValue;  // 严重程度字典 Code Value 绑定关系
+
+    // 物资属性
+    QList<QString> m_dataCacheMaterialPropId;                   // 物资属性 ID 列表
+    QHash<QString, QString> m_dataCacheMaterialPropName;        // 物资属性 ID Name 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialPropPropertyId;  // 物资属性 ID 属性项ID 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialPropPropertyName;// 物资属性 ID 属性项名称 绑定关系
+
+
+    // 物资类型
+    QList<QString> m_dataCacheMaterialTypeId;                   // 物资类型 ID 列表
+    QHash<QString, QString> m_dataCacheMaterialTypeName;        // 物资类型 ID 名称 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialTypeIcon;        // 物资类型 ID 图标 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialTypePicture;     // 物资类型 ID 图片 绑定关系
+    QHash<QString, QStringList> m_dataCacheMaterialTypeAncestors;       // 物资类型 ID 上层属性 绑定关系
+    QHash<QString, QStringList> m_dataCacheMaterialTypePropertyIds;     // 物资类型 ID 属性项ids 绑定关系
+
+
+    // 物资信息
+    QList<QString> m_dataCacheMaterialInfoId;                   // 物资信息 ID 列表
+    QHash<QString, QString> m_dataCacheMaterialInfoName;        // 物资信息 ID 名称 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialInfoRfid;        // 物资信息 ID rfid 绑定关系
+
+    QHash<QString, QString> m_dataCacheMaterialInfoLoan;        // 物资信息 ID 借出状态 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialInfoStat;        // 物资信息 ID 异常状态 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialInfoDate;        // 物资信息 ID 过期时间 绑定关系
+
+    QHash<QString, QString> m_dataCacheMaterialInfoTypeId;      // 物资信息 ID 类型ID 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialInfoPropId;      // 物资信息 ID 属性ID 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialInfoCabinetId;   // 物资信息 ID 机柜ID 绑定关系
+
+
+    // 异常信息类型
+    QList<QString> m_dataCacheExMaterialTypeId;                 // 物资类型 ID 列表
+    QHash<QString, int> m_dataCacheExMaterialTypeExNumber;      // 物资异常类型数量绑定关系
+
+    // 异常信息处理
+    QList<QString> m_dataCacheExMaterialInfoId;                 // 异常物资信息 ID 列表
+    QHash<QString, QString> m_dataCacheExMaterialInfoName;      // 异常物资信息 ID 名称 绑定关系
+    QHash<QString, QString> m_dataCacheExMaterialInfoRfid;      // 异常物资信息 ID rfid 绑定关系
+    QHash<QString, QString> m_dataCacheExMaterialInfoLoan;      // 异常物资信息 ID 借出状态 绑定关系
+    QHash<QString, QString> m_dataCacheExMaterialInfoStat;      // 异常物资信息 ID 状态 绑定关系
+    QHash<QString, QString> m_dataCacheExMaterialInfoDate;      // 异常物资信息 ID 过期时间 绑定关系
+    QHash<QString, QString> m_dataCacheExMaterialInfoTypeId;    // 异常物资信息 ID 类型ID 绑定关系
+    QHash<QString, QString> m_dataCacheExMaterialInfoPropId;    // 异常物资信息 ID 属性ID 绑定关系
+
+
+    // 错放物资信息
+    QList<QString> m_dataCacheMaterialLoadRfid;                   // 错放物资信息 RFID 列表
+    QHash<QString, QString> m_dataCacheMaterialLoanName;          // 错放物资信息 RFID 名称 绑定关系
+    // QHash<QString, QString> m_dataCacheMaterialLoanRfid;          // 错放物资信息 RFID rfid 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialLoanTypeIcon;      // 错放物资信息 RFID 类型图标 绑定关系
+    QHash<QString, QString> m_dataCacheMaterialLoanTypePicture;   // 错放物资信息 RFID 类型图片 绑定关系
+
+
+
+    // 本柜子的物资
+
+
+    // 用于qml显示的model
+
+    DataListModel m_modelMaterialType;           // 物资类型 model
+    DataListModel m_modelMaterialInfo;           // 物资信息 model
+    DataListModel m_modelMaterialManualReplace;  // 手动更换 model
+
+    DataListModel m_modelMaterialException;      // 物资异常 Model
+
+    DataListModel m_modelMaterialDissolve;      // 物资解除错放 model
+    DataListModel m_modelMaterialMisplace;      // 物资错放异常 model
+
+    DataListModel m_modelMaterialBinded;        // 物资绑定 model
+    DataListModel m_modelMaterialUnbind;        // 物资解绑 model
+
+    DataListModel m_modelMaterialTake;          // 物资领取 model
+    DataListModel m_modelMaterialBack;          // 物资归还 model
+
+};
+
+#endif // INTERACTIVEDATA_H

+ 413 - 0
Interactive/InteractiveFace.cpp

@@ -0,0 +1,413 @@
+#include "InteractiveFace.h"
+
+InteractiveFace::InteractiveFace(QObject *parent) : QQuickImageProvider(QQuickImageProvider::Image)
+{
+    initEngine();
+
+    if (hasCamera())
+    {
+        // initCamera();
+    }
+
+    // 图像取1s 10帧
+    m_timerId = startTimer(100);
+}
+
+bool InteractiveFace::hasCamera()
+{
+    return !QMediaDevices::videoInputs().isEmpty();
+}
+
+
+InteractiveFace::~InteractiveFace()
+{
+    destroyEngine();
+}
+
+void InteractiveFace::initEngine()
+{
+    const char* appId = "FTN3G4pk8n2RKwjD955sRapRjbYQFefwhHd4sBZMYEz6";
+    const char* sdkKey = "BjJomNU2bQc2SYhT7NNqwvFd9zfc72Q7nneh75r3NT3x";
+    const char* licenseFilePath = "./offlineLicense.dat";
+
+    // 超过5次不再尝试获取授权文件
+    int iLoopCount = 5;
+    do{
+        MPChar activeDeviceInfo;
+        ASFGetActiveDeviceInfo(&activeDeviceInfo);
+        ASF_ActiveFileInfo activeFileInfo;
+        MRESULT res = -1;
+        if ((res = ASFGetActiveFileInfo(&activeFileInfo)) == MOK)
+        {
+            qDebug() << "获取版本信息成功";
+            break;
+        }
+        else{
+            FileLogger::writeToFile("deviceInfo","ArcSoftDeviceInfo.txt",activeDeviceInfo,FileLogger::WriteMode::OVERWRITE);
+            if(res == 0x1601A){
+
+                if((res = ASFOfflineActivation((MPChar)licenseFilePath)) == MOK)
+                {
+                    qDebug() << "授权成功";
+                }
+            }
+        }
+        break;
+    }while(iLoopCount--);
+
+    // 初始化引擎
+    MRESULT res = ASFInitEngine(ASF_DETECT_MODE_VIDEO,
+                                ASF_OP_ALL_OUT,
+                                1,
+                                ASF_FACE_DETECT | ASF_FACERECOGNITION,
+                                &m_engine);
+
+    if (res != MOK)
+    {
+        qDebug() << " 初始化引擎失败" << res;
+    }
+}
+
+void InteractiveFace::destroyEngine()
+{
+
+}
+
+void InteractiveFace::cameraPlay()
+{
+    // 如果相机不是播放状态
+    if (!m_camera.isActive())
+    {
+        QCameraDevice cameraDevice = QMediaDevices::defaultVideoInput();
+        if (cameraDevice.isNull())
+        {
+            qWarning() << "系统中没有检测到任何摄像机设备";
+            return;
+        }
+
+        m_camera.setCameraDevice(cameraDevice);
+
+        // 确保图像宽度是4的倍数(虹软人脸识别要求)
+        if (m_camera.cameraFormat().resolution().width() % 4 != 0)
+        {
+            QList<QCameraFormat> cameraFormats = cameraDevice.videoFormats();
+            for (int i = 0; i < cameraFormats.size(); ++i)
+            {
+                const QCameraFormat &cameraFormat = cameraFormats.at(i);
+                if (cameraFormat.resolution().width() % 4 == 0)
+                {
+                    m_camera.setCameraFormat(cameraFormat);
+                    break;
+                }
+            }
+        }
+
+        m_session.setCamera(&m_camera);
+        m_session.setVideoSink(&m_videoSink);
+
+        m_camera.start();
+    }
+}
+
+void InteractiveFace::cameraStop()
+{
+    if (m_camera.isActive())
+    {
+        m_camera.stop();
+        m_camera.setActive(false);
+        m_camera.setCameraDevice(QCameraDevice());
+
+        m_session.setCamera(nullptr);
+        m_session.setVideoSink(nullptr);
+    }
+}
+
+
+void InteractiveFace::initCamera()
+{
+    m_camera.setCameraDevice(QMediaDevices::defaultVideoInput());
+
+    QCameraDevice device = QMediaDevices::defaultVideoInput();
+    QList<QCameraFormat> formats = device.videoFormats();
+    // 选择最适合的格式
+    for (const QCameraFormat &format : formats)
+    {
+        // qDebug() << "fps---" << format.maxFrameRate() << format.resolution().width() << format.resolution().height();
+        if (format.maxFrameRate() >= 10.0 && format.resolution().width() % 4 == 0)
+        {
+            m_camera.setCameraFormat(format);
+            break;
+        }
+    }
+    m_session.setCamera(&m_camera);
+    m_session.setVideoSink(&m_videoSink);
+}
+
+void InteractiveFace::destroyCamera()
+{
+
+}
+
+QString InteractiveFace::getImageUrl()
+{
+    // image://InteractiveFaceImage/(0-9999)
+    return QString("image://") +
+           QString(INTERACTIVE_FACE_IMAGE_URL) +
+           QString("/") +
+           // 取随机数,确保图片刷新(Qt机制,两次url地址相同,图片不会显示)
+           QString::number(QRandomGenerator::global()->bounded(10000));
+}
+
+// 设置图像采集回调
+void InteractiveFace::setCameraImageGatherCallBack(QJSValue callback)
+{
+    m_imageGatherCallback = callback;
+}
+// 设置发现人脸回调
+void InteractiveFace::setCameraImageAppearCallBack(QJSValue callback)
+{
+    m_imageAppearCallback = callback;
+}
+// 设置人脸停留回调
+void InteractiveFace::setCameraImageRemainCallBack(QJSValue callback)
+{
+    m_imageRemainCallback = callback;
+}
+
+void InteractiveFace::setCameraImageCallBack(QJSValue gatherCallback,
+                                             QJSValue appearCallback,
+                                             QJSValue remainCallback)
+{
+    m_imageGatherCallback = gatherCallback;
+    m_imageAppearCallback = appearCallback;
+    m_imageRemainCallback = remainCallback;
+}
+
+void InteractiveFace::setCallBackFaceStatus(QJSValue isAppearCallback)
+{
+    m_isAppearCallback = isAppearCallback;
+}
+
+void InteractiveFace::cameraImagePlay()
+{
+    if (!hasCamera())
+    {
+        return;
+    }
+
+
+    if (!m_camera.isActive())
+    {
+        cameraPlay();
+        m_laseEpoch = 0;
+        m_laseCount = 0;
+
+        m_FrameId = 0;
+    }
+}
+
+void InteractiveFace::cameraImageStop()
+{
+    if (!hasCamera())
+    {
+        return;
+    }
+
+    cameraStop();
+}
+
+QImage InteractiveFace::requestImage(const QString &, QSize *, const QSize &)
+{
+    return m_image;
+}
+
+void InteractiveFace::timerEvent(QTimerEvent *event)
+{
+    if (event->timerId() == m_timerId)
+    {
+        if (!hasCamera())
+        {
+            return;
+        }
+
+        if (m_camera.isActive())
+        {
+            QMutexLocker locker(&m_mutex);
+            QVideoFrame currentFormat = m_videoSink.videoFrame();
+
+            QImage image;       // 图像
+            QPainter painter;   // 画笔
+
+            // 过滤无效帧, 前10帧不做处理
+            if(++m_FrameId <= 10)
+            {
+                m_image = image.copy();
+                if (m_imageGatherCallback.isCallable())
+                {
+                    QJSValueList args;
+                    args << getImageUrl();
+                    m_imageGatherCallback.call(args);
+                }
+                return;
+            }
+
+            if (currentFormat.isValid())
+            {
+                if (currentFormat.map(QVideoFrame::ReadOnly))
+                {
+                    image = currentFormat.toImage();
+                    // image = image.scaled(QSize(800, 600), Qt::KeepAspectRatio, Qt::SmoothTransformation);
+                }
+                currentFormat.unmap();
+            }
+
+            if (!image.isNull())
+            {
+                // image底部框
+                painter.begin(&image);
+                painter.setRenderHint(QPainter::Antialiasing);
+                painter.setFont(QFont("Arial", 24));
+                painter.setBrush(QColor(255, 255, 255, 127));
+                painter.setPen(Qt::NoPen);
+                painter.drawRect(QRect(0, image.height() - 50, image.width(), 50));
+
+                QImage convertedImage = image.convertToFormat(QImage::Format_RGB888);
+                ASVLOFFSCREEN offscreen = {0};
+                offscreen.u32PixelArrayFormat = ASVL_PAF_RGB24_B8G8R8;
+                offscreen.i32Width = convertedImage.width();
+                offscreen.i32Height = convertedImage.height();
+                offscreen.pi32Pitch[0] = convertedImage.bytesPerLine();
+                offscreen.ppu8Plane[0] = (MUInt8*)convertedImage.bits();
+
+                if (offscreen.ppu8Plane[0])
+                {
+                    if (m_engine != NULL)
+                    {
+                        ASF_MultiFaceInfo detectedFaces = {0};
+
+                        MRESULT res = ASFDetectFaces(m_engine,
+                                                     offscreen.i32Width,
+                                                     offscreen.i32Height,
+                                                     offscreen.u32PixelArrayFormat,
+                                                     offscreen.ppu8Plane[0],
+                                                     &detectedFaces);
+
+                        if (res != MOK)
+                        {
+                            qDebug() << "检测人脸失败" << res;
+                        }
+
+                        bool isAppear;
+                        // 获取第一个人脸
+                        if (res == MOK && detectedFaces.faceNum == 1) {
+                            isAppear = true;
+                            if (m_laseCount <= 0)
+                            {
+                                m_laseCount = 1;
+                                m_laseEpoch = QDateTime::currentSecsSinceEpoch();
+                            }
+
+                            if (m_imageAppearCallback.isCallable())
+                            {
+                                m_image = image.copy();
+                                QJSValueList args;
+                                args << getImageUrl();
+                                m_imageAppearCallback.call(args);
+                            }
+
+                            MRECT mrect = detectedFaces.faceRect[0];
+
+                            qint64 epoch = QDateTime::currentSecsSinceEpoch() - m_laseEpoch;
+                            if (epoch <= 1)
+                            {
+                                painter.setPen(QPen(Qt::blue, 3));
+                                painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
+                                                 Qt::AlignCenter,
+                                                 QString("检测到人脸,即将拍摄").arg(epoch));
+
+                                // 绘制人脸框
+                                painter.setPen(QPen(Qt::green, 2));
+                                painter.setBrush(Qt::NoBrush);
+                                painter.drawRect(QRect(mrect.left,
+                                                       mrect.top,
+                                                       mrect.right - mrect.left,
+                                                       mrect.bottom - mrect.top));
+                            }
+                            else if (epoch > 1 && epoch <= 4)
+                            {
+                                painter.setPen(QPen(Qt::blue, 3));
+                                painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
+                                                 Qt::AlignCenter,
+                                                 QString("%1").arg(5 - epoch));
+
+                                // 绘制人脸框
+                                painter.setPen(QPen(Qt::green, 2));
+                                painter.setBrush(Qt::NoBrush);
+                                painter.drawRect(QRect(mrect.left,
+                                                       mrect.top,
+                                                       mrect.right - mrect.left,
+                                                       mrect.bottom - mrect.top));
+
+                            }
+                            else if (epoch >= 5)
+                            {
+                                if (m_imageRemainCallback.isCallable())
+                                {
+                                    QJSValueList args;
+                                    args << getImageUrl();
+                                    m_imageRemainCallback.call(args);
+                                }
+                            }
+
+                        }
+                        else if (res == MOK && detectedFaces.faceNum >= 2)
+                        {
+                            isAppear = true;
+                            m_laseCount--;
+                            painter.setPen(QPen(Qt::red, 3));
+                            painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
+                                             Qt::AlignCenter,
+                                             QString("请保持单人入镜,请保持光线充足"));
+                        }
+                        else
+                        {
+                            isAppear = false;
+                            m_laseCount--;
+                            painter.setPen(QPen(Qt::red, 3));
+                            painter.drawText(QRect(0, image.height() - 50, image.width(), 50),
+                                             Qt::AlignCenter,
+                                             QString("请保持真人操作,请保持光线充足"));
+                        }
+
+                        if (m_isAppearCallback.isCallable())
+                        {
+                            QJSValueList args;
+                            args << isAppear;
+                            m_isAppearCallback.call(args);
+                        }
+                    }
+                }
+
+                painter.end();
+
+                m_image = image.copy();
+
+                if (m_imageGatherCallback.isCallable())
+                {
+                    QJSValueList args;
+                    args << getImageUrl();
+                    m_imageGatherCallback.call(args);
+                }
+            }
+        }
+    }
+
+
+}
+
+// 获取图像
+QImage InteractiveFace::getImage()
+{
+    QMutexLocker locker(&m_mutex);
+    return m_image.copy();
+}

+ 129 - 0
Interactive/InteractiveFace.h

@@ -0,0 +1,129 @@
+#ifndef INTERACTIVEFACE_H
+#define INTERACTIVEFACE_H
+
+#include <QObject>
+#include <QJSValue>
+
+#include <QTimer>
+#include <QDateTime>
+
+#include <QImage>
+#include <QVideoFrame>
+#include <QPainter>
+#include <QBuffer>
+
+#include <QString>
+#include <QBuffer>
+#include <QByteArray>
+#include <QTimerEvent>
+#include <QMutex>
+#include <QMutexLocker>
+
+#include <QCamera>
+#include <QVideoSink>
+#include <QMediaDevices>
+#include <QMediaCaptureSession>
+#include <QQuickImageProvider>
+
+#include <QtMath>
+#include <QRandomGenerator>
+
+#include "template_singleton.h"
+
+#include "sdk/hrsdk/inc/amcomdef.h"
+#include "sdk/hrsdk/inc/arcsoft_face_sdk.h"
+#include "sdk/hrsdk/inc/asvloffscreen.h"
+#include "sdk/hrsdk/inc/merror.h"
+#include "user/filelogger.h"
+
+#define INTERACTIVE_FACE_IMAGE_URL "InteractiveFaceImage"
+
+class InteractiveFace : public QQuickImageProvider
+{
+    SINGLETON_DEFINE(InteractiveFace)       // 定义为单例类
+    Q_OBJECT
+private:
+    InteractiveFace(QObject *parent = nullptr);
+    ~InteractiveFace();
+
+    // 获取图像url
+    QString getImageUrl();
+public:
+
+    // 设置图像采集回调
+    Q_INVOKABLE void setCameraImageGatherCallBack(QJSValue callback);
+    // 设置发现人脸回调
+    Q_INVOKABLE void setCameraImageAppearCallBack(QJSValue callback);
+    // 设置人脸停留回调(5s)
+    Q_INVOKABLE void setCameraImageRemainCallBack(QJSValue callback);
+    // 回调函数设置
+    Q_INVOKABLE void setCameraImageCallBack(QJSValue gatherCallback,
+                                            QJSValue appearCallback,
+                                            QJSValue remainCallback);
+
+
+
+    // 发现人脸状态
+    Q_INVOKABLE void setCallBackFaceStatus(QJSValue isAppearCallback);
+
+
+    // 相机图像播放 (采集)
+    Q_INVOKABLE void cameraImagePlay();
+    // 相机图像停止 (采集)
+    Q_INVOKABLE void cameraImageStop();
+
+    // 获取图像
+    QImage getImage();
+
+
+protected:
+    QImage requestImage(const QString &, QSize *, const QSize &);
+
+    void timerEvent(QTimerEvent *event);
+private:
+    // 初始化虹软人脸识别
+    void initEngine();
+    // 销毁虹软人脸识别
+    void destroyEngine();
+
+    // 初始化相机
+    void initCamera();
+    // 销毁相机
+    void destroyCamera();
+
+    // 判断电脑上是否存在摄像头
+    bool hasCamera();
+
+
+    void cameraPlay();
+    void cameraStop();
+
+public:
+    QMutex m_mutex;
+
+private:
+    int m_timerId;      // 当前定时器ID
+    int m_FrameId;      // 帧过滤
+
+
+    QImage m_image;     // 图像
+
+    MHandle m_engine;   // 虹软引擎
+    QCamera m_camera;   // 照相机
+
+    QVideoSink m_videoSink;         // 视频接收器
+    QMediaCaptureSession m_session; // 媒体连接器
+
+    // 记录信息
+    qint32 m_laseCount = 0;
+    qint64 m_laseEpoch = 0;
+
+    QJSValue m_imageGatherCallback; // 图像采集回调
+    QJSValue m_imageAppearCallback; // 发现人脸回调
+    QJSValue m_imageRemainCallback; // 人脸停留回调
+
+
+    QJSValue m_isAppearCallback;
+};
+
+#endif // INTERACTIVEFACE_H

+ 129 - 0
Interactive/InteractiveHand.cpp

@@ -0,0 +1,129 @@
+#include "InteractiveHand.h"
+
+InteractiveHand::InteractiveHand() : QQuickImageProvider(QQuickImageProvider::Image)
+{
+    initHandle();
+
+    m_switch = 0;
+    // 图像取1s 1帧
+    m_timerId = startTimer(1000);
+}
+
+InteractiveHand::~InteractiveHand()
+{
+    destroyHandle();
+}
+
+void InteractiveHand::setFingerImageAppearCallBack(QJSValue callback)
+{
+    m_imageAppearCallback = callback;
+}
+
+void InteractiveHand::fingerImagePlay()
+{
+    m_switch = 1;
+}
+
+void InteractiveHand::fingerImageStop()
+{
+    m_switch = 0;
+}
+
+void InteractiveHand::initHandle()
+{
+    m_templateSize = MAX_TEMPLATE_SIZE;
+    m_templateData.resize(MAX_TEMPLATE_SIZE);
+
+    int zkfpErr = ZKFPM_Init(); // 调用DLL中的函数
+    if(zkfpErr == ZKFP_ERR_OK || zkfpErr == ZKFP_ERR_ALREADY_INIT)
+    {
+        int count = ZKFPM_GetDeviceCount();
+        if(count > 0)
+        {
+            m_handle = ZKFPM_OpenDevice(0);
+
+            if(m_handle != NULL)
+            {
+                unsigned int uArgs = 1;
+                unsigned int uSize = 4;
+                ZKFPM_SetParameters(m_handle, 2002, (unsigned char *)&uArgs, 4);
+                ZKFPM_SetParameters(m_handle, 104,  (unsigned char *)&uArgs, 4);
+
+                // 获取宽高
+                ZKFPM_GetParameters(m_handle, 1, (unsigned char *)&m_imageW, &uSize);
+                ZKFPM_GetParameters(m_handle, 2, (unsigned char *)&m_imageH, &uSize);
+                // ZKFPM_GetParameters(m_handle, 3, (unsigned char *)&m_impDpi, &uSize);
+
+                m_imageData.resize(m_imageW * m_imageH);
+
+                m_isInit = true;
+            }
+        }
+    }
+}
+
+void InteractiveHand::destroyHandle()
+{
+    if(m_handle != NULL)
+    {
+        ZKFPM_CloseDevice(m_handle);
+        m_isInit = false;
+    }
+
+    ZKFPM_Terminate();
+}
+
+QString InteractiveHand::getImageUrl()
+{
+    // image://InteractiveHandImage/(0-9999)
+    return QString("image://") +
+           QString(INTERACTIVE_HAND_IMAGE_URL) +
+           QString("/") +
+           // 取随机数,确保图片刷新(Qt机制,两次url地址相同,图片不会显示)
+           QString::number(QRandomGenerator::global()->bounded(10000));
+}
+
+QImage InteractiveHand::requestImage(const QString &, QSize *, const QSize &)
+{
+    return m_image;
+}
+
+void InteractiveHand::timerEvent(QTimerEvent *event)
+{
+    if (event->timerId() == m_timerId)
+    {
+        if (m_switch && m_isInit)
+        {
+            unsigned int templateSize = m_templateSize;
+            int zkfpErr = ZKFPM_AcquireFingerprint(m_handle,
+                                                   reinterpret_cast<unsigned char *>(m_imageData.data()),
+                                                   static_cast<unsigned int>(m_imageData.size()),
+                                                   reinterpret_cast<unsigned char *>(m_templateData.data()),
+                                                   &templateSize);
+            if(zkfpErr == ZKFP_ERR_OK)
+            {
+                QImage::Format format = QImage::Format_Grayscale8;
+
+                // 将字节流转换为 QImage
+                m_image = QImage(reinterpret_cast<const uchar*>(m_imageData.constData()),
+                                 m_imageW,
+                                 m_imageH,
+                                 QImage::Format_Grayscale8);
+
+                if (m_imageAppearCallback.isCallable())
+                {
+                    QJSValueList args;
+                    args << getImageUrl();
+                    m_imageAppearCallback.call(args);
+                }
+            }
+
+        }
+    }
+}
+
+// 获取图像
+QImage InteractiveHand::getImage()
+{
+    return m_image.copy();
+}

+ 91 - 0
Interactive/InteractiveHand.h

@@ -0,0 +1,91 @@
+#ifndef INTERACTIVEHAND_H
+#define INTERACTIVEHAND_H
+
+#include <QObject>
+#include <QJSValue>
+
+#include <QTimer>
+#include <QDateTime>
+
+#include <QImage>
+#include <QVideoFrame>
+#include <QPainter>
+
+#include <QString>
+#include <QBuffer>
+#include <QByteArray>
+#include <QTimerEvent>
+
+#include <QCamera>
+#include <QVideoSink>
+#include <QMediaDevices>
+#include <QMediaCaptureSession>
+#include <QQuickImageProvider>
+
+#include <QtMath>
+#include <QRandomGenerator>
+
+#include "template_singleton.h"
+
+#include "libs/include/libzkfp.h"
+#include "libs/include/libzkfperrdef.h"
+#include "libs/include/libzkfptype.h"
+
+#define INTERACTIVE_HAND_IMAGE_URL "InteractiveHandImage"
+
+
+class InteractiveHand : public QQuickImageProvider
+{
+    SINGLETON_DEFINE(InteractiveHand)       // 定义为单例类
+    Q_OBJECT
+private:
+    InteractiveHand();
+    ~InteractiveHand();
+
+    // 获取图像url
+    QString getImageUrl();
+
+public:
+    // 设置指纹采集回调
+    Q_INVOKABLE void setFingerImageAppearCallBack(QJSValue callback);
+
+    // 指纹图像播放 (采集)
+    Q_INVOKABLE void fingerImagePlay();
+    // 指纹图像停止 (采集)
+    Q_INVOKABLE void fingerImageStop();
+
+public:
+    // 初始化指纹句柄
+    void initHandle();
+    // 销毁指纹句柄
+    void destroyHandle();
+
+    QImage getImage();
+
+protected:
+    QImage requestImage(const QString &, QSize *, const QSize &);
+
+    void timerEvent(QTimerEvent *event);
+
+private:
+    bool m_isInit = false;      // 是否初始化成功
+
+    int m_timerId;      // 当前定时器ID
+    int m_FrameId;      // 帧过滤
+
+    QImage m_image;     // 图像
+
+    HANDLE m_handle;    // 指纹采集器句柄
+    quint8 m_switch;    // 开关标志
+
+    int m_imageW;       // 图像宽
+    int m_imageH;       // 图像高
+    QByteArray m_imageData;     // 图像数据
+
+    QByteArray      m_templateData; // 模板数据
+    unsigned int    m_templateSize; // 模板长度
+
+    QJSValue m_imageAppearCallback; // 发现指纹回调
+};
+
+#endif // INTERACTIVEHAND_H

+ 595 - 0
Interactive/InteractiveHttp.cpp

@@ -0,0 +1,595 @@
+#include "InteractiveHttp.h"
+#include "InteractiveData.h"
+#include "InteractiveFace.h"
+#include "InteractiveHand.h"
+
+
+#include "../user/config.h"
+extern config *pconfig;
+
+QString InteractiveHttp::strToken;
+
+InteractiveHttp::InteractiveHttp(QObject *parent)
+    : QObject{parent}
+{
+
+}
+
+
+bool InteractiveHttp::httpRequestGet(const QString &url, const QByteArray &inData, QByteArray &outData)
+{
+    QNetworkAccessManager* pHttpMgr = new QNetworkAccessManager();
+    QString strUrl = url;
+    if(false == inData.isNull())
+    {
+        strUrl = strUrl + "?" + inData;
+    }
+    // 设置头信息
+    QNetworkRequest requestInfo;
+    requestInfo.setUrl(QUrl(strUrl));
+    requestInfo.setRawHeader("Authorization", InteractiveHttp::strToken.toUtf8());
+
+    // 发送 post 请求
+    QNetworkReply* reply = pHttpMgr->get(requestInfo);
+
+    // 添加超时处理,1ms 超时
+    QEventLoop eventLoop;
+    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
+
+    // 比如设置 1ms 内完成请求,否则就认为是超时
+    QTimer::singleShot(HTTP_REQUEST_TIMEOUT_TIME, &eventLoop, &QEventLoop::quit);
+    eventLoop.exec();
+
+    QByteArray array;
+    if(reply->isFinished()){
+        if (reply->error() == QNetworkReply::NoError) {
+            // 正常结束,读取响应数据
+            QByteArray result = reply->readAll();
+            QString strResult = QString::fromUtf8(result);
+            reply->deleteLater();
+            outData = strResult.toUtf8();
+            return true;
+        }
+        else {
+            // 请求失败
+            QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
+
+            outData = QString("{\"code\":" + statusCode.toString() + ",\"result\":\"" + reply->errorString() + "\"}").toUtf8();
+            reply->deleteLater();
+            return false;
+        }
+    }
+    else {
+        // 请求超时
+        disconnect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
+        reply->abort();
+
+    }
+
+    reply->deleteLater();
+
+    outData =  "{\"code\":400,\"result\":\"failure\"}";
+    return false;
+}
+
+bool InteractiveHttp::httpRequestPostJson(const QString &url, const QByteArray &inData, QByteArray &outData)
+{
+    // 获取当前日期和时间
+    QDateTime currentDateTime = QDateTime::currentDateTime();
+    QString timetamp_str = currentDateTime.toString("yyyy-MM-ddTHH:mm:ssZ");
+
+    QNetworkAccessManager* pHttpMgr = new QNetworkAccessManager();
+    QString strUrl = url;
+    // 设置头信息
+    QNetworkRequest requestInfo;
+    requestInfo.setUrl(QUrl(strUrl));
+    requestInfo.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json"));
+    requestInfo.setRawHeader("Module", "Android_Material");
+    requestInfo.setRawHeader("Authorization", InteractiveHttp::strToken.toUtf8());
+
+    // 发送 post 请求
+    QNetworkReply* reply = pHttpMgr->post(requestInfo, inData);
+
+    // 添加超时处理,1ms 超时
+    QEventLoop eventLoop;
+    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
+
+    // 比如设置 1ms 内完成请求,否则就认为是超时
+    QTimer::singleShot(HTTP_REQUEST_TIMEOUT_TIME, &eventLoop, &QEventLoop::quit);
+    eventLoop.exec();
+
+    if(reply->isFinished()){
+        if (reply->error() == QNetworkReply::NoError) {
+            // 正常结束,读取响应数据
+            QByteArray result = reply->readAll();
+            outData = result;
+            reply->deleteLater();
+            return true;
+        }
+        else {
+            // 请求失败
+            QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
+
+            // qDebug() << "http post failed, error code = " << statusCode.toString() << " error info: " << reply->errorString();
+            outData = QString("{\"code\":" + statusCode.toString() + ",\"result\":\"" + reply->errorString() + "\"}").toUtf8();
+            reply->deleteLater();
+            return false;
+        }
+    }
+    else {
+        // 请求超时
+        disconnect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
+        reply->abort();
+    }
+
+    reply->deleteLater();
+
+    outData = "{\"code\":400,\"result\":\"failure\"}";
+    return false;
+}
+
+bool InteractiveHttp::httpRequestPostFormdata(const QString &url, QList<QHttpPart> &inData, QByteArray &outData)
+{
+    // 获取当前日期和时间
+    QDateTime currentDateTime = QDateTime::currentDateTime();
+    QString timetamp_str = currentDateTime.toString("yyyy-MM-ddTHH:mm:ssZ");
+
+    QNetworkAccessManager* pHttpMgr = new QNetworkAccessManager();
+    QString strUrl = url;
+
+    // 创建multipart表单
+    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
+
+    for (int i = 0; i < inData.size(); ++i)
+    {
+        multiPart->append(inData.at(i));
+    }
+
+
+    // 设置头信息
+    QNetworkRequest requestInfo;
+    requestInfo.setUrl(QUrl(url));
+    requestInfo.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary=" + multiPart->boundary());
+    requestInfo.setRawHeader("Module", "Android_Material");
+    requestInfo.setRawHeader("Authorization", InteractiveHttp::strToken.toUtf8());
+
+    // 发送 post 请求
+    QNetworkReply* reply = pHttpMgr->post(requestInfo, multiPart);
+    multiPart->setParent(reply); // reply删除时会自动删除multiPart
+
+    // 添加超时处理,1ms 超时
+    QEventLoop eventLoop;
+    connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit()));
+
+    // 比如设置 1ms 内完成请求,否则就认为是超时
+    QTimer::singleShot(HTTP_REQUEST_TIMEOUT_TIME, &eventLoop, &QEventLoop::quit);
+    eventLoop.exec();
+
+    if(reply->isFinished()){
+        if (reply->error() == QNetworkReply::NoError) {
+            // 正常结束,读取响应数据
+            QByteArray result = reply->readAll();
+            outData = result;
+            reply->deleteLater();
+            return true;
+        }
+        else {
+            // 请求失败
+            QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
+            // qDebug() << "http post failed, error code = " << statusCode.toString() << " error info: " << reply->errorString();
+            outData = QString("{\"code\":" + statusCode.toString() + ",\"result\":\"" + reply->errorString() + "\"}").toUtf8();
+            reply->deleteLater();
+            return false;
+        }
+    }
+    else {
+        // 请求超时
+        disconnect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);
+        reply->abort();
+    }
+
+    reply->deleteLater();
+
+    outData = "{\"code\":400,\"result\":\"failure\"}";
+    return false;
+}
+
+// 获取异常类型字典值
+QByteArray InteractiveHttp::http_get_exception_type()
+{
+    QString strUrl = "http://" + pconfig->httpHost + "/system/dict/data/type/material_exception";
+    QByteArray inData;
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    return outData;
+}
+
+// 获取严重等级字典值
+QByteArray InteractiveHttp::http_get_severity_level()
+{
+    QString strUrl = "http://" + pconfig->httpHost + "/system/dict/data/type/severity_level";
+    QByteArray inData;
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    return outData;
+}
+
+// 获取用户信息
+QByteArray InteractiveHttp::http_get_getInfo()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->getInfo_url;
+    QByteArray inData;
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    return outData;
+}
+
+// 获取物资柜主界面显示信息
+QByteArray InteractiveHttp::http_get_getCabinetHomePage()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + "/iscs/hardware/material-api/getCabinetHomePage";
+    QByteArray inData = QString("cabinetCode=%1").arg(pconfig->devUuid).toUtf8();
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    return outData;
+}
+
+
+QByteArray InteractiveHttp::http_get_getInstructionsList()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + "/iscs/hardware/material-api/getInstructionsList";
+    QByteArray inData;
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    return outData;
+}
+
+
+// 获取物资信息
+QByteArray InteractiveHttp::http_get_getIsMaterialsPage()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + "/iscs/materials/getIsMaterialsPage";
+    QByteArray inData = QString("current=1&size=-1&cabinetCode=%1").arg(pconfig->devUuid).toUtf8();
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    return outData;
+}
+
+// 开始检查
+// url: /iscs/hardware/material-api/startCheckPlan
+QByteArray InteractiveHttp::http_post_startCheckPlan()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + "/iscs/hardware/material-api/startCheckPlan";
+
+    QByteArray inData;
+    QByteArray outData;
+    {
+        QJsonObject jsonRoot;
+        QDateTime currentDateTime = QDateTime::currentDateTime();
+        qint64 timestampSeconds = currentDateTime.toMSecsSinceEpoch();
+
+        jsonRoot.insert("cabinetCode", pconfig->devUuid);
+        jsonRoot.insert("planId", pconfig->currentPlanId);
+
+        QJsonDocument jsonDoc(jsonRoot);
+        inData = jsonDoc.toJson(QJsonDocument::Compact);
+    }
+
+    httpRequestPostJson(strUrl, inData, outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_post_insertCheckRecord(const QByteArray &json)
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + "/iscs/hardware/material-api/insertCheckRecord";
+
+    QByteArray inData = json;
+    QByteArray outData;
+    httpRequestPostJson(strUrl, inData, outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_post_selectMaterialsByRfidList(const QStringList &rfids)
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->getMaterial_url;
+
+    QByteArray inData;
+    QByteArray outData;
+    {
+        QJsonObject jsonRoot;
+        QDateTime currentDateTime = QDateTime::currentDateTime();
+        qint64 timestampSeconds = currentDateTime.toMSecsSinceEpoch();
+
+        QJsonArray jsonarray;
+        for (const QString& str : rfids)
+        {
+            jsonarray.append(str);
+        }
+        jsonRoot.insert("list", jsonarray);
+        QJsonDocument jsonDoc(jsonRoot);
+        inData = jsonDoc.toJson(QJsonDocument::Compact);
+    }
+
+    httpRequestPostJson(strUrl, inData, outData);
+
+    return outData;
+}
+
+// 获取物资柜物资错放异常
+QByteArray InteractiveHttp::http_get_getIsMaterialsLoanExceptionPage()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->getIsMaterialsLoanExceptionPage_url;
+    QByteArray inData = QString("loanFromCode=" + pconfig->devUuid).toUtf8();
+    inData += "&current=1&size=-1&exceptionType=0&status=0";
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    // TempWriteData("C:/Users/HP/Desktop/Temp/0.txt", outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_get_getSysUserCharacteristicPage()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->getSysUserCharacteristicPage_url;
+    QByteArray inData = QString("userId=" + pconfig->userId).toUtf8();
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_get_getLastCheckPlanByCabinetCode()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->getMaterialCheckPlan_url;
+    QByteArray inData = QString("cabinetCode=" + pconfig->devUuid).toUtf8();
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_get_selectExMaterialTypeById()
+{
+
+    return QByteArray();
+}
+
+QByteArray InteractiveHttp::http_get_selectIsMaterialsCabinetByCode()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + "/iscs/cabinet/selectIsMaterialsCabinetByCode";
+    QByteArray inData = QString("cabinetCode=" + pconfig->devUuid).toUtf8();
+    QByteArray outData;
+
+    httpRequestGet(strUrl, inData, outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_post_insertSubmitPlan()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->postSubmit_url;
+    QByteArray inData;
+    QByteArray outData;
+    {
+        QJsonObject jsonObjRoot;
+        QString url = pconfig->postSubmit_url;
+        jsonObjRoot.insert("cabinetCode", pconfig->devUuid);
+        jsonObjRoot.insert("planId", pconfig->currentPlanId);
+
+        QJsonDocument jsonDoc(jsonObjRoot);
+        inData = jsonDoc.toJson(QJsonDocument::Compact);
+    }
+
+    httpRequestPostJson(strUrl, inData, outData);
+
+    return outData;
+}
+
+// 上报异常
+QByteArray InteractiveHttp::http_post_insertIsException(const QString &json)
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + "/iscs/exception/insertIsException";
+    QByteArray inData = json.toUtf8();
+    QByteArray outData;
+
+    httpRequestPostJson(strUrl, inData, outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_post_deleteSysUserCharacteristicByRecordIds(const QString &recordIds)
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + "/system/user/characteristic/deleteSysUserCharacteristicByRecordIds";
+    // if (!recordIds.isEmpty())
+    // {
+    //     strUrl += "?recordIds=";
+    //     for (int i = 0; i < recordIds.size(); ++i)
+    //     {
+    //         strUrl += recordIds.at(i);
+    //         if (i != recordIds.size() - 1)
+    //         {
+    //             strUrl += ",";
+    //         }
+    //     }
+    // }
+    strUrl += recordIds;
+
+    QByteArray inData;
+    QByteArray outData;
+
+    httpRequestPostJson(strUrl, inData, outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_post_insertUserFace()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->insertUserFace_url;
+    QList<QHttpPart> inData;
+    QByteArray outData;
+
+    // 添加用户名
+    QHttpPart httpPartUserName;
+    httpPartUserName.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"userName\""));
+    httpPartUserName.setBody(SINGLETON_CREATE(InteractiveData)()->m_userName.toUtf8());
+    inData.append(httpPartUserName);
+
+    // 添加用户图片
+    QImage image = SINGLETON_CREATE(InteractiveFace)()->getImage();
+    QByteArray imageData;
+    QBuffer buffer(&imageData);
+    buffer.open(QIODevice::WriteOnly);
+    image.save(&buffer, "PNG");
+
+    QHttpPart httpPartImage;
+    httpPartImage.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
+    httpPartImage.setHeader(QNetworkRequest::ContentDispositionHeader,
+                            QVariant(QString("form-data; name=\"file\"; filename=\"face.png\"")));
+
+    httpPartImage.setBody(imageData);
+    inData.append(httpPartImage);
+
+    httpRequestPostFormdata(strUrl, inData, outData);
+
+    // TempWriteData("C:/Users/HP/Desktop/Temp/1.txt", outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_post_insertUserFingerprintDat(const QString &group)
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->addfinger_url;
+    QList<QHttpPart> inData;
+    QByteArray outData;
+
+    // 添加用户名
+    QHttpPart httpPartUserName;
+    httpPartUserName.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"userName\""));
+    httpPartUserName.setBody(SINGLETON_CREATE(InteractiveData)()->m_userName.toUtf8());
+    inData.append(httpPartUserName);
+
+    // 添加用户组
+    QHttpPart httpPartUserGroup;
+    httpPartUserGroup.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"group\""));
+    httpPartUserGroup.setBody(group.toUtf8());
+    inData.append(httpPartUserGroup);
+
+    // 添加用户图片
+    QImage image = SINGLETON_CREATE(InteractiveHand)()->getImage();
+    QByteArray imageData;
+    QBuffer buffer(&imageData);
+    buffer.open(QIODevice::WriteOnly);
+    image.save(&buffer, "BMP");
+
+    QHttpPart httpPartImage;
+    httpPartImage.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/bmp"));
+    httpPartImage.setHeader(QNetworkRequest::ContentDispositionHeader,
+                            QVariant(QString("form-data; name=\"file\"; filename=\"face.bmp\"")));
+
+    httpPartImage.setBody(imageData);
+    inData.append(httpPartImage);
+
+    httpRequestPostFormdata(strUrl, inData, outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_post_loginByFace()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->loginByFace_url;
+    QList<QHttpPart> inData;
+    QByteArray outData;
+
+    // 添加用户图片
+    QImage image = SINGLETON_CREATE(InteractiveFace)()->getImage();
+    QByteArray imageData;
+    QBuffer buffer(&imageData);
+    buffer.open(QIODevice::WriteOnly);
+    image.save(&buffer, "PNG");
+
+    QHttpPart httpPartImage;
+    httpPartImage.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
+    httpPartImage.setHeader(QNetworkRequest::ContentDispositionHeader,
+                            QVariant(QString("form-data; name=\"file\"; filename=\"face.png\"")));
+
+    httpPartImage.setBody(imageData);
+    inData.append(httpPartImage);
+
+    httpRequestPostFormdata(strUrl, inData, outData);
+
+    return outData;
+}
+
+QByteArray InteractiveHttp::http_post_loginByFingerprintDat()
+{
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->fingerLogin_url;
+    QList<QHttpPart> inData;
+    QByteArray outData;
+
+    // 添加用户图片
+    QImage image = SINGLETON_CREATE(InteractiveHand)()->getImage();
+    QByteArray imageData;
+    QBuffer buffer(&imageData);
+    buffer.open(QIODevice::WriteOnly);
+    image.save(&buffer, "BMP");
+
+
+    QHttpPart httpPartImage;
+    httpPartImage.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/bmp"));
+    httpPartImage.setHeader(QNetworkRequest::ContentDispositionHeader,
+                            QVariant(QString("form-data; name=\"file\"; filename=\"face.bmp\"")));
+
+    httpPartImage.setBody(imageData);
+    inData.append(httpPartImage);
+
+    httpRequestPostFormdata(strUrl, inData, outData);
+
+    return outData;
+}
+
+// 用于临时存储服务器请求响应的函数
+// TempWriteData("C:/Users/HP/Desktop/Temp/0.txt", outData);
+void InteractiveHttp::TempWriteData(const QString &path, const QByteArray &data)
+{
+    QFile file(path);
+    if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+        file.write(data);
+        file.close();
+    }
+}

+ 133 - 0
Interactive/InteractiveHttp.h

@@ -0,0 +1,133 @@
+#ifndef INTERACTIVEHTTP_H
+#define INTERACTIVEHTTP_H
+
+#include <QObject>
+
+#include <QTimer>
+#include <QFile>
+#include <QEventLoop>
+
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QHttpMultiPart>
+#include <QHttpPart>
+
+#include <QJsonParseError>
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QJsonValue>
+
+#define HTTP_REQUEST_TIMEOUT_TIME 1000 * 20
+
+class InteractiveHttp : public QObject
+{
+    Q_OBJECT
+public:
+    explicit InteractiveHttp(QObject *parent = nullptr);
+
+    // 全局函数
+    static bool httpRequestGet(const QString &url, const QByteArray &inData, QByteArray &outData);
+    static bool httpRequestPostJson(const QString &url, const QByteArray &inData, QByteArray &outData);
+    static bool httpRequestPostFormdata(const QString &url, QList<QHttpPart> &inData, QByteArray &outData);
+
+    static QString strToken;
+private:
+    static void TempWriteData(const QString &path, const QByteArray &data);
+
+public:
+
+    // 获取异常类型字典值
+    // url: /system/dict/data/type/material_exception
+    static QByteArray http_get_exception_type();
+
+    // 获取严重等级字典值
+    // url: /system/dict/data/type/severity_level
+    static QByteArray http_get_severity_level();
+
+    // 获取用户信息
+    // url: /getInfo
+    static QByteArray http_get_getInfo();
+
+
+    // 获取主界面显示信息
+    // url: /iscs/hardware/material-api/getCabinetHomePage
+    static QByteArray http_get_getCabinetHomePage();
+
+
+    // 查询物资使用说明
+    // url: /prod-api/iscs/hardware/material-api/getInstructionsList
+    static QByteArray http_get_getInstructionsList();
+
+    // 获取物资信息
+    // url: /prod-api/iscs/materials/getIsMaterialsPage
+    static QByteArray http_get_getIsMaterialsPage();
+
+    // 获取物资柜物资错放异常
+    // url: /iscs/exception/getIsMaterialsLoanExceptionPage
+    static QByteArray http_get_getIsMaterialsLoanExceptionPage();
+
+    // 查询用户特征
+    // url: /system/user/characteristic/getSysUserCharacteristicPage
+    static QByteArray http_get_getSysUserCharacteristicPage();
+
+
+    // 查询物资检查计划
+    // url: /iscs/hardware/material-api/getLastCheckPlanByCabinetCode
+    static QByteArray http_get_getLastCheckPlanByCabinetCode();
+
+    // 查询异常物资信息
+    // url: /iscs/hardware/material-api/selectExMaterialTypeById
+    static QByteArray http_get_selectExMaterialTypeById();
+
+    // 根据物资柜code获取物资柜ID
+    // url: /iscs/cabinet/selectIsMaterialsCabinetByCode
+    static QByteArray http_get_selectIsMaterialsCabinetByCode();
+
+
+
+    // 开始检查
+    // url: /iscs/hardware/material-api/startCheckPlan
+    static QByteArray http_post_startCheckPlan();
+
+    // 保存检查状态
+    // url: /iscs/hardware/material-api/insertCheckRecord
+    static QByteArray http_post_insertCheckRecord(const QByteArray &json);
+
+    // 查询物资信息
+    // url: /iscs/hardware/material-api/selectMaterialsByRfidList
+    static QByteArray http_post_selectMaterialsByRfidList(const QStringList &rfids);
+
+    // 提交最终检查结果
+    // url: /iscs/hardware/material-api/insertSubmitPlan
+    static QByteArray http_post_insertSubmitPlan();
+
+
+    // 上报异常
+    // url: /iscs/exception/insertIsException
+    static QByteArray http_post_insertIsException(const QString &json);
+
+    // 删除用户特征
+    // url: /system/user/characteristic/deleteSysUserCharacteristicByRecordIds
+    static QByteArray http_post_deleteSysUserCharacteristicByRecordIds(const QString &recordIds);
+
+    // 新增面部信息
+    // url: /system/user/characteristic/insertUserFace
+    static QByteArray http_post_insertUserFace();
+
+    // 新增指纹信息
+    // url: /system/user/characteristic/insertUserFingerprintDat
+    static QByteArray http_post_insertUserFingerprintDat(const QString &group);
+
+    // 根据人脸登录
+    // url: /loginByFace
+    static QByteArray http_post_loginByFace();
+
+    // 根据指纹登录
+    // url: /loginByFingerprintDat
+    static QByteArray http_post_loginByFingerprintDat();
+
+};
+
+#endif // INTERACTIVEHTTP_H

+ 6 - 0
Interactive/InteractiveTask.cpp

@@ -0,0 +1,6 @@
+#include "InteractiveTask.h"
+
+InteractiveTask::InteractiveTask(QObject *parent)
+    : QObject(parent)
+{
+}

+ 73 - 0
Interactive/InteractiveTask.h

@@ -0,0 +1,73 @@
+#ifndef INTERACTIVETASK_H
+#define INTERACTIVETASK_H
+
+#include <QObject>
+#include <QJSValue>
+#include <QVariant>
+
+class InteractiveTask : public QObject
+{
+    Q_OBJECT
+public:
+    enum TaskType
+    {
+        TypeDataCacheRefresh,                       // 刷新缓存信息
+
+        TypeMaterialInfoListRefresh,                // http get 请求, 获取物资信息列表
+
+        TypeMaterialReplaceRefreshListModel,        // 刷新物资更换视图model
+        TypeMaterialManualReplaceRefreshListModel,  // 刷新手动更换视图model
+
+        TypeMaterialManualReplaceSubmit,            // 物资手动更换提交
+
+        TypeMaterialExceptionReport,                // 异常上报
+        TypeMaterialExceptionRefreshListModel,      // 刷新异常列表
+
+
+        TypeHttpGet_exception_type,                     // 获取异常类型字典值
+        TypeHttpGet_severity_level,                     // 获取严重等级字典值
+        TypeHttpGet_getInfo,                            // 获取用户信息
+        TypeHttpGet_getCabinetHomePage,                 // 获取主界面信息
+        TypeHttpGet_getInstructionsList,                // 查询用户使用说明
+        TypeHttpGet_selectIsMaterialsCabinetByCode,     // 获取物资柜ID
+
+        TypeHttpGet_getIsMaterialsLoanExceptionPage,    // 获取异常信息
+        TypeHttpGet_getSysUserCharacteristicPage,       // 查询用户特征(指纹、面部)
+        TypeHttpGet_getIsMaterialsPage,                 // 查询物资信息All
+        TypeHttpGet_getLastCheckPlanByCabinetCode,      // 查询当前用户的物资检查计划
+
+        TypeHttpPost_startCheckPlan,                    // 开始物资检查计划
+        TypeHttpPost_insertCheckRecord,                 // 物资检查保存
+        TypeHttpPost_insertSubmitPlan,                  // 提交最终检查结果
+        TypeHttpPost_deleteSysUserCharacteristicByRecordIds,    // 删除人员特征
+        TypeHttpPost_insertUserFace,                    // 新增人脸记录
+        TypeHttpPost_insertUserFingerprintDat,          // 新增指纹记录
+        TypeHttpPost_loginByFace,                       // 人脸登录
+        TypeHttpPost_loginByFingerprintDat,             // 指纹登录
+        TypeHttpPost_insertIsException,                 // 上报异常
+
+        TypeViewWait,                                   // 视图等待(ms)
+        TypeViewRefresh_AbnormalReport,                 // 视图刷新-异常上报
+
+    };
+
+    enum TaskStat
+    {
+        StatWaitStart,      // 等待开始
+        StatExecAfoot,      // 正在进行
+        StatCompleted,      // 已经完成
+        StatFailStart,      // 启动失败
+    };
+
+    Q_ENUM(TaskType)
+public:
+    explicit InteractiveTask(QObject *parent = nullptr);
+
+    TaskType type;    // 任务类型
+    TaskStat stat;    // 任务状态
+    QVariant request; // 任务请求信息
+    QVariant respond; // 任务响应信息
+    QJSValue callback;// 任务回调
+};
+
+#endif // INTERACTIVETASK_H

+ 244 - 0
Interactive/InteractiveWork.cpp

@@ -0,0 +1,244 @@
+#include "InteractiveWork.h"
+
+#include "RunAbstract.h"
+#include "RunDataCacheRefresh.h"
+#include "RunMaterialInfoListRefresh.h"
+#include "RunMaterialReplaceRefreshListModel.h"
+#include "RunMaterialManualReplaceRefreshListModel.h"
+#include "RunMaterialManualReplaceSubmit.h"
+#include "RunMaterialExceptionRefreshListModel.h"
+
+#include "RunHttpGet_exception_type.h"
+#include "RunHttpGet_severity_level.h"
+#include "RunHttpGet_getInfo.h"
+#include "RunHttpGet_getCabinetHomePage.h"
+#include "RunHttpGet_getInstructionsList.h"
+
+#include "RunHttpGet_getIsMaterialsLoanExceptionPage.h"
+#include "RunHttpGet_getSysUserCharacteristicPage.h"
+#include "RunHttpGet_getIsMaterialsPage.h"
+#include "RunHttpGet_getLastCheckPlanByCabinetCode.h"
+#include "RunHttpGet_selectIsMaterialsCabinetByCode.h"
+
+#include "RunHttpPost_startCheckPlan.h"
+#include "RunHttpPost_deleteSysUserCharacteristicByRecordIds.h"
+#include "RunHttpPost_insertCheckRecord.h"
+#include "RunHttpPost_insertSubmitPlan.h"
+#include "RunHttpPost_insertUserFace.h"
+#include "RunHttpPost_insertUserFingerprintDat.h"
+#include "RunHttpPost_loginByFace.h"
+#include "RunHttpPost_loginByFingerprintDat.h"
+#include "RunHttpPost_insertIsException.h"
+
+#include "RunViewWait.h"
+#include "RunViewRefresh_AbnormalReport.h"
+
+InteractiveWork::InteractiveWork(QObject *parent)
+    : QThread(parent)
+{
+    m_bThread = true;
+}
+
+InteractiveWork::~InteractiveWork()
+{
+    m_bThread = false;
+}
+
+void InteractiveWork::appendTask(InteractiveTask *task)
+{
+    QMutexLocker locker(&m_mutex);
+    task->stat = InteractiveTask::StatWaitStart;
+    m_listTask.append(task);
+}
+
+void InteractiveWork::run()
+{
+    while (m_bThread)
+    {
+        QThread::msleep(10);
+
+        QMutexLocker locker(&m_mutex);
+        for (auto it = m_listTask.begin(); it != m_listTask.end();)
+        {
+
+            InteractiveTask *task = *it;
+            // 任务等待开始
+            if (task->stat == InteractiveTask::StatWaitStart)
+            {
+                RunAbstract *run = nullptr;
+
+                switch(task->type)
+                {
+                case InteractiveTask::TypeDataCacheRefresh:
+                    run = new RunDataCacheRefresh(task, &m_mutex);
+                    break;
+
+                case InteractiveTask::TypeMaterialInfoListRefresh:
+                    run = new RunMaterialInfoListRefresh(task, &m_mutex);
+                    break;
+
+                case InteractiveTask::TypeMaterialReplaceRefreshListModel:
+                    run = new RunMaterialReplaceRefreshListModel(task, &m_mutex);
+                    break;
+
+                case InteractiveTask::TypeMaterialManualReplaceRefreshListModel:
+                    run = new RunMaterialManualReplaceRefreshListModel(task, &m_mutex);
+                    break;
+
+                case InteractiveTask::TypeMaterialManualReplaceSubmit:
+                    run = new RunMaterialManualReplaceSubmit(task, &m_mutex);
+                    break;
+
+                // 刷新异常列表
+                case InteractiveTask::TypeMaterialExceptionRefreshListModel:
+                    run = new RunMaterialExceptionRefreshListModel(task, &m_mutex);
+                    break;
+
+
+                    // 获取异常类型字典值
+                case InteractiveTask::TypeHttpGet_exception_type:
+                    run = new RunHttpGet_exception_type(task, &m_mutex);
+                    break;
+
+                    // 获取严重等级字典值
+                case InteractiveTask::TypeHttpGet_severity_level:
+                    run = new RunHttpGet_severity_level(task, &m_mutex);
+                    break;
+
+                    // 获取用户信息
+                case InteractiveTask::TypeHttpGet_getInfo:
+                    run = new RunHttpGet_getInfo(task, &m_mutex);
+                    break;
+
+                    // 获取主界面信息
+                case InteractiveTask::TypeHttpGet_getCabinetHomePage:
+                    run = new RunHttpGet_getCabinetHomePage(task, &m_mutex);
+                    break;
+
+                    // 获取用户使用说明
+                case InteractiveTask::TypeHttpGet_getInstructionsList:
+                    run = new RunHttpGet_getInstructionsList(task, &m_mutex);
+                    break;
+
+                    // 获取异常信息
+                case InteractiveTask::TypeHttpGet_getIsMaterialsLoanExceptionPage:
+                    run = new RunHttpGet_getIsMaterialsLoanExceptionPage(task, &m_mutex);
+                    break;
+
+                    // 查询用户特征
+                case InteractiveTask::TypeHttpGet_getSysUserCharacteristicPage:
+                    run = new RunHttpGet_getSysUserCharacteristicPage(task, &m_mutex);
+                    break;
+
+                    // 查询当前机柜物资检查计划
+                case InteractiveTask::TypeHttpGet_getLastCheckPlanByCabinetCode:
+                    run = new RunHttpGet_getLastCheckPlanByCabinetCode(task, &m_mutex);
+                    break;
+
+                    // 查询物资信息
+                case InteractiveTask::TypeHttpGet_getIsMaterialsPage:
+                    run = new RunHttpGet_getIsMaterialsPage(task, &m_mutex);
+                    break;
+
+                // 获取物资柜ID
+                case InteractiveTask::TypeHttpGet_selectIsMaterialsCabinetByCode:
+                    run = new RunHttpGet_selectIsMaterialsCabinetByCode(task, &m_mutex);
+                    break;
+
+
+                    // 开始物资检查计划
+                case InteractiveTask::TypeHttpPost_startCheckPlan:
+                    run = new RunHttpPost_startCheckPlan(task, &m_mutex);
+                    break;
+
+
+                    // 物资检查计划保存
+                case InteractiveTask::TypeHttpPost_insertCheckRecord:
+                    run = new RunHttpPost_insertCheckRecord(task, &m_mutex);
+                    break;
+
+                    // 提交最终检查结果
+                case InteractiveTask::TypeHttpPost_insertSubmitPlan:
+                    run = new RunHttpPost_insertSubmitPlan(task, &m_mutex);
+                    break;
+
+                    // 删除人员特征
+                case InteractiveTask::TypeHttpPost_deleteSysUserCharacteristicByRecordIds:
+                    run = new RunHttpPost_deleteSysUserCharacteristicByRecordIds(task, &m_mutex);
+                    break;
+
+                    // 新增人脸记录
+                case InteractiveTask::TypeHttpPost_insertUserFace:
+                    run = new RunHttpPost_insertUserFace(task, &m_mutex);
+                    break;
+
+                    // 新增指纹记录
+                case InteractiveTask::TypeHttpPost_insertUserFingerprintDat:
+                    run = new RunHttpPost_insertUserFingerprintDat(task, &m_mutex);
+                    break;
+
+                    // 人脸登录
+                case InteractiveTask::TypeHttpPost_loginByFace:
+                    run = new RunHttpPost_loginByFace(task, &m_mutex);
+                    break;
+
+                    // 指纹登录
+                case InteractiveTask::TypeHttpPost_loginByFingerprintDat:
+                    run = new RunHttpPost_loginByFingerprintDat(task, &m_mutex);
+                    break;
+
+                    // 异常上报
+                case InteractiveTask::TypeHttpPost_insertIsException:
+                    run = new RunHttpPost_insertIsException(task, &m_mutex);
+                    break;
+
+
+                    // 视图等待
+                case InteractiveTask::TypeViewWait:
+                    run = new RunViewWait(task, &m_mutex);
+                    break;
+
+                    // 视图刷新-异常上报
+                case InteractiveTask::TypeViewRefresh_AbnormalReport:
+                    run = new RunViewRefresh_AbnormalReport(task, &m_mutex);
+                    break;
+
+
+
+                    // 丢弃无效任务
+                default:
+                    task->stat = InteractiveTask::StatFailStart;
+                    break;
+                }
+
+                if (run != nullptr)
+                {
+                    task->stat = InteractiveTask::StatExecAfoot;
+                    QThreadPool::globalInstance()->start(run);
+                }
+            }
+            // 任务正在执行
+            else if (task->stat == InteractiveTask::StatExecAfoot)
+            {
+                // 执行中...
+            }
+            // 任务执行完成
+            else if (task->stat == InteractiveTask::StatCompleted)
+            {
+                emit signal_completed(task);
+                it = m_listTask.erase(it);
+                continue;
+            }
+            // 任务执行失败
+            else if (task->stat == InteractiveTask::StatFailStart)
+            {
+                emit signal_failstart(task);
+                it = m_listTask.erase(it);
+                continue;
+            }
+
+            ++it;
+        }
+
+    }
+}

+ 35 - 0
Interactive/InteractiveWork.h

@@ -0,0 +1,35 @@
+#ifndef INTERACTIVEWORK_H
+#define INTERACTIVEWORK_H
+
+#include <QThread>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QThreadPool>
+
+#include "InteractiveTask.h"
+#include "template_singleton.h"
+
+class InteractiveWork : public QThread
+{
+    SINGLETON_DEFINE(InteractiveWork)
+    Q_OBJECT
+private:
+    explicit InteractiveWork(QObject *parent = nullptr);
+    ~InteractiveWork();
+public:
+    void appendTask(InteractiveTask *task);
+
+protected:
+    void run();
+
+signals:
+    void signal_completed(InteractiveTask *task);
+    void signal_failstart(InteractiveTask *task);
+
+private:
+    bool m_bThread;
+    QMutex m_mutex;
+    QList<InteractiveTask *> m_listTask;
+};
+
+#endif // INTERACTIVEWORK_H

+ 37 - 0
Interactive/RunAbstract.cpp

@@ -0,0 +1,37 @@
+#include "RunAbstract.h"
+
+RunAbstract::RunAbstract(InteractiveTask *task, QMutex *mutex)
+{
+    m_pTask = task;
+    m_pMutex = mutex;
+}
+
+RunAbstract::~RunAbstract()
+{
+    if (m_pTask && m_pMutex)
+    {
+        QMutexLocker writeLocker(m_pMutex);
+        m_pTask->stat = InteractiveTask::StatCompleted;
+    }
+}
+
+void RunAbstract::setRespond(const QVariant &respond)
+{
+    if (m_pTask && m_pMutex)
+    {
+        QMutexLocker writeLocker(m_pMutex);
+        m_pTask->respond = respond;
+    }
+}
+
+
+QVariant RunAbstract::getRequest() const
+{
+    QVariant request;
+    if (m_pTask && m_pMutex)
+    {
+        QMutexLocker writeLocker(m_pMutex);
+        request = m_pTask->request;
+    }
+    return request;
+}

+ 34 - 0
Interactive/RunAbstract.h

@@ -0,0 +1,34 @@
+#ifndef RUNABSTRACT_H
+#define RUNABSTRACT_H
+
+#include <QRunnable>
+#include <QMutex>
+#include <QMutexLocker>
+
+#include <QJsonValue>
+#include <QJsonArray>
+#include <QJsonObject>
+#include <QJsonDocument>
+
+#include "InteractiveTask.h"
+#include "InteractiveHttp.h"
+#include "InteractiveData.h"
+
+class RunAbstract : public QRunnable
+{
+public:
+    RunAbstract(InteractiveTask *task = nullptr, QMutex *mutex = nullptr);
+    virtual ~RunAbstract();
+
+protected:
+    void setRespond(const QVariant &respond);
+    QVariant getRequest() const;
+
+protected:
+    InteractiveTask *m_pTask;
+    QMutex *m_pMutex;
+};
+
+
+
+#endif // RUNABSTRACT_H

+ 542 - 0
Interactive/RunDataCacheRefresh.cpp

@@ -0,0 +1,542 @@
+#include "RunDataCacheRefresh.h"
+
+#include "InteractiveData.h"
+#include "InteractiveHttp.h"
+
+#include "../user/httpclient.h"
+#include "../user/config.h"
+extern config *pconfig;
+
+
+#include <QFile>
+
+// 用于临时存储http json返回值的函数
+void TempFuncWriteData(const QString &path, const QByteArray &data)
+{
+    QFile file(path);
+    if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+        file.write(data);
+        file.close();
+    }
+}
+
+
+RunDataCacheRefresh::RunDataCacheRefresh(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+
+}
+
+void RunDataCacheRefresh::run()
+{
+    // 获取物资属性值
+    httpGetMaterialProp();
+    // 获取物资类型
+    httpGetMaterialType();
+    // 获取物资信息
+    // httpGetMaterialInfo();
+
+
+    // // 获取异常类型字典值
+    // httpGetExceptionTypeDict();
+    // // 获取严重等级字典值
+    // httpGetSeverityLevelDict();
+    // 获取异常物资信息
+    httpGetExMaterialInfo();
+
+    // 获取物资柜物资错放异常
+
+}
+
+
+void RunDataCacheRefresh::httpGetMaterialProp()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->getMaterialPropList_url;
+    QByteArray inData = QString("cabinetCode=" + pconfig->devUuid).toUtf8();
+    QByteArray outData;
+
+    httpClient::getRequest(strUrl, pSingletonData->m_token, inData, outData);
+
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+
+    // 如果数据发生改变,缓存信息
+    if (pSingletonData->m_jsonCacheMaterialProp != outData)
+    {
+        // 缓存json信息
+        pSingletonData->m_jsonCacheMaterialProp = outData;
+
+        // 清理缓存数据
+        pSingletonData->m_dataCacheMaterialPropId.clear();
+        pSingletonData->m_dataCacheMaterialPropName.clear();
+        pSingletonData->m_dataCacheMaterialPropPropertyId.clear();
+        pSingletonData->m_dataCacheMaterialPropPropertyName.clear();
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+                {
+                    QJsonObject jsonObjData = jsonObjRoot.value("data").toObject();
+                    if(jsonObjRoot.value("code").toInt() == 200 && jsonObjData.contains("records"))
+                    {
+                        QJsonArray jsonArrRecords = jsonObjData.value("records").toArray();
+                        for (int i = 0; i < jsonArrRecords.count(); ++i)
+                        {
+                            if (!jsonArrRecords.at(i).isObject())
+                            {
+                                continue;
+                            }
+
+                            QJsonObject jsonObjRecord = jsonArrRecords.at(i).toObject();
+
+                            QString recordId = jsonObjRecord.value("recordId").toString();
+                            QString valueName = jsonObjRecord.value("valueName").toString();
+                            QString propertyId = jsonObjRecord.value("propertyId").toString();
+                            QString propertyName = jsonObjRecord.value("propertyName").toString();
+
+
+                            pSingletonData->m_dataCacheMaterialPropId.append(recordId);
+                            pSingletonData->m_dataCacheMaterialPropName.insert(recordId, valueName);
+                            pSingletonData->m_dataCacheMaterialPropPropertyId.insert(recordId, propertyId);
+                            pSingletonData->m_dataCacheMaterialPropPropertyName.insert(recordId, propertyName);
+
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+void RunDataCacheRefresh::httpGetMaterialType()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->getMaterialTypeList_url;
+    QByteArray inData = QString("current=1&size=-1").toUtf8();
+    QByteArray outData;
+
+    httpClient::getRequest(strUrl, pSingletonData->m_token, inData, outData);
+
+
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+
+
+    // 如果数据发生改变,缓存信息
+    if (pSingletonData->m_jsonCacheMaterialType != outData)
+    {
+        // 缓存json信息
+        pSingletonData->m_jsonCacheMaterialType = outData;
+
+        // 清理缓存数据
+        pSingletonData->m_dataCacheMaterialTypeId.clear();
+        pSingletonData->m_dataCacheMaterialTypeName.clear();
+        pSingletonData->m_dataCacheMaterialTypePicture.clear();
+        pSingletonData->m_dataCacheMaterialTypeAncestors.clear();
+        pSingletonData->m_dataCacheMaterialTypePropertyIds.clear();
+
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+                {
+                    QJsonObject jsonObjData = jsonObjRoot.value("data").toObject();
+                    if(jsonObjRoot.value("code").toInt() == 200 && jsonObjData.contains("records"))
+                    {
+                        QJsonArray jsonArrRecords = jsonObjData.value("records").toArray();
+                        for (int i = 0; i < jsonArrRecords.count(); ++i)
+                        {
+                            if (!jsonArrRecords.at(i).isObject())
+                            {
+                                continue;
+                            }
+
+                            QJsonObject jsonObjRecord = jsonArrRecords.at(i).toObject();
+
+                            QString materialsTypeId = jsonObjRecord.value("materialsTypeId").toString();
+                            QString materialsTypeName = jsonObjRecord.value("materialsTypeName").toString();
+                            QString materialsTypeIcon = jsonObjRecord.value("materialsTypeIcon").toString();
+                            QString materialsTypePicture = jsonObjRecord.value("materialsTypePicture").toString();
+                            QStringList ancestors = jsonObjRecord.value("ancestors").toString().split(",");
+                            QStringList propertyIds = jsonObjRecord.value("propertyIds").toString().split(",");
+
+                            pSingletonData->m_dataCacheMaterialTypeId.append(materialsTypeId);
+                            pSingletonData->m_dataCacheMaterialTypeName.insert(materialsTypeId, materialsTypeName);
+                            pSingletonData->m_dataCacheMaterialTypeIcon.insert(materialsTypeId, materialsTypeIcon);
+                            pSingletonData->m_dataCacheMaterialTypePicture.insert(materialsTypeId, materialsTypePicture);
+                            pSingletonData->m_dataCacheMaterialTypeAncestors.insert(materialsTypeId, ancestors);
+                            pSingletonData->m_dataCacheMaterialTypePropertyIds.insert(materialsTypeId, propertyIds);
+
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+void RunDataCacheRefresh::httpGetMaterialInfo()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->getMaterialInfoList_url;
+    QByteArray inData = QString("cabinetCode=" + pconfig->devUuid).toUtf8();
+    QByteArray outData;
+
+    httpClient::getRequest(strUrl, pSingletonData->m_token, inData, outData);
+
+
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // 如果数据发生改变,缓存信息
+    if (pSingletonData->m_jsonCacheMaterialInfo != outData)
+    {
+        // 缓存json信息
+        pSingletonData->m_jsonCacheMaterialInfo = outData;
+
+        // 清理缓存数据
+        pSingletonData->m_dataCacheMaterialInfoId.clear();
+        pSingletonData->m_dataCacheMaterialInfoName.clear();
+        pSingletonData->m_dataCacheMaterialInfoRfid.clear();
+        pSingletonData->m_dataCacheMaterialInfoStat.clear();
+        pSingletonData->m_dataCacheMaterialInfoDate.clear();
+        pSingletonData->m_dataCacheMaterialInfoTypeId.clear();
+
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+                {
+                    QJsonObject jsonObjData = jsonObjRoot.value("data").toObject();
+                    if(jsonObjRoot.value("code").toInt() == 200 && jsonObjData.contains("records"))
+                    {
+                        QJsonArray jsonArrRecords = jsonObjData.value("records").toArray();
+                        for (int i = 0; i < jsonArrRecords.count(); ++i)
+                        {
+                            if (!jsonArrRecords.at(i).isObject())
+                            {
+                                continue;
+                            }
+
+                            QJsonObject jsonObjRecord = jsonArrRecords.at(i).toObject();
+
+                            QString materialsId = jsonObjRecord.value("materialsId").toString();
+                            QString materialsName = jsonObjRecord.value("materialsName").toString();
+                            QString materialsRfid = jsonObjRecord.value("materialsRfid").toString();
+                            QString expirationDate = jsonObjRecord.value("expirationDate").toString();
+                            QString materialsTypeId = jsonObjRecord.value("materialsTypeId").toString();
+                            QString propertiesValueId = jsonObjRecord.value("propertiesValueId").toString();
+                            QString loanState = jsonObjRecord.value("loanState").toString();
+                            QString status = jsonObjRecord.value("status").toString();
+
+                            pSingletonData->m_dataCacheMaterialInfoId.append(materialsId);
+                            pSingletonData->m_dataCacheMaterialInfoName.insert(materialsId, materialsName);
+                            pSingletonData->m_dataCacheMaterialInfoRfid.insert(materialsId, materialsRfid);
+                            pSingletonData->m_dataCacheMaterialInfoLoan.insert(materialsId, loanState);
+                            pSingletonData->m_dataCacheMaterialInfoStat.insert(materialsId, status);
+                            pSingletonData->m_dataCacheMaterialInfoDate.insert(materialsId, expirationDate);
+                            pSingletonData->m_dataCacheMaterialInfoTypeId.insert(materialsId, materialsTypeId);
+                            pSingletonData->m_dataCacheMaterialInfoPropId.insert(materialsId, propertiesValueId);
+
+                            // 如果类型不存在
+
+                            if (materialsTypeId != "")
+                            {
+                                if (!pSingletonData->m_dataCacheMaterialTypeId.contains(materialsTypeId))
+                                {
+                                    QString materialsTypeName = jsonObjRecord.value("materialsTypeName").toString();
+                                    QString materialsTypeIcon = jsonObjRecord.value("materialsTypeIcon").toString();
+                                    QString materialsTypePicture = jsonObjRecord.value("materialsTypePicture").toString();
+
+                                    // ...
+
+                                    pSingletonData->m_dataCacheMaterialTypeId.append(materialsTypeId);
+                                    pSingletonData->m_dataCacheMaterialTypeName.insert(materialsTypeId, materialsTypeName);
+                                    pSingletonData->m_dataCacheMaterialTypeIcon.insert(materialsTypeId, materialsTypeIcon);
+                                    pSingletonData->m_dataCacheMaterialTypePicture.insert(materialsTypeId, materialsTypePicture);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+
+void RunDataCacheRefresh::httpGetExceptionTypeDict()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    // 访问http服务,获取字典值
+    QString strUrl = "http://" + pconfig->httpHost + "/dev-api/system/dict/data/type/" + "exception_type";
+    QByteArray inData;
+    QByteArray outData;
+
+    httpClient::getRequest(strUrl, pSingletonData->m_token, inData, outData);
+
+    // // 进行数据写操作
+    // QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // // 如果数据发生改变,缓存信息
+    // if (pSingletonData->m_jsonCacheExceptionTypeDict != outData)
+    // {
+    //     // 缓存json信息
+    //     pSingletonData->m_jsonCacheExceptionTypeDict = outData;
+
+
+    //     // 异常类型字典清理数据缓存
+    //     pSingletonData->m_dataCacheExceptionTypeDictCode.clear();
+    //     pSingletonData->m_dataCacheExceptionTypeDictLabel.clear();
+    //     pSingletonData->m_dataCacheExceptionTypeDictValue.clear();
+
+
+    //     QJsonParseError error;
+    //     QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+    //     if (error.error == QJsonParseError::NoError)
+    //     {
+    //         if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+    //         {
+    //             QJsonObject jsonObjRoot = jsonDoc.object();
+    //             if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+    //             {
+    //                 if (jsonObjRoot.value("code").toInt() == 200 && jsonObjRoot.value("data").isArray())
+    //                 {
+    //                     QJsonArray jsonArrData = jsonObjRoot.value("data").toArray();
+
+    //                     for (int i = 0; i < jsonArrData.size(); ++i)
+    //                     {
+    //                         if (!jsonArrData.at(i).isObject())
+    //                         {
+    //                             continue;
+    //                         }
+    //                         QJsonObject jsonObjData = jsonArrData.at(i).toObject();
+
+    //                         QString dictCode = jsonObjData.value("dictCode").toString();
+    //                         QString dictLabel = jsonObjData.value("dictLabel").toString();
+    //                         QString dictValue = jsonObjData.value("dictValue").toString();
+
+    //                         if (pSingletonData->m_dataCacheExceptionTypeDictCode.contains(dictCode))
+    //                         {
+    //                             continue;
+    //                         }
+
+    //                         pSingletonData->m_dataCacheExceptionTypeDictCode.append(dictCode);
+    //                         pSingletonData->m_dataCacheExceptionTypeDictLabel.insert(dictCode, dictLabel);
+    //                         pSingletonData->m_dataCacheExceptionTypeDictValue.insert(dictCode, dictValue);
+    //                     }
+    //                 }
+    //             }
+    //         }
+    //     }
+    // }
+
+}
+
+void RunDataCacheRefresh::httpGetSeverityLevelDict()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    // 访问http服务,获取字典值
+    QString strUrl = "http://" + pconfig->httpHost + "/dev-api/system/dict/data/type/" + "severity_level";
+    QByteArray inData;
+    QByteArray outData;
+
+    httpClient::getRequest(strUrl, pSingletonData->m_token, inData, outData);
+
+    // // 进行数据写操作
+    // QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // // 如果数据发生改变,缓存信息
+    // if (pSingletonData->m_jsonCacheSeverityLevelDict != outData)
+    // {
+    //     // 缓存json信息
+    //     pSingletonData->m_jsonCacheSeverityLevelDict = outData;
+
+
+    //     // 异常类型字典清理数据缓存
+    //     pSingletonData->m_dataCacheSeverityLevelDictCode.clear();
+    //     pSingletonData->m_dataCacheSeverityLevelDictLabel.clear();
+    //     pSingletonData->m_dataCacheSeverityLevelDictValue.clear();
+
+
+    //     QJsonParseError error;
+    //     QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+    //     if (error.error == QJsonParseError::NoError)
+    //     {
+    //         if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+    //         {
+    //             QJsonObject jsonObjRoot = jsonDoc.object();
+    //             if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+    //             {
+    //                 if (jsonObjRoot.value("code").toInt() == 200 && jsonObjRoot.value("data").isArray())
+    //                 {
+    //                     QJsonArray jsonArrData = jsonObjRoot.value("data").toArray();
+
+    //                     for (int i = 0; i < jsonArrData.size(); ++i)
+    //                     {
+    //                         if (!jsonArrData.at(i).isObject())
+    //                         {
+    //                             continue;
+    //                         }
+    //                         QJsonObject jsonObjData = jsonArrData.at(i).toObject();
+
+    //                         QString dictCode = jsonObjData.value("dictCode").toString();
+    //                         QString dictLabel = jsonObjData.value("dictLabel").toString();
+    //                         QString dictValue = jsonObjData.value("dictValue").toString();
+
+    //                         if (pSingletonData->m_dataCacheSeverityLevelDictCode.contains(dictCode))
+    //                         {
+    //                             continue;
+    //                         }
+
+    //                         pSingletonData->m_dataCacheSeverityLevelDictCode.append(dictCode);
+    //                         pSingletonData->m_dataCacheSeverityLevelDictLabel.insert(dictCode, dictLabel);
+    //                         pSingletonData->m_dataCacheSeverityLevelDictValue.insert(dictCode, dictValue);
+    //                     }
+    //                 }
+    //             }
+    //         }
+    //     }
+    // }
+
+}
+
+void RunDataCacheRefresh::httpGetExMaterialInfo()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->getExMaterialInfoList_url;
+    QByteArray inData = QString("cabinetCode=" + pconfig->devUuid).toUtf8();
+    QByteArray outData;
+
+    httpClient::getRequest(strUrl, pSingletonData->m_token, inData, outData);
+
+
+    qDebug() << outData;
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // 如果数据发生改变,缓存信息
+    if (pSingletonData->m_jsonCacheExMaterialInfo != outData)
+    {
+        // 缓存json信息
+        pSingletonData->m_jsonCacheExMaterialInfo = outData;
+
+        pSingletonData->m_dataCacheExMaterialTypeId.clear();
+        pSingletonData->m_dataCacheExMaterialTypeExNumber.clear();
+
+        // 物资信息清理数据缓存
+        pSingletonData->m_dataCacheExMaterialInfoId.clear();
+        pSingletonData->m_dataCacheExMaterialInfoName.clear();
+        pSingletonData->m_dataCacheExMaterialInfoRfid.clear();
+        pSingletonData->m_dataCacheExMaterialInfoStat.clear();
+        pSingletonData->m_dataCacheExMaterialInfoDate.clear();
+        pSingletonData->m_dataCacheExMaterialInfoTypeId.clear();
+        pSingletonData->m_dataCacheExMaterialInfoPropId.clear();
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+                {
+                    if (jsonObjRoot.value("code").toInt() == 200)
+                    {
+                        QJsonArray jsonArrData = jsonObjRoot.value("data").toArray();
+
+                        for (int i = 0; i < jsonArrData.size(); ++i)
+                        {
+                            if (!jsonArrData.at(i).isObject())
+                            {
+                                continue;
+                            }
+
+                            QJsonObject jsonObjData = jsonArrData.at(i).toObject();
+
+                            if (!jsonObjData.contains("materials"))
+                            {
+                                continue;
+                            }
+
+
+                            QString materialsTypeName = jsonObjData.value("materialsTypeName").toString();
+                            QString materialsTypeId = jsonObjData.value("materialsTypeId").toString();
+                            int exNumber = jsonObjData.value("exNumber").toInt();
+
+
+                            if (materialsTypeId == "0")
+                            {
+                                continue;
+                            }
+
+                            if (!pSingletonData->m_dataCacheExMaterialTypeId.contains(materialsTypeId))
+                            {
+                                pSingletonData->m_dataCacheExMaterialTypeId.append(materialsTypeId);
+                                pSingletonData->m_dataCacheExMaterialTypeExNumber.insert(materialsTypeId, exNumber);
+                            }
+
+                            if (materialsTypeName == "全部")
+                            {
+                                continue;
+                            }
+
+                            QJsonArray jsonArrRecords = jsonObjData.value("materials").toArray();
+
+                            for (int j = 0; j < jsonArrRecords.count(); ++j)
+                            {
+                                if (!jsonArrRecords.at(j).isObject())
+                                {
+                                    continue;
+                                }
+
+                                QJsonObject jsonObjMaterials = jsonArrRecords.at(j).toObject();
+
+                                QString materialsId = jsonObjMaterials.value("materialsId").toString();
+                                QString materialsName = jsonObjMaterials.value("materialsName").toString();
+                                QString materialsRfid = jsonObjMaterials.value("materialsRfid").toString();
+                                QString expirationDate = jsonObjMaterials.value("expirationDate").toString();
+                                QString materialsTypeId = jsonObjMaterials.value("materialsTypeId").toString();
+                                QString propertiesValueId = jsonObjMaterials.value("propertiesValueId").toString();
+                                QString loanState = jsonObjMaterials.value("loanState").toString();
+                                QString status = jsonObjMaterials.value("status").toString();
+
+                                if (pSingletonData->m_dataCacheExMaterialInfoId.contains(materialsId))
+                                {
+                                    continue;
+                                }
+
+                                pSingletonData->m_dataCacheExMaterialInfoId.append(materialsId);
+                                pSingletonData->m_dataCacheExMaterialInfoName.insert(materialsId, materialsName);
+                                pSingletonData->m_dataCacheExMaterialInfoRfid.insert(materialsId, materialsRfid);
+                                pSingletonData->m_dataCacheExMaterialInfoLoan.insert(materialsId, loanState);
+                                pSingletonData->m_dataCacheExMaterialInfoStat.insert(materialsId, status);
+                                pSingletonData->m_dataCacheExMaterialInfoDate.insert(materialsId, expirationDate);
+                                pSingletonData->m_dataCacheExMaterialInfoTypeId.insert(materialsId, materialsTypeId);
+                                pSingletonData->m_dataCacheExMaterialInfoPropId.insert(materialsId, propertiesValueId);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 36 - 0
Interactive/RunDataCacheRefresh.h

@@ -0,0 +1,36 @@
+#ifndef RUNDATACACHEREFRESH_H
+#define RUNDATACACHEREFRESH_H
+
+#include "RunAbstract.h"
+
+class RunDataCacheRefresh : public RunAbstract
+{
+public:
+    RunDataCacheRefresh(InteractiveTask *task, QMutex *mutex);
+
+public:
+
+    // 定时刷新获取
+    // 获取异常类型字典值
+    static void httpGetExceptionTypeDict();
+    // 获取严重等级字典值
+    static void httpGetSeverityLevelDict();
+
+    // 获取物资属性值
+    static void httpGetMaterialProp();
+    // 获取物资类型
+    static void httpGetMaterialType();
+
+    // 实时获取
+    // 获取物资信息
+    static void httpGetMaterialInfo();
+
+    // 获取异常物资信息 url: /dev-api/iscs/hardware/material-api/selectExMaterialTypeById
+    static void httpGetExMaterialInfo();
+
+
+protected:
+    void run();
+};
+
+#endif // RUNDATACACHEREFRESH_H

+ 69 - 0
Interactive/RunHttpGet_exception_type.cpp

@@ -0,0 +1,69 @@
+#include "RunHttpGet_exception_type.h"
+
+RunHttpGet_exception_type::RunHttpGet_exception_type(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+void RunHttpGet_exception_type::run()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    QByteArray outData = InteractiveHttp::http_get_exception_type();
+
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // 如果数据发生改变,缓存信息
+    if (pSingletonData->m_jsonCacheExceptionTypeDict != outData)
+    {
+        // 缓存json信息
+        pSingletonData->m_jsonCacheExceptionTypeDict = outData;
+
+
+        // 异常类型字典清理数据缓存
+        pSingletonData->m_dataCacheExceptionTypeDictCode.clear();
+        pSingletonData->m_dataCacheExceptionTypeDictLabel.clear();
+        pSingletonData->m_dataCacheExceptionTypeDictValue.clear();
+
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+                {
+                    if (jsonObjRoot.value("code").toInt() == 200 && jsonObjRoot.value("data").isArray())
+                    {
+                        QJsonArray jsonArrData = jsonObjRoot.value("data").toArray();
+
+                        for (int i = 0; i < jsonArrData.size(); ++i)
+                        {
+                            if (!jsonArrData.at(i).isObject())
+                            {
+                                continue;
+                            }
+                            QJsonObject jsonObjData = jsonArrData.at(i).toObject();
+
+                            QString dictCode = jsonObjData.value("dictCode").toString();
+                            QString dictLabel = jsonObjData.value("dictLabel").toString();
+                            QString dictValue = jsonObjData.value("dictValue").toString();
+
+                            if (pSingletonData->m_dataCacheExceptionTypeDictCode.contains(dictCode))
+                            {
+                                continue;
+                            }
+
+                            pSingletonData->m_dataCacheExceptionTypeDictCode.append(dictCode);
+                            pSingletonData->m_dataCacheExceptionTypeDictLabel.insert(dictCode, dictLabel);
+                            pSingletonData->m_dataCacheExceptionTypeDictValue.insert(dictCode, dictValue);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 16 - 0
Interactive/RunHttpGet_exception_type.h

@@ -0,0 +1,16 @@
+#ifndef RUNHTTPGET_EXCEPTION_TYPE_H
+#define RUNHTTPGET_EXCEPTION_TYPE_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_exception_type : public RunAbstract
+{
+public:
+    RunHttpGet_exception_type(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+
+#endif // RUNHTTPGET_EXCEPTION_TYPE_H

+ 78 - 0
Interactive/RunHttpGet_getCabinetHomePage.cpp

@@ -0,0 +1,78 @@
+#include "RunHttpGet_getCabinetHomePage.h"
+#include "../user/config.h"
+extern config *pconfig;
+
+RunHttpGet_getCabinetHomePage::RunHttpGet_getCabinetHomePage(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+void RunHttpGet_getCabinetHomePage::run()
+{
+
+    QByteArray outData = InteractiveHttp::http_get_getCabinetHomePage();
+
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // 如果数据发生改变,缓存信息
+    if (!outData.isEmpty())
+    {
+        pconfig->changeNumber = 0;
+        pconfig->checkNumber = 0;
+        pconfig->rarNumber = 0;
+
+        pconfig->bottomTypeName.clear();
+        pconfig->bottomTypeIcon.clear();
+        pconfig->bottomTypeAll.clear();
+        pconfig->bottomTypeBorrowable.clear();
+
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code"))
+                {
+                    if (jsonObjRoot.value("code").toInt() == 200)
+                    {
+                        QJsonObject jsonObjData = jsonObjRoot.value("data").toObject();
+
+                        QString changeNumber = QString::number(jsonObjData.value("changeNumber").toInt());
+                        QString checkNumber = QString::number(jsonObjData.value("checkNumber").toInt());
+                        QString rarNumber = QString::number(jsonObjData.value("rarNumber").toInt());
+
+                        pconfig->changeNumber = changeNumber;
+                        pconfig->checkNumber = checkNumber;
+                        pconfig->rarNumber = rarNumber;
+
+
+                        QJsonArray jsonArrList = jsonObjData.value("list").toArray();
+                        for (int i = 0; i < jsonArrList.size(); ++i)
+                        {
+                            QJsonObject jsonObjList = jsonArrList.at(i).toObject();
+
+                            QString materialsTypeId = jsonObjList.value("materialsTypeId").toString();
+                            QString materialsTypeName = jsonObjList.value("materialsTypeName").toString();
+                            QString materialsTypeIcon = jsonObjList.value("materialsTypeIcon").toString();
+                            QString allNumber = QString::number(jsonObjList.value("allNumber").toInt());
+                            QString borrowableNumber = QString::number(jsonObjList.value("borrowableNumber").toInt());
+
+                            pconfig->bottomTypeName.insert(materialsTypeId, materialsTypeName);
+                            pconfig->bottomTypeIcon.insert(materialsTypeId, materialsTypeIcon);
+                            pconfig->bottomTypeAll.insert(materialsTypeId, allNumber);
+                            pconfig->bottomTypeBorrowable.insert(materialsTypeId, borrowableNumber);
+                        }
+
+                    }
+                }
+            }
+        }
+
+    }
+}

+ 15 - 0
Interactive/RunHttpGet_getCabinetHomePage.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPGET_GETCABINETHOMEPAGE_H
+#define RUNHTTPGET_GETCABINETHOMEPAGE_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_getCabinetHomePage : public RunAbstract
+{
+public:
+    RunHttpGet_getCabinetHomePage(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPGET_GETCABINETHOMEPAGE_H

+ 71 - 0
Interactive/RunHttpGet_getInfo.cpp

@@ -0,0 +1,71 @@
+#include "RunHttpGet_getInfo.h"
+#include <QDebug>
+#include "../user/config.h"
+extern config *pconfig;
+
+RunHttpGet_getInfo::RunHttpGet_getInfo(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+void RunHttpGet_getInfo::run()
+{
+
+    QByteArray outData = InteractiveHttp::http_get_getInfo();
+    // 关键调试输出
+    qDebug() << "HTTP raw response:" << outData;
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // 如果数据发生改变,缓存信息
+    if (!outData.isEmpty())
+    {
+        pSingletonData->m_roles.clear();
+        pSingletonData->m_permissions.clear();
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("user"))
+                {
+                    if (jsonObjRoot.value("code").toInt() == 200)
+                    {
+                        if (jsonObjRoot.value("user").isObject())
+                        {
+                            QJsonObject jsonObjUser = jsonObjRoot.value("user").toObject();
+                            pconfig->userId = jsonObjUser.value("userId").toString();
+                            // pconfig->username = jsonObjUser.value("userName").toString();
+                            pSingletonData->m_userName = jsonObjUser.value("userName").toString();
+                        }
+
+                        if (jsonObjRoot.value("roles").isArray())
+                        {
+                            QJsonArray jsonArrRoles = jsonObjRoot.value("roles").toArray();
+                            for (int i = 0; i < jsonArrRoles.size(); ++i)
+                            {
+                                QString jsonStrRole = jsonArrRoles.at(i).toString();
+                                pSingletonData->m_roles.insert(jsonStrRole);
+                            }
+                        }
+
+                        if (jsonObjRoot.value("permissions").isArray())
+                        {
+                            QJsonArray jsonArrPermissions = jsonObjRoot.value("permissions").toArray();
+                            for (int i = 0; i < jsonArrPermissions.size(); ++i)
+                            {
+                                QString jsonStrPermission = jsonArrPermissions.at(i).toString();
+                                pSingletonData->m_permissions.insert(jsonStrPermission);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+}

+ 15 - 0
Interactive/RunHttpGet_getInfo.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPGET_GETINFO_H
+#define RUNHTTPGET_GETINFO_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_getInfo : public RunAbstract
+{
+public:
+    RunHttpGet_getInfo(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPGET_GETINFO_H

+ 13 - 0
Interactive/RunHttpGet_getInstructionsList.cpp

@@ -0,0 +1,13 @@
+#include "RunHttpGet_getInstructionsList.h"
+
+RunHttpGet_getInstructionsList::RunHttpGet_getInstructionsList(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+void RunHttpGet_getInstructionsList::run()
+{
+    QByteArray outData = InteractiveHttp::http_get_getInstructionsList();
+    setRespond(outData);
+}

+ 15 - 0
Interactive/RunHttpGet_getInstructionsList.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPGET_GETINSTRUCTIONSLIST_H
+#define RUNHTTPGET_GETINSTRUCTIONSLIST_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_getInstructionsList : public RunAbstract
+{
+public:
+    RunHttpGet_getInstructionsList(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPGET_GETINSTRUCTIONSLIST_H

+ 147 - 0
Interactive/RunHttpGet_getIsMaterialsLoanExceptionPage.cpp

@@ -0,0 +1,147 @@
+#include "RunHttpGet_getIsMaterialsLoanExceptionPage.h"
+#include "InteractiveData.h"
+
+RunHttpGet_getIsMaterialsLoanExceptionPage::RunHttpGet_getIsMaterialsLoanExceptionPage(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+void RunHttpGet_getIsMaterialsLoanExceptionPage::http_get_getIsMaterialsLoanExceptionPage()
+{
+
+    QByteArray outData = InteractiveHttp::http_get_getIsMaterialsLoanExceptionPage();
+
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // 如果数据发生改变,缓存信息
+    if (pSingletonData->m_jsonCacheMaterialsLoanExceptionInfo != outData)
+    {
+        pSingletonData->m_jsonCacheMaterialsLoanExceptionInfo = outData;
+
+        // 物资信息清理数据缓存
+        pSingletonData->m_dataCacheMaterialLoadRfid.clear();
+        pSingletonData->m_dataCacheMaterialLoanName.clear();
+        // pSingletonData->m_dataCacheMaterialLoanRfid.clear();
+        pSingletonData->m_dataCacheMaterialLoanTypeIcon.clear();
+        pSingletonData->m_dataCacheMaterialLoanTypePicture.clear();
+
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+                {
+                    if (jsonObjRoot.value("code").toInt() == 200 && jsonObjRoot.value("data").isObject())
+                    {
+                        QJsonObject jsonObjData = jsonObjRoot.value("data").toObject();
+
+                        if (jsonObjData.contains("records") && jsonObjData.value("records").isArray())
+                        {
+                            QJsonArray jsonArrRecords = jsonObjData.value("records").toArray();
+
+                            for (int i = 0; i < jsonArrRecords.size(); ++i)
+                            {
+                                if (!jsonArrRecords.at(i).isObject())
+                                {
+                                    continue;
+                                }
+
+                                QJsonObject jsonObjRecords = jsonArrRecords.at(i).toObject();
+
+                                // QString materialsId = jsonObjRecords.value("materialsId").toString();
+                                QString materialsName = jsonObjRecords.value("materialsName").toString();
+                                QString materialsRfid = jsonObjRecords.value("materialsRfid").toString();
+                                QString materialsTypeIcon = jsonObjRecords.value("materialsTypeIcon").toString();
+                                QString materialsTypePicture = jsonObjRecords.value("materialsTypePicture").toString();
+
+                                if (!pSingletonData->m_dataCacheMaterialLoadRfid.contains(materialsRfid) && materialsRfid != "")
+                                {
+                                    pSingletonData->m_dataCacheMaterialLoadRfid.append(materialsRfid);
+                                    pSingletonData->m_dataCacheMaterialLoanName.insert(materialsRfid, materialsName);
+                                    // pSingletonData->m_dataCacheMaterialLoanRfid.insert(materialsId, materialsRfid);
+                                    pSingletonData->m_dataCacheMaterialLoanTypeIcon.insert(materialsRfid, materialsTypeIcon);
+                                    pSingletonData->m_dataCacheMaterialLoanTypePicture.insert(materialsRfid, materialsTypePicture);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+void RunHttpGet_getIsMaterialsLoanExceptionPage::run()
+{
+    QByteArray outData = InteractiveHttp::http_get_getIsMaterialsLoanExceptionPage();
+
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // 如果数据发生改变,缓存信息
+    if (pSingletonData->m_jsonCacheMaterialsLoanExceptionInfo != outData)
+    {
+        pSingletonData->m_jsonCacheMaterialsLoanExceptionInfo = outData;
+
+        // 物资信息清理数据缓存
+        pSingletonData->m_dataCacheMaterialLoadRfid.clear();
+        pSingletonData->m_dataCacheMaterialLoanName.clear();
+        // pSingletonData->m_dataCacheMaterialLoanRfid.clear();
+        pSingletonData->m_dataCacheMaterialLoanTypeIcon.clear();
+        pSingletonData->m_dataCacheMaterialLoanTypePicture.clear();
+
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+                {
+                    if (jsonObjRoot.value("code").toInt() == 200 && jsonObjRoot.value("data").isObject())
+                    {
+                        QJsonObject jsonObjData = jsonObjRoot.value("data").toObject();
+
+                        if (jsonObjData.contains("records") && jsonObjData.value("records").isArray())
+                        {
+                            QJsonArray jsonArrRecords = jsonObjData.value("records").toArray();
+
+                            for (int i = 0; i < jsonArrRecords.size(); ++i)
+                            {
+                                if (!jsonArrRecords.at(i).isObject())
+                                {
+                                    continue;
+                                }
+
+                                QJsonObject jsonObjRecords = jsonArrRecords.at(i).toObject();
+
+                                // QString materialsId = jsonObjRecords.value("materialsId").toString();
+                                QString materialsName = jsonObjRecords.value("materialsName").toString();
+                                QString materialsRfid = jsonObjRecords.value("materialsRfid").toString();
+                                QString materialsTypeIcon = jsonObjRecords.value("materialsTypeIcon").toString();
+                                QString materialsTypePicture = jsonObjRecords.value("materialsTypePicture").toString();
+
+                                if (!pSingletonData->m_dataCacheMaterialLoadRfid.contains(materialsRfid) && materialsRfid != "")
+                                {
+                                    pSingletonData->m_dataCacheMaterialLoadRfid.append(materialsRfid);
+                                    pSingletonData->m_dataCacheMaterialLoanName.insert(materialsRfid, materialsName);
+                                    // pSingletonData->m_dataCacheMaterialLoanRfid.insert(materialsId, materialsRfid);
+                                    pSingletonData->m_dataCacheMaterialLoanTypeIcon.insert(materialsRfid, materialsTypeIcon);
+                                    pSingletonData->m_dataCacheMaterialLoanTypePicture.insert(materialsRfid, materialsTypePicture);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 17 - 0
Interactive/RunHttpGet_getIsMaterialsLoanExceptionPage.h

@@ -0,0 +1,17 @@
+#ifndef RUNHTTPGET_GETISMATERIALSLOANEXCEPTIONPAGE_H
+#define RUNHTTPGET_GETISMATERIALSLOANEXCEPTIONPAGE_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_getIsMaterialsLoanExceptionPage : public RunAbstract
+{
+public:
+    RunHttpGet_getIsMaterialsLoanExceptionPage(InteractiveTask *task, QMutex *mutex);
+
+    static void http_get_getIsMaterialsLoanExceptionPage();
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPGET_GETISMATERIALSLOANEXCEPTIONPAGE_H

+ 87 - 0
Interactive/RunHttpGet_getIsMaterialsPage.cpp

@@ -0,0 +1,87 @@
+#include "RunHttpGet_getIsMaterialsPage.h"
+
+RunHttpGet_getIsMaterialsPage::RunHttpGet_getIsMaterialsPage(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+void RunHttpGet_getIsMaterialsPage::run()
+{
+    QByteArray outData = InteractiveHttp::http_get_getIsMaterialsPage();
+
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+
+    if (pSingletonData->m_jsonCacheMaterialInfo != outData)
+    {
+        // 清理缓存数据
+        pSingletonData->m_dataCacheMaterialInfoId.clear();
+        pSingletonData->m_dataCacheMaterialInfoName.clear();
+        pSingletonData->m_dataCacheMaterialInfoRfid.clear();
+
+        pSingletonData->m_dataCacheMaterialInfoLoan.clear();
+        pSingletonData->m_dataCacheMaterialInfoStat.clear();
+        pSingletonData->m_dataCacheMaterialInfoDate.clear();
+
+        pSingletonData->m_dataCacheMaterialInfoTypeId.clear();
+        pSingletonData->m_dataCacheMaterialInfoPropId.clear();
+        pSingletonData->m_dataCacheMaterialInfoCabinetId.clear();
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+                {
+                    QJsonObject jsonObjData = jsonObjRoot.value("data").toObject();
+                    if(jsonObjRoot.value("code").toInt() == 200 && jsonObjData.contains("records"))
+                    {
+                        QJsonArray jsonArrRecords = jsonObjData.value("records").toArray();
+                        for (int i = 0; i < jsonArrRecords.count(); ++i)
+                        {
+                            if (!jsonArrRecords.at(i).isObject())
+                            {
+                                continue;
+                            }
+
+                            QJsonObject jsonObjRecord = jsonArrRecords.at(i).toObject();
+
+                            QString materialsId = jsonObjRecord.value("materialsId").toString();
+                            QString materialsName = jsonObjRecord.value("materialsName").toString();
+                            QString materialsRfid = jsonObjRecord.value("materialsRfid").toString();
+
+                            QString loanState = jsonObjRecord.value("loanState").toString();
+                            QString status = jsonObjRecord.value("status").toString();
+                            QString expirationDate = jsonObjRecord.value("expirationDate").toString();
+
+                            QString materialsTypeId = jsonObjRecord.value("materialsTypeId").toString();
+                            QString propertiesValueId = jsonObjRecord.value("propertiesValueId").toString();
+                            QString materialsCabinetId = jsonObjRecord.value("materialsCabinetId").toString();
+
+                            if (!pSingletonData->m_dataCacheMaterialInfoId.contains(materialsId))
+                            {
+                                pSingletonData->m_dataCacheMaterialInfoId.append(materialsId);
+                                pSingletonData->m_dataCacheMaterialInfoName.insert(materialsId, materialsName);
+                                pSingletonData->m_dataCacheMaterialInfoRfid.insert(materialsId, materialsRfid);
+
+                                pSingletonData->m_dataCacheMaterialInfoLoan.insert(materialsId, loanState);
+                                pSingletonData->m_dataCacheMaterialInfoStat.insert(materialsId, status);
+                                pSingletonData->m_dataCacheMaterialInfoDate.insert(materialsId, expirationDate);
+
+                                pSingletonData->m_dataCacheMaterialInfoTypeId.insert(materialsId, materialsTypeId);
+                                pSingletonData->m_dataCacheMaterialInfoPropId.insert(materialsId, propertiesValueId);
+                                pSingletonData->m_dataCacheMaterialInfoCabinetId.insert(materialsId, materialsCabinetId);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 15 - 0
Interactive/RunHttpGet_getIsMaterialsPage.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPGET_GETISMATERIALSPAGE_H
+#define RUNHTTPGET_GETISMATERIALSPAGE_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_getIsMaterialsPage : public RunAbstract
+{
+public:
+    RunHttpGet_getIsMaterialsPage(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPGET_GETISMATERIALSPAGE_H

+ 70 - 0
Interactive/RunHttpGet_getLastCheckPlanByCabinetCode.cpp

@@ -0,0 +1,70 @@
+#include "RunHttpGet_getLastCheckPlanByCabinetCode.h"
+
+RunHttpGet_getLastCheckPlanByCabinetCode::RunHttpGet_getLastCheckPlanByCabinetCode(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunHttpGet_getLastCheckPlanByCabinetCode::run()
+{
+    QByteArray outData = InteractiveHttp::http_get_getLastCheckPlanByCabinetCode();
+
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    setRespond(outData);
+
+    // // 进行数据写操作
+    // QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // if (!outData.isEmpty())
+    // {
+    //     // 清理Data缓存
+    //     pSingletonData->m_checkPlanStatus = -1;
+
+    //     // 解析 JSON 数据
+    //     QJsonParseError parseError;
+    //     QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &parseError);
+
+    //     if (parseError.error != QJsonParseError::NoError)
+    //     {
+    //         qWarning() << "JSON 解析错误:" << parseError.errorString();
+    //         return;
+    //     }
+
+    //     if (!jsonDoc.isObject())
+    //     {
+    //         qWarning() << "JSON 数据不是对象";
+    //         return;
+    //     }
+
+    //     QJsonObject jsonObjRoot = jsonDoc.object();
+
+    //     // 检查 code 字段
+    //     if (jsonObjRoot["code"].toInt() == 200) {
+    //         QJsonObject jsonObjData = jsonObjRoot["data"].toObject();
+
+    //         // 获取 planId 并转换为整数
+    //         int planId = jsonObjData["planId"].toInt();
+
+    //         // 获取其他字段
+    //         QString planDate = jsonObjData["planDate"].toString();
+    //         int planStat = jsonObjData["status"].toInt();
+    //         QString strPlanStat = "未定义";
+
+    //         // 根据 status 值设置 strPlanStat
+    //         switch (planStat) {
+    //         case 0: strPlanStat = "未开始"; break;
+    //         case 1: strPlanStat = "进行中"; break;
+    //         case 2: strPlanStat = "已完成"; break;
+    //         // 添加更多状态...
+    //         default: strPlanStat = "未定义";
+    //         }
+    //         pSingletonData->m_checkPlanStatus = planStat;
+
+    //     } else {
+    //         qWarning() << "返回码不为 200,实际为:" << jsonObjRoot["code"].toInt();
+    //     }
+
+    // }
+}

+ 16 - 0
Interactive/RunHttpGet_getLastCheckPlanByCabinetCode.h

@@ -0,0 +1,16 @@
+#ifndef RUNHTTPGET_GETLASTCHECKPLANBYCABINETCODE_H
+#define RUNHTTPGET_GETLASTCHECKPLANBYCABINETCODE_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_getLastCheckPlanByCabinetCode : public RunAbstract
+{
+public:
+    RunHttpGet_getLastCheckPlanByCabinetCode(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+
+};
+
+#endif // RUNHTTPGET_GETLASTCHECKPLANBYCABINETCODE_H

+ 25 - 0
Interactive/RunHttpGet_getSysUserCharacteristicPage.cpp

@@ -0,0 +1,25 @@
+#include "RunHttpGet_getSysUserCharacteristicPage.h"
+
+RunHttpGet_getSysUserCharacteristicPage::RunHttpGet_getSysUserCharacteristicPage(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunHttpGet_getSysUserCharacteristicPage::run()
+{
+    QByteArray outData = InteractiveHttp::http_get_getSysUserCharacteristicPage();
+
+    setRespond(outData);
+
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    if (!outData.isEmpty())
+    {
+
+
+    }
+
+}

+ 16 - 0
Interactive/RunHttpGet_getSysUserCharacteristicPage.h

@@ -0,0 +1,16 @@
+#ifndef RUNHTTPGET_GETSYSUSERCHARACTERISTICPAGE_H
+#define RUNHTTPGET_GETSYSUSERCHARACTERISTICPAGE_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_getSysUserCharacteristicPage : public RunAbstract
+{
+public:
+    RunHttpGet_getSysUserCharacteristicPage(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+
+};
+
+#endif // RUNHTTPGET_GETSYSUSERCHARACTERISTICPAGE_H

+ 14 - 0
Interactive/RunHttpGet_selectExMaterialTypeById.cpp

@@ -0,0 +1,14 @@
+#include "RunHttpGet_selectExMaterialTypeById.h"
+
+RunHttpGet_selectExMaterialTypeById::RunHttpGet_selectExMaterialTypeById(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+
+
+void RunHttpGet_selectExMaterialTypeById::run()
+{
+
+}

+ 16 - 0
Interactive/RunHttpGet_selectExMaterialTypeById.h

@@ -0,0 +1,16 @@
+#ifndef RUNHTTPGET_SELECTEXMATERIALTYPEBYID_H
+#define RUNHTTPGET_SELECTEXMATERIALTYPEBYID_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_selectExMaterialTypeById : public RunAbstract
+{
+public:
+    RunHttpGet_selectExMaterialTypeById(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+
+};
+
+#endif // RUNHTTPGET_SELECTEXMATERIALTYPEBYID_H

+ 50 - 0
Interactive/RunHttpGet_selectIsMaterialsCabinetByCode.cpp

@@ -0,0 +1,50 @@
+#include "RunHttpGet_selectIsMaterialsCabinetByCode.h"
+
+#include "../user/config.h"
+extern config *pconfig;
+
+
+RunHttpGet_selectIsMaterialsCabinetByCode::RunHttpGet_selectIsMaterialsCabinetByCode(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+
+
+void RunHttpGet_selectIsMaterialsCabinetByCode::run()
+{
+    QByteArray outData = InteractiveHttp::http_get_selectIsMaterialsCabinetByCode();
+
+
+
+    qDebug() << outData;
+
+    // 解析 JSON 数据
+    QJsonParseError parseError;
+    QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &parseError);
+
+    if (parseError.error != QJsonParseError::NoError)
+    {
+        qWarning() << "JSON 解析错误:" << parseError.errorString();
+        return;
+    }
+
+    if (!jsonDoc.isObject())
+    {
+        qWarning() << "JSON 数据不是对象";
+        return;
+    }
+
+    QJsonObject jsonObjRoot = jsonDoc.object();
+
+    // 检查 code 字段
+    if (jsonObjRoot["code"].toInt() == 200)
+    {
+        QJsonObject jsonObjData = jsonObjRoot["data"].toObject();
+        QString cabinetId = jsonObjData.value("cabinetId").toString();
+
+        pconfig->devId = cabinetId;
+    }
+
+}

+ 16 - 0
Interactive/RunHttpGet_selectIsMaterialsCabinetByCode.h

@@ -0,0 +1,16 @@
+#ifndef RUNHTTPGET_SELECTISMATERIALSCABINETBYCODE_H
+#define RUNHTTPGET_SELECTISMATERIALSCABINETBYCODE_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_selectIsMaterialsCabinetByCode : public RunAbstract
+{
+public:
+    RunHttpGet_selectIsMaterialsCabinetByCode(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+
+};
+
+#endif // RUNHTTPGET_SELECTISMATERIALSCABINETBYCODE_H

+ 70 - 0
Interactive/RunHttpGet_severity_level.cpp

@@ -0,0 +1,70 @@
+#include "RunHttpGet_severity_level.h"
+
+RunHttpGet_severity_level::RunHttpGet_severity_level(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+
+
+void RunHttpGet_severity_level::run()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    QByteArray outData = InteractiveHttp::http_get_severity_level();
+
+    // 进行数据写操作
+    QWriteLocker locker(&pSingletonData->m_dataCacheLock);
+    // 如果数据发生改变,缓存信息
+    if (pSingletonData->m_jsonCacheSeverityLevelDict != outData)
+    {
+        // 缓存json信息
+        pSingletonData->m_jsonCacheSeverityLevelDict = outData;
+
+
+        // 异常类型字典清理数据缓存
+        pSingletonData->m_dataCacheSeverityLevelDictCode.clear();
+        pSingletonData->m_dataCacheSeverityLevelDictLabel.clear();
+        pSingletonData->m_dataCacheSeverityLevelDictValue.clear();
+
+
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code") && jsonObjRoot.contains("data"))
+                {
+                    if (jsonObjRoot.value("code").toInt() == 200 && jsonObjRoot.value("data").isArray())
+                    {
+                        QJsonArray jsonArrData = jsonObjRoot.value("data").toArray();
+
+                        for (int i = 0; i < jsonArrData.size(); ++i)
+                        {
+                            if (!jsonArrData.at(i).isObject())
+                            {
+                                continue;
+                            }
+                            QJsonObject jsonObjData = jsonArrData.at(i).toObject();
+
+                            QString dictCode = jsonObjData.value("dictCode").toString();
+                            QString dictLabel = jsonObjData.value("dictLabel").toString();
+                            QString dictValue = jsonObjData.value("dictValue").toString();
+
+                            if (pSingletonData->m_dataCacheSeverityLevelDictCode.contains(dictCode))
+                            {
+                                continue;
+                            }
+
+                            pSingletonData->m_dataCacheSeverityLevelDictCode.append(dictCode);
+                            pSingletonData->m_dataCacheSeverityLevelDictLabel.insert(dictCode, dictLabel);
+                            pSingletonData->m_dataCacheSeverityLevelDictValue.insert(dictCode, dictValue);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 15 - 0
Interactive/RunHttpGet_severity_level.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPGET_SEVERITY_LEVEL_H
+#define RUNHTTPGET_SEVERITY_LEVEL_H
+
+#include "RunAbstract.h"
+
+class RunHttpGet_severity_level : public RunAbstract
+{
+public:
+    RunHttpGet_severity_level(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPGET_SEVERITY_LEVEL_H

+ 17 - 0
Interactive/RunHttpPost_deleteSysUserCharacteristicByRecordIds.cpp

@@ -0,0 +1,17 @@
+#include "RunHttpPost_deleteSysUserCharacteristicByRecordIds.h"
+
+RunHttpPost_deleteSysUserCharacteristicByRecordIds::RunHttpPost_deleteSysUserCharacteristicByRecordIds(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+
+
+void RunHttpPost_deleteSysUserCharacteristicByRecordIds::run()
+{
+    QString inData = getRequest().toString();
+    QByteArray outData = InteractiveHttp::http_post_deleteSysUserCharacteristicByRecordIds(inData);
+
+    setRespond(outData);
+}

+ 17 - 0
Interactive/RunHttpPost_deleteSysUserCharacteristicByRecordIds.h

@@ -0,0 +1,17 @@
+#ifndef RUNHTTPPOST_DELETESYSUSERCHARACTERISTICBYRECORDIDS_H
+#define RUNHTTPPOST_DELETESYSUSERCHARACTERISTICBYRECORDIDS_H
+
+#include "RunAbstract.h"
+
+class RunHttpPost_deleteSysUserCharacteristicByRecordIds : public RunAbstract
+{
+public:
+    RunHttpPost_deleteSysUserCharacteristicByRecordIds(InteractiveTask *task, QMutex *mutex);
+
+
+protected:
+    void run();
+
+};
+
+#endif // RUNHTTPPOST_DELETESYSUSERCHARACTERISTICBYRECORDIDS_H

+ 19 - 0
Interactive/RunHttpPost_insertCheckRecord.cpp

@@ -0,0 +1,19 @@
+#include "RunHttpPost_insertCheckRecord.h"
+
+RunHttpPost_insertCheckRecord::RunHttpPost_insertCheckRecord(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunHttpPost_insertCheckRecord::run()
+{
+    QByteArray inData = getRequest().toString().toUtf8();
+    QByteArray outData = InteractiveHttp::http_post_insertCheckRecord(inData);
+
+    if (!outData.isEmpty())
+    {
+        setRespond(outData);
+    }
+}

+ 15 - 0
Interactive/RunHttpPost_insertCheckRecord.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPPOST_INSERTCHECKRECORD_H
+#define RUNHTTPPOST_INSERTCHECKRECORD_H
+
+#include "RunAbstract.h"
+
+class RunHttpPost_insertCheckRecord : public RunAbstract
+{
+public:
+    RunHttpPost_insertCheckRecord(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPPOST_INSERTCHECKRECORD_H

+ 64 - 0
Interactive/RunHttpPost_insertIsException.cpp

@@ -0,0 +1,64 @@
+#include "RunHttpPost_insertIsException.h"
+
+#include "../user/config.h"
+extern config *pconfig;
+
+RunHttpPost_insertIsException::RunHttpPost_insertIsException(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunHttpPost_insertIsException::run()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    QReadLocker locker(&pSingletonData->m_dataCacheLock);
+
+    QString inData = getRequest().toString();
+
+    QJsonParseError error;
+    QJsonDocument jsonDocRead = QJsonDocument::fromJson(inData.toUtf8());
+    QJsonDocument jsonDocWrite;
+
+    if (error.error == QJsonParseError::NoError)
+    {
+        QJsonObject jsonObjRoot = jsonDocRead.object();
+
+        QString exceptionTypeName = jsonObjRoot.value("exceptionTypeName").toString();
+        QString exceptionLevelName = jsonObjRoot.value("exceptionLevelName").toString();
+        QString exceptionDescription = jsonObjRoot.value("exceptionDescription").toString();
+
+        jsonObjRoot.insert("exceptionCategory", "2");
+        jsonObjRoot.insert("raiser", pconfig->userId.toInt());
+
+        for (auto it = pSingletonData->m_dataCacheExceptionTypeDictLabel.begin(); it != pSingletonData->m_dataCacheExceptionTypeDictLabel.end(); ++it)
+        {
+            if (it.value() == exceptionTypeName)
+            {
+                jsonObjRoot.insert("exceptionType", pSingletonData->m_dataCacheExceptionTypeDictValue[it.key()]);
+            }
+        }
+
+        for (auto it = pSingletonData->m_dataCacheSeverityLevelDictLabel.begin(); it != pSingletonData->m_dataCacheSeverityLevelDictLabel.end(); ++it)
+        {
+            if (it.value() == exceptionLevelName)
+            {
+                jsonObjRoot.insert("exceptionLevel", pSingletonData->m_dataCacheSeverityLevelDictValue[it.key()]);
+            }
+        }
+
+        if (!pconfig->devId.isEmpty())
+        {
+            jsonObjRoot.insert("sourceId", pconfig->devId);
+        }
+
+        jsonDocWrite.setObject(jsonObjRoot);
+    }
+
+    QByteArray json = jsonDocWrite.toJson(QJsonDocument::Compact);
+
+    QByteArray outData = InteractiveHttp::http_post_insertIsException(json);
+
+    setRespond(outData);
+}

+ 15 - 0
Interactive/RunHttpPost_insertIsException.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPPOST_INSERTISEXCEPTION_H
+#define RUNHTTPPOST_INSERTISEXCEPTION_H
+
+#include "RunAbstract.h"
+
+class RunHttpPost_insertIsException : public RunAbstract
+{
+public:
+    RunHttpPost_insertIsException(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPPOST_INSERTISEXCEPTION_H

+ 19 - 0
Interactive/RunHttpPost_insertSubmitPlan.cpp

@@ -0,0 +1,19 @@
+#include "RunHttpPost_insertSubmitPlan.h"
+
+RunHttpPost_insertSubmitPlan::RunHttpPost_insertSubmitPlan(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunHttpPost_insertSubmitPlan::run()
+{
+    QByteArray outData = InteractiveHttp::http_post_insertSubmitPlan();
+
+    if (!outData.isEmpty())
+    {
+        setRespond(outData);
+    }
+
+}

+ 15 - 0
Interactive/RunHttpPost_insertSubmitPlan.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPPOST_INSERTSUBMITPLAN_H
+#define RUNHTTPPOST_INSERTSUBMITPLAN_H
+
+#include "RunAbstract.h"
+
+class RunHttpPost_insertSubmitPlan : public RunAbstract
+{
+public:
+    RunHttpPost_insertSubmitPlan(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPPOST_INSERTSUBMITPLAN_H

+ 43 - 0
Interactive/RunHttpPost_insertUserFace.cpp

@@ -0,0 +1,43 @@
+#include "RunHttpPost_insertUserFace.h"
+
+RunHttpPost_insertUserFace::RunHttpPost_insertUserFace(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunHttpPost_insertUserFace::run()
+{
+
+    QByteArray outData = InteractiveHttp::http_post_insertUserFace();
+
+    QByteArray json;
+    if (!outData.isEmpty())
+    {
+        // 解析是否录入成功
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code"))
+                {
+                    if(jsonObjRoot.value("code").toInt() == 200)
+                    {
+                        json = QString("{\"text\": \"录入成功\"}").toUtf8();
+                    }
+                    else
+                    {
+                        json = QString("{\"text\": \"录入失败:%1\"}").arg(jsonObjRoot.value("msg").toString()).toUtf8();
+                    }
+                }
+            }
+        }
+    }
+
+    setRespond(QString(json));
+}
+

+ 15 - 0
Interactive/RunHttpPost_insertUserFace.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPPOST_INSERTUSERFACE_H
+#define RUNHTTPPOST_INSERTUSERFACE_H
+
+#include "RunAbstract.h"
+
+class RunHttpPost_insertUserFace : public RunAbstract
+{
+public:
+    RunHttpPost_insertUserFace(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPPOST_INSERTUSERFACE_H

+ 16 - 0
Interactive/RunHttpPost_insertUserFingerprintDat.cpp

@@ -0,0 +1,16 @@
+#include "RunHttpPost_insertUserFingerprintDat.h"
+
+RunHttpPost_insertUserFingerprintDat::RunHttpPost_insertUserFingerprintDat(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunHttpPost_insertUserFingerprintDat::run()
+{
+    QString group = getRequest().toString();
+    QByteArray outData = InteractiveHttp::http_post_insertUserFingerprintDat(group);
+
+    setRespond(outData);
+}

+ 15 - 0
Interactive/RunHttpPost_insertUserFingerprintDat.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPPOST_INSERTUSERFINGERPRINTDAT_H
+#define RUNHTTPPOST_INSERTUSERFINGERPRINTDAT_H
+
+#include "RunAbstract.h"
+
+class RunHttpPost_insertUserFingerprintDat : public RunAbstract
+{
+public:
+    RunHttpPost_insertUserFingerprintDat(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPPOST_INSERTUSERFINGERPRINTDAT_H

+ 73 - 0
Interactive/RunHttpPost_loginByFace.cpp

@@ -0,0 +1,73 @@
+#include "RunHttpPost_loginByFace.h"
+
+#include "../user/config.h"
+extern config *pconfig;
+
+RunHttpPost_loginByFace::RunHttpPost_loginByFace(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+void RunHttpPost_loginByFace::run()
+{
+    QByteArray json;
+    QByteArray outData = InteractiveHttp::http_post_loginByFace();
+
+    if (!outData.isEmpty())
+    {
+        // 解析是否登录成功
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code"))
+                {
+                    if(jsonObjRoot.value("code").toInt() == 200)
+                    {
+                        if(jsonObjRoot.contains("token"))
+                        {
+                            QJsonValue value = jsonObjRoot.value("token");
+                            if(value.type() == QJsonValue::String)
+                            {
+                                InteractiveHttp::strToken = value.toString();
+
+                                QString username = "未知用户";
+                                if(jsonObjRoot.contains("nickName"))
+                                {
+                                    QJsonValue name = jsonObjRoot.value("nickName");
+                                    if(name.type() == QJsonValue::String)
+                                    {
+                                        username = name.toString();
+                                    }
+                                }
+                                pconfig->username = username;
+
+                                // 这里为了保证原有逻辑,需调用pro类
+                                json = QString("{\"stat\":0,\"str\":\"登陆成功\",\"name\":\"%1\",\"outh\": 0}").arg(username).toUtf8();
+                            }
+                            else
+                            {
+                                json = QString("{\"stat\":-3,\"str\":\"登陆失败\",\"name\":\"\",\"outh\": 0}").toUtf8();
+                            }
+                        }
+                    }
+                    else
+                    {
+                        // json = QString("{\"stat\":-3,\"str\":\"登陆失败\",\"name\":\"\",\"outh\": 0}").toUtf8();
+                        json = QString("{\"stat\":-2,\"str\":\"%1\",\"name\":\"\",\"outh\": 0}").arg(jsonObjRoot.value("msg").toString()).toUtf8();
+                    }
+                }
+            }
+        }
+        else
+        {
+            json = QString("{\"stat\":-3,\"str\":\"服务器返回数据解析错误\",\"name\":\"\",\"outh\": 0}").toUtf8();
+        }
+    }
+
+    setRespond(QString(json));
+}

+ 15 - 0
Interactive/RunHttpPost_loginByFace.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPPOST_LOGINBYFACE_H
+#define RUNHTTPPOST_LOGINBYFACE_H
+
+#include "RunAbstract.h"
+
+class RunHttpPost_loginByFace : public RunAbstract
+{
+public:
+    RunHttpPost_loginByFace(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPPOST_LOGINBYFACE_H

+ 72 - 0
Interactive/RunHttpPost_loginByFingerprintDat.cpp

@@ -0,0 +1,72 @@
+#include "RunHttpPost_loginByFingerprintDat.h"
+
+#include "../user/config.h"
+extern config *pconfig;
+
+RunHttpPost_loginByFingerprintDat::RunHttpPost_loginByFingerprintDat(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+void RunHttpPost_loginByFingerprintDat::run()
+{
+    QByteArray json;
+    QByteArray outData = InteractiveHttp::http_post_loginByFingerprintDat();
+
+    if (!outData.isEmpty())
+    {
+        // 解析是否登录成功
+        QJsonParseError error;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &error);
+        if (error.error == QJsonParseError::NoError)
+        {
+            if(!(jsonDoc.isNull() || jsonDoc.isEmpty()))
+            {
+                QJsonObject jsonObjRoot = jsonDoc.object();
+                if(jsonObjRoot.contains("code"))
+                {
+                    if(jsonObjRoot.value("code").toInt() == 200)
+                    {
+                        if(jsonObjRoot.contains("token"))
+                        {
+                            QJsonValue value = jsonObjRoot.value("token");
+                            if(value.type() == QJsonValue::String)
+                            {
+                                InteractiveHttp::strToken = value.toString();
+                                QString username = "未知用户";
+                                if(jsonObjRoot.contains("nickName"))
+                                {
+                                    QJsonValue name = jsonObjRoot.value("nickName");
+                                    if(name.type() == QJsonValue::String)
+                                    {
+                                        username = name.toString();
+                                    }
+                                }
+                                pconfig->username = username;
+
+                                // 这里为了保证原有逻辑,需调用pro类
+                                json = QString("{\"stat\":0,\"str\":\"登陆成功\",\"name\":\"%1\",\"outh\": 0}").arg(username).toUtf8();
+                            }
+                            else
+                            {
+                                json = QString("{\"stat\":-3,\"str\":\"登陆失败\",\"name\":\"\",\"outh\": 0}").toUtf8();
+                            }
+                        }
+                    }
+                    else
+                    {
+                        // json = QString("{\"stat\":-3,\"str\":\"登陆失败\",\"name\":\"\",\"outh\": 0}").toUtf8();
+                        json = QString("{\"stat\":-2,\"str\":\"%1\",\"name\":\"\",\"outh\": 0}").arg(jsonObjRoot.value("msg").toString()).toUtf8();
+                    }
+                }
+            }
+        }
+        else
+        {
+            json = QString("{\"stat\":-3,\"str\":\"服务器返回数据解析错误\",\"name\":\"\",\"outh\": 0}").toUtf8();
+        }
+    }
+
+    setRespond(QString(json));
+}

+ 15 - 0
Interactive/RunHttpPost_loginByFingerprintDat.h

@@ -0,0 +1,15 @@
+#ifndef RUNHTTPPOST_LOGINBYFINGERPRINTDAT_H
+#define RUNHTTPPOST_LOGINBYFINGERPRINTDAT_H
+
+#include "RunAbstract.h"
+
+class RunHttpPost_loginByFingerprintDat : public RunAbstract
+{
+public:
+    RunHttpPost_loginByFingerprintDat(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNHTTPPOST_LOGINBYFINGERPRINTDAT_H

+ 15 - 0
Interactive/RunHttpPost_startCheckPlan.cpp

@@ -0,0 +1,15 @@
+#include "RunHttpPost_startCheckPlan.h"
+
+RunHttpPost_startCheckPlan::RunHttpPost_startCheckPlan(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunHttpPost_startCheckPlan::run()
+{
+    QByteArray outData = InteractiveHttp::http_post_startCheckPlan();
+    qDebug() << outData;
+
+}

+ 14 - 0
Interactive/RunHttpPost_startCheckPlan.h

@@ -0,0 +1,14 @@
+#ifndef RUNHTTPPOST_STARTCHECKPLAN_H
+#define RUNHTTPPOST_STARTCHECKPLAN_H
+
+#include "RunAbstract.h"
+
+class RunHttpPost_startCheckPlan : public RunAbstract
+{
+public:
+    RunHttpPost_startCheckPlan(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+#endif // RUNHTTPPOST_STARTCHECKPLAN_H

+ 42 - 0
Interactive/RunMaterialExceptionRefreshListModel.cpp

@@ -0,0 +1,42 @@
+#include "RunMaterialExceptionRefreshListModel.h"
+#include "InteractiveData.h"
+
+#include "RunHttpGet_getIsMaterialsLoanExceptionPage.h"
+
+RunMaterialExceptionRefreshListModel::RunMaterialExceptionRefreshListModel(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+void RunMaterialExceptionRefreshListModel::run()
+{
+    // 访问http
+    RunHttpGet_getIsMaterialsLoanExceptionPage::http_get_getIsMaterialsLoanExceptionPage();
+
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    // 清理缓存
+    QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialException, "clear", Qt::QueuedConnection);
+
+    QReadLocker locker(&pSingletonData->m_dataCacheLock);
+
+    for (int i = 0; i < pSingletonData->m_dataCacheMaterialLoadRfid.size(); ++i)
+    {
+        QString infoRfid = pSingletonData->m_dataCacheMaterialLoadRfid.at(i);
+
+        QVariantMap info;
+        info["materialsRfid"] = infoRfid;
+        info["materialsName"] = pSingletonData->m_dataCacheMaterialLoanName[infoRfid].isEmpty() ?
+            "未知物资" : pSingletonData->m_dataCacheMaterialLoanName[infoRfid];
+        // info["materialsRfid"] = pSingletonData->m_dataCacheMaterialLoanRfid[infoId];
+        info["materialsTypePicture"] = pSingletonData->m_dataCacheMaterialLoanTypePicture[infoRfid].isEmpty() ?
+                 "qrc:/png/unknown.png" : pSingletonData->m_dataCacheMaterialLoanTypePicture[infoRfid];
+
+        QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialException, "append", Qt::QueuedConnection,
+                                  Q_ARG(QVariantMap, info));
+
+
+    }
+
+}

+ 15 - 0
Interactive/RunMaterialExceptionRefreshListModel.h

@@ -0,0 +1,15 @@
+#ifndef RUNMATERIALEXCEPTIONREFRESHLISTMODEL_H
+#define RUNMATERIALEXCEPTIONREFRESHLISTMODEL_H
+
+#include "RunAbstract.h"
+
+class RunMaterialExceptionRefreshListModel : public RunAbstract
+{
+public:
+    RunMaterialExceptionRefreshListModel(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNMATERIALEXCEPTIONREFRESHLISTMODEL_H

+ 40 - 0
Interactive/RunMaterialExceptionReport.cpp

@@ -0,0 +1,40 @@
+#include "RunMaterialExceptionReport.h"
+#include "InteractiveData.h"
+
+RunMaterialExceptionReport::RunMaterialExceptionReport(InteractiveTask *task, QMutex *mutex)
+    : RunAbstract(task, mutex)
+{
+
+}
+
+void RunMaterialExceptionReport::run()
+{
+    // InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    // // 清理缓存
+    // QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialException, "clear", Qt::QueuedConnection);
+
+    // QReadLocker locker(&pSingletonData->m_dataCacheLock);
+
+    // for (int i = 0; i < pSingletonData->m_dataCacheMaterialInfoId.size(); ++i)
+    // {
+    //     QString infoId = pSingletonData->m_dataCacheMaterialInfoId.at(i);
+    //     if (pSingletonData->m_dataCacheMaterialInfoStat[infoId] == "3")
+    //     {
+    //         QVariantMap info;
+    //         info["materialsId"] = infoId;
+    //         info["materialsName"] = pSingletonData->m_dataCacheExMaterialInfoName[infoId];
+    //         info["materialsRfid"] = pSingletonData->m_dataCacheExMaterialInfoRfid[infoId];
+    //         info["expirationDate"] = pSingletonData->m_dataCacheExMaterialInfoDate[infoId];
+    //         info["status"] = pSingletonData->m_dataCacheExMaterialInfoStat[infoId];
+
+    //         info["materialsTypePicture"] = pSingletonData->m_dataCacheMaterialTypePicture
+    //                                            [pSingletonData->m_dataCacheExMaterialInfoTypeId[infoId]];
+
+    //         QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialException, "append", Qt::QueuedConnection,
+    //                                   Q_ARG(QVariantMap, info));
+
+    //     }
+    // }
+
+}

+ 15 - 0
Interactive/RunMaterialExceptionReport.h

@@ -0,0 +1,15 @@
+#ifndef RUNMATERIALEXCEPTIONREPORT_H
+#define RUNMATERIALEXCEPTIONREPORT_H
+
+#include "RunAbstract.h"
+
+class RunMaterialExceptionReport : public RunAbstract
+{
+public:
+    RunMaterialExceptionReport(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNMATERIALEXCEPTIONREPORT_H

+ 17 - 0
Interactive/RunMaterialInfoListRefresh.cpp

@@ -0,0 +1,17 @@
+#include "RunMaterialInfoListRefresh.h"
+#include "RunDataCacheRefresh.h"
+
+RunMaterialInfoListRefresh::RunMaterialInfoListRefresh(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunMaterialInfoListRefresh::run()
+{
+    qDebug() << "调用获取物资类型接口(2)";
+     RunDataCacheRefresh::httpGetMaterialType();
+    qDebug() << "调用获取异常物资接口(3)";
+    RunDataCacheRefresh::httpGetExMaterialInfo();
+}

+ 21 - 0
Interactive/RunMaterialInfoListRefresh.h

@@ -0,0 +1,21 @@
+#ifndef RUNMATERIALINFOLISTREFRESH_H
+#define RUNMATERIALINFOLISTREFRESH_H
+
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+#include <QHttpMultiPart>
+#include <QHttpPart>
+
+#include "RunAbstract.h"
+
+class RunMaterialInfoListRefresh : public RunAbstract
+{
+public:
+    RunMaterialInfoListRefresh(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNMATERIALINFOLISTREFRESH_H

+ 116 - 0
Interactive/RunMaterialManualReplaceRefreshListModel.cpp

@@ -0,0 +1,116 @@
+#include "RunMaterialManualReplaceRefreshListModel.h"
+
+#include "InteractiveData.h"
+
+RunMaterialManualReplaceRefreshListModel::RunMaterialManualReplaceRefreshListModel(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+
+void RunMaterialManualReplaceRefreshListModel::run()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+
+    // 清理缓存
+    QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialManualReplace, "clear", Qt::QueuedConnection);
+
+    QReadLocker locker(&pSingletonData->m_dataCacheLock);
+
+    QStringList listParent;
+    for (int i = 0; i < pSingletonData->m_dataCacheMaterialTypeId.size(); ++i)
+    {
+        QString typeId = pSingletonData->m_dataCacheMaterialTypeId.at(i);
+        if (pSingletonData->m_dataCacheMaterialTypeAncestors[typeId].size() > 1)
+        {
+            if (!listParent.contains(pSingletonData->m_dataCacheMaterialTypeAncestors[typeId].last()))
+            {
+                listParent.append(pSingletonData->m_dataCacheMaterialTypeAncestors[typeId].last());
+            }
+        }
+    }
+
+    QVariantList types;
+    for (int i = 0; i < pSingletonData->m_dataCacheMaterialTypeId.size(); ++i)
+    {
+        QString typeId = pSingletonData->m_dataCacheMaterialTypeId.at(i);
+
+        QVariantMap type;
+
+        type["display"] = pSingletonData->m_dataCacheMaterialTypeName[typeId];
+        type["materialsTypeId"] = typeId;
+        type["materialsTypeName"] =  pSingletonData->m_dataCacheMaterialTypeName[typeId];
+        type["materialsTypePicture"] = pSingletonData->m_dataCacheMaterialTypePicture[typeId];
+
+        QStringList propertyIds = pSingletonData->m_dataCacheMaterialTypePropertyIds[typeId];
+
+        QVariantList props;
+        for (int j = 0; j < propertyIds.size(); ++j)
+        {
+            QString propertyId = propertyIds.at(j);
+            for (int k = 0; k < pSingletonData->m_dataCacheMaterialPropId.size(); ++k)
+            {
+                QString propId = pSingletonData->m_dataCacheMaterialPropId.at(k);
+                if (propertyId ==  pSingletonData->m_dataCacheMaterialPropPropertyId[propId])
+                {
+                    QVariantMap prop;
+
+                    prop["display"] = pSingletonData->m_dataCacheMaterialPropName[propId];
+                    prop["propertiesValue"] = pSingletonData->m_dataCacheMaterialPropName[propId];
+                    prop["propertiesValueId"] = propId;
+
+                    prop["propertiesProperty"] = pSingletonData->m_dataCacheMaterialPropPropertyName[propId];
+                    prop["propertiesPropertyId"] = propertyId;
+
+                    props.append(prop);
+                }
+            }
+        }
+        type["props"] = props;
+
+        if (!listParent.contains(typeId))
+        {
+            types.append(type);
+        }
+    }
+
+
+    for (int i = 0; i < pSingletonData->m_dataCacheExMaterialInfoId.size(); ++i)
+    {
+        QString infoId = pSingletonData->m_dataCacheExMaterialInfoId.at(i);
+        if(pSingletonData->m_dataCacheExMaterialInfoStat[infoId] != "0")
+        {
+            QVariantMap info;
+
+            QString typeId = pSingletonData->m_dataCacheExMaterialInfoTypeId[infoId];
+            QString propId = pSingletonData->m_dataCacheExMaterialInfoPropId[infoId];
+
+            info["materialsId"] = infoId;
+            info["oldMaterialsId"] = infoId;
+
+            info["materialsName"] = pSingletonData->m_dataCacheExMaterialInfoName[infoId];
+            info["materialsRfid"] = pSingletonData->m_dataCacheExMaterialInfoRfid[infoId];
+            info["expirationDate"] = pSingletonData->m_dataCacheExMaterialInfoDate[infoId];
+            info["propertiesValue"] = pSingletonData->m_dataCacheMaterialPropName[propId];
+            info["materialsTypeName"] = pSingletonData->m_dataCacheMaterialTypeName[typeId];
+            info["materialsTypePicture"] = pSingletonData->m_dataCacheMaterialTypePicture[typeId];
+
+            info["oldMaterialsName"] = pSingletonData->m_dataCacheExMaterialInfoName[infoId];
+            info["oldMaterialsRfid"] = pSingletonData->m_dataCacheExMaterialInfoRfid[infoId];
+            info["oldExpirationDate"] = pSingletonData->m_dataCacheExMaterialInfoDate[infoId];
+            info["oldPropertiesValue"] = pSingletonData->m_dataCacheMaterialPropName[propId];
+            info["oldMaterialsTypeName"] = pSingletonData->m_dataCacheMaterialTypeName[typeId];
+            info["oldMaterialsTypePicture"] = pSingletonData->m_dataCacheMaterialTypePicture[typeId];
+
+            info["status"] = pSingletonData->m_dataCacheExMaterialInfoStat[infoId];
+            info["click"] = 0;      // 0.未点击    1.维修    2.更换
+            info["types"] = types;
+
+            QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialManualReplace, "append", Qt::QueuedConnection,
+                                      Q_ARG(QVariantMap, info));
+        }
+    }
+
+}

+ 15 - 0
Interactive/RunMaterialManualReplaceRefreshListModel.h

@@ -0,0 +1,15 @@
+#ifndef RUNMATERIALMANUALREPLACEREFRESHLISTMODEL_H
+#define RUNMATERIALMANUALREPLACEREFRESHLISTMODEL_H
+
+#include "RunAbstract.h"
+
+class RunMaterialManualReplaceRefreshListModel : public RunAbstract
+{
+public:
+    RunMaterialManualReplaceRefreshListModel(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNMATERIALMANUALREPLACEREFRESHLISTMODEL_H

+ 176 - 0
Interactive/RunMaterialManualReplaceSubmit.cpp

@@ -0,0 +1,176 @@
+#include "RunMaterialManualReplaceSubmit.h"
+
+#include "InteractiveData.h"
+#include "InteractiveConf.h"
+
+#include "../user/httpclient.h"
+#include "../user/config.h"
+extern config *pconfig;
+
+RunMaterialManualReplaceSubmit::RunMaterialManualReplaceSubmit(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+void RunMaterialManualReplaceSubmit::run()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    QStringList currentRegular; // 正常的
+    QStringList currentUnusual; // 异常的
+    QStringList currentCabinet; // 柜中的
+
+    // 获取正常物资
+    for(auto it = pconfig->materialLoanStateList.cbegin(); it != pconfig->materialLoanStateList.cend(); ++it)
+    {
+        if(it.value() == SERVER_MATERIAL_LOANSTATE_IN)
+        {
+            currentRegular.append(it.key());
+        }
+    }
+
+    // 获取异常物资
+    currentUnusual = InteractiveConf::confReadElseMaterials();
+    currentCabinet = currentRegular + currentUnusual;
+
+
+    QJsonObject jsonObjRoot;
+    QJsonArray jsonArrList;
+    for (int i = 0; i < pSingletonData->m_modelMaterialManualReplace.count(); ++i)
+    {
+        QVariantMap info = pSingletonData->m_modelMaterialManualReplace.get(i);
+
+        QJsonObject jsonObjData;
+
+        int click = info.value("click").toInt();
+
+        // 维修
+        if (click == 1)
+        {
+            jsonObjData.insert("measure", "维修");
+        }
+        // 更换
+        else if(click == 2)
+        {
+            jsonObjData.insert("measure", "更换");
+        }
+        else
+        {
+            continue;
+        }
+
+        QString newMaterialsRfid = info.value("materialsRfid").toString();
+        QString oldMaterialsRfid = info.value("oldMaterialsRfid").toString();
+
+        if (oldMaterialsRfid == newMaterialsRfid)
+        {
+            if (!currentCabinet.contains(oldMaterialsRfid))
+            {
+                setRespond(QString("{\"code\":-1,\"msg\":\"属于本柜的物资%1不在柜中,请放入\"}").arg(oldMaterialsRfid));
+                return;
+            }
+        }
+        else
+        {
+            if (currentCabinet.contains(oldMaterialsRfid))
+            {
+                setRespond(QString("{\"code\":-1,\"msg\":\"不属于本柜的物资%1在柜中,请取出\"}").arg(oldMaterialsRfid));
+                return;
+            }
+            if (!currentCabinet.contains(newMaterialsRfid))
+            {
+                setRespond(QString("{\"code\":-1,\"msg\":\"属于本柜的物资%1不在柜中,请放入\"}").arg(newMaterialsRfid));
+                return;
+            }
+        }
+
+        if (oldMaterialsRfid != newMaterialsRfid)
+        {
+            currentUnusual.removeAll(newMaterialsRfid);
+        }
+
+        jsonObjData.insert("expirationDate", info.value("expirationDate").toString());
+        jsonObjData.insert("materialsName", info.value("materialsName").toString());
+        jsonObjData.insert("materialsRfid", info.value("materialsRfid").toString());
+        jsonObjData.insert("oldMaterialsId", info.value("materialsId").toString());
+
+
+        QString selectedTypeName = info.value("materialsTypeName").toString();
+        QString selectedPropName = info.value("propertiesValue").toString();
+
+
+        QVariantList types = info.value("types").toList();
+        for (int i = 0; i < types.size(); ++i)
+        {
+            QVariantMap type = types.at(i).toMap();
+            QString typeName = type.value("display").toString();
+            if (typeName == selectedTypeName)
+            {
+                jsonObjData.insert("materialsTypeId", type.value("materialsTypeId").toString());
+
+                QVariantList props = type.value("props").toList();
+                for (int j = 0; j < props.size(); ++j)
+                {
+                    QVariantMap prop = props.at(j).toMap();
+                    QString propName = prop.value("display").toString();
+
+                    if (propName == selectedPropName)
+                    {
+                        jsonObjData.insert("propertiesProperty", prop.value("propertiesProperty").toString());
+                        jsonObjData.insert("propertiesPropertyId", prop.value("propertiesPropertyId").toString());
+                        jsonObjData.insert("propertiesValue", prop.value("propertiesValue").toString());
+                        jsonObjData.insert("propertiesValueId", prop.value("propertiesValueId").toString());
+                    }
+                }
+            }
+        }
+
+        jsonArrList.append(jsonObjData);
+    }
+
+    jsonObjRoot.insert("list", jsonArrList);
+
+    QJsonDocument jsonDoc(jsonObjRoot);
+    QByteArray jsonData = jsonDoc.toJson(QJsonDocument::Compact);
+
+    // 访问http服务
+    QString strUrl = "http://" + pconfig->httpHost + pconfig->postMaterialReplace_url;
+    QByteArray inData = jsonData;
+    QByteArray outData;
+
+    httpClient::postRequest(strUrl, pSingletonData->m_token, inData, outData);
+
+    setRespond(outData);
+
+    // 解析 JSON 数据
+    if (!outData.isEmpty())
+    {
+        QJsonParseError parseError;
+        QJsonDocument jsonDoc = QJsonDocument::fromJson(outData, &parseError);
+
+        if (parseError.error != QJsonParseError::NoError)
+        {
+            qWarning() << "JSON 解析错误:" << parseError.errorString();
+            return;
+        }
+
+        if (!jsonDoc.isObject())
+        {
+            qWarning() << "JSON 数据不是对象";
+            return;
+        }
+
+        QJsonObject jsonObjRoot = jsonDoc.object();
+
+        // 检查 code 字段
+        if (jsonObjRoot["code"].toInt() == 200) {
+            InteractiveConf::confSaveElseMaterials(currentUnusual);
+        } else {
+            qWarning() << "返回码不为 200,实际为:" << jsonObjRoot["code"].toInt();
+        }
+    }
+
+
+    qDebug() << outData;
+}

+ 15 - 0
Interactive/RunMaterialManualReplaceSubmit.h

@@ -0,0 +1,15 @@
+#ifndef RUNMATERIALMANUALREPLACESUBMIT_H
+#define RUNMATERIALMANUALREPLACESUBMIT_H
+
+#include "RunAbstract.h"
+
+class RunMaterialManualReplaceSubmit : public RunAbstract
+{
+public:
+    RunMaterialManualReplaceSubmit(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNMATERIALMANUALREPLACESUBMIT_H

+ 82 - 0
Interactive/RunMaterialReplaceRefreshListModel.cpp

@@ -0,0 +1,82 @@
+#include "RunMaterialReplaceRefreshListModel.h"
+
+#include "InteractiveData.h"
+
+RunMaterialReplaceRefreshListModel::RunMaterialReplaceRefreshListModel(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+void RunMaterialReplaceRefreshListModel::run()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+
+    qDebug() << "开始将缓存数据写入model(5)";
+
+    // 清理缓存
+    QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialType, "clear", Qt::QueuedConnection);
+    QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialInfo, "clear", Qt::QueuedConnection);
+
+    // 获取传入参数
+    QString strRequestTypeId = getRequest().toString();
+
+    QReadLocker locker(&pSingletonData->m_dataCacheLock);
+
+    int numberAll = 0;
+
+    for (int i = 0; i < pSingletonData->m_dataCacheExMaterialInfoId.size(); ++i)
+    {
+        QString infoId = pSingletonData->m_dataCacheExMaterialInfoId.at(i);
+        QString typeId = pSingletonData->m_dataCacheExMaterialInfoTypeId[infoId];
+        if (strRequestTypeId == MATERIALS_TYPE_ALL || strRequestTypeId == typeId)
+        {
+            QVariantMap info;
+            info["materialsId"] = infoId;
+            info["materialsName"] = pSingletonData->m_dataCacheExMaterialInfoName[infoId];
+            info["materialsRfid"] = pSingletonData->m_dataCacheExMaterialInfoRfid[infoId];
+            info["expirationDate"] = pSingletonData->m_dataCacheExMaterialInfoDate[infoId];
+            info["status"] = pSingletonData->m_dataCacheExMaterialInfoStat[infoId];
+
+            info["materialsTypePicture"] = pSingletonData->m_dataCacheMaterialTypePicture
+                                               [pSingletonData->m_dataCacheExMaterialInfoTypeId[infoId]];
+
+            QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialInfo, "append", Qt::QueuedConnection,
+                                      Q_ARG(QVariantMap, info));
+
+        }
+        numberAll++;
+    }
+
+    {
+        QVariantMap type;
+        type["materialsTypeId"] = 0;
+        type["materialsTypeName"] = "全部";
+        type["materialsTypeIcon"] = "qrc:/png/allsel.png";
+        type["materialsTypeError"] = numberAll;
+        type["materialsTypePicture"] = "qrc:/png/allsel.png";
+        type["materialsTypeSelected"] = ("0" == strRequestTypeId);
+
+        QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialType, "append", Qt::QueuedConnection,
+                                  Q_ARG(QVariantMap, type));
+    }
+
+    for (int i = 0; i < pSingletonData->m_dataCacheExMaterialTypeId.size(); ++i)
+    {
+        QString typeId = pSingletonData->m_dataCacheExMaterialTypeId.at(i);
+
+        QVariantMap type;
+        type["materialsTypeId"] = typeId;
+        type["materialsTypeName"] = pSingletonData->m_dataCacheMaterialTypeName[typeId];
+        type["materialsTypeIcon"] = pSingletonData->m_dataCacheMaterialTypeIcon[typeId];
+        type["materialsTypeError"] = pSingletonData->m_dataCacheExMaterialTypeExNumber[typeId];
+        type["materialsTypePicture"] = pSingletonData->m_dataCacheMaterialTypePicture[typeId];
+        type["materialsTypeSelected"] = (typeId == strRequestTypeId);
+
+        QMetaObject::invokeMethod(&pSingletonData->m_modelMaterialType, "append", Qt::QueuedConnection,
+                                  Q_ARG(QVariantMap, type));
+    }
+
+}
+
+

+ 15 - 0
Interactive/RunMaterialReplaceRefreshListModel.h

@@ -0,0 +1,15 @@
+#ifndef RUNMATERIALREPLACEREFRESHLISTMODEL_H
+#define RUNMATERIALREPLACEREFRESHLISTMODEL_H
+
+#include "RunAbstract.h"
+
+class RunMaterialReplaceRefreshListModel : public RunAbstract
+{
+public:
+    RunMaterialReplaceRefreshListModel(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNMATERIALREPLACEREFRESHLISTMODEL_H

+ 38 - 0
Interactive/RunViewRefresh_AbnormalReport.cpp

@@ -0,0 +1,38 @@
+#include "RunViewRefresh_AbnormalReport.h"
+
+RunViewRefresh_AbnormalReport::RunViewRefresh_AbnormalReport(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+void RunViewRefresh_AbnormalReport::run()
+{
+    InteractiveData *pSingletonData = SINGLETON_CREATE(InteractiveData)();
+    QReadLocker locker(&pSingletonData->m_dataCacheLock);
+
+    QJsonDocument jsonDoc;
+    QJsonObject jsonObjRoot;
+
+    QJsonArray jsonArrExceptionTypeDict;
+    QJsonArray jsonArrSeverityLevelDict;
+
+    for (int i = 0; i < pSingletonData->m_dataCacheExceptionTypeDictCode.size(); ++i)
+    {
+        QString code = pSingletonData->m_dataCacheExceptionTypeDictCode.at(i);
+        jsonArrExceptionTypeDict.append( pSingletonData->m_dataCacheExceptionTypeDictLabel.value(code));
+    }
+
+    for (int i = 0; i < pSingletonData->m_dataCacheSeverityLevelDictCode.size(); ++i)
+    {
+        QString code = pSingletonData->m_dataCacheSeverityLevelDictCode.at(i);
+        jsonArrSeverityLevelDict.append( pSingletonData->m_dataCacheSeverityLevelDictLabel.value(code));
+    }
+
+    jsonObjRoot.insert("ExceptionTypeDict", jsonArrExceptionTypeDict);
+    jsonObjRoot.insert("SeverityLevelDict", jsonArrSeverityLevelDict);
+
+    jsonDoc.setObject(jsonObjRoot);
+    QByteArray json = jsonDoc.toJson(QJsonDocument::Compact);
+    setRespond(json);
+}

+ 15 - 0
Interactive/RunViewRefresh_AbnormalReport.h

@@ -0,0 +1,15 @@
+#ifndef RUNVIEWREFRESH_ABNORMALREPORT_H
+#define RUNVIEWREFRESH_ABNORMALREPORT_H
+
+#include "RunAbstract.h"
+
+class RunViewRefresh_AbnormalReport : public RunAbstract
+{
+public:
+    RunViewRefresh_AbnormalReport(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+
+#endif // RUNVIEWREFRESH_ABNORMALREPORT_H

+ 17 - 0
Interactive/RunViewWait.cpp

@@ -0,0 +1,17 @@
+#include "RunViewWait.h"
+
+RunViewWait::RunViewWait(InteractiveTask *task, QMutex *mutex)
+    :RunAbstract(task, mutex)
+{
+
+}
+
+void RunViewWait::run()
+{
+    int timeout = getRequest().toInt();
+    if (timeout > 0)
+    {
+        QThread::msleep(timeout);
+    }
+
+}

+ 15 - 0
Interactive/RunViewWait.h

@@ -0,0 +1,15 @@
+#ifndef RUNVIEWWAIT_H
+#define RUNVIEWWAIT_H
+
+#include "RunAbstract.h"
+#include <QThread>
+
+class RunViewWait : public RunAbstract
+{
+public:
+    RunViewWait(InteractiveTask *task, QMutex *mutex);
+
+protected:
+    void run();
+};
+#endif // RUNVIEWWAIT_H

+ 65 - 0
Interactive/template_singleton.h

@@ -0,0 +1,65 @@
+#ifndef TEMPLATE_SINGLETON_H
+#define TEMPLATE_SINGLETON_H
+
+#include <mutex>
+
+// 定义单例(声明友元)
+#define SINGLETON_DEFINE(Class, ...) \
+    friend TemplateSingleton<Class, ##__VA_ARGS__>;
+
+// 创建单例(不存在创建,存在获取本类唯一单例)
+#define SINGLETON_CREATE(Class, ...) \
+    TemplateSingleton<Class, ##__VA_ARGS__>::CreateInstance
+
+// 销毁单例
+#define SINGLETON_DELETE(Class, ...) \
+    TemplateSingleton<Class, ##__VA_ARGS__>::DeleteInstance
+
+
+template <typename Class, typename ...Args>
+class TemplateSingleton
+{
+public:
+    static Class* CreateInstance(Args ...args);
+    static void DeleteInstance();
+
+private:
+    static Class* s_pObject;
+    static std::mutex s_mutex;
+};
+
+template <typename Class, typename ...Args>
+Class* TemplateSingleton<Class, Args...>::CreateInstance(Args ...args)
+{
+    if (s_pObject == nullptr)
+    {
+        std::lock_guard<std::mutex> unique(s_mutex);
+        if (s_pObject == nullptr)
+        {
+            s_pObject = new Class(args...);
+        }
+    }
+    return s_pObject;
+}
+
+template <typename Class, typename ...Args>
+void TemplateSingleton<Class, Args...>::DeleteInstance()
+{
+    if (s_pObject != nullptr)
+    {
+        std::lock_guard<std::mutex> unique(s_mutex);
+        if (s_pObject != nullptr)
+        {
+            delete s_pObject;
+            s_pObject = nullptr;
+        }
+    }
+}
+
+template <typename Class, typename ...Args>
+Class* TemplateSingleton<Class, Args...>::s_pObject = nullptr;
+
+template <typename Class, typename ...Args>
+std::mutex TemplateSingleton<Class, Args...>::s_mutex;
+
+#endif //TEMPLATE_SINGLETON_H

+ 35 - 0
content/App.qml

@@ -0,0 +1,35 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+import QtQuick 6.2
+import Cabinet
+import QtQuick.VirtualKeyboard 6.2
+
+Window {
+    width: mainScreen.width
+    height: mainScreen.height
+
+    visible: true
+    title: "Cabinet"
+
+    Screen01 {
+        id: mainScreen
+    }
+
+    InputPanel {
+        id: inputPanel
+        property bool showKeyboard :  active
+        y: showKeyboard ? parent.height - height : parent.height
+        Behavior on y {
+            NumberAnimation {
+                duration: 200
+                easing.type: Easing.InOutQuad
+            }
+        }
+        anchors.leftMargin: Constants.width/10
+        anchors.rightMargin: Constants.width/10
+        anchors.left: parent.left
+        anchors.right: parent.right
+    }
+}
+

+ 14 - 0
content/CMakeLists.txt

@@ -0,0 +1,14 @@
+### This file is automatically generated by Qt Design Studio.
+### Do not change
+
+qt_add_library(content STATIC)
+qt6_add_qml_module(content
+    URI "content"
+    VERSION 1.0
+    RESOURCE_PREFIX "/qt/qml"
+    QML_FILES
+        App.qml
+        Screen01.ui.qml
+    RESOURCES
+        fonts/fonts.txt
+)

+ 237 - 0
content/FacialRecognition.qml

@@ -0,0 +1,237 @@
+import QtQuick
+import QtQuick.Controls
+
+import com.InteractiveTask 1.0
+
+Item {
+    id: facialrecognition
+    x: 290
+    y: 130
+    width: 1600
+    height: 920
+
+    Connections {
+        target: facialrecognition
+        onVisibleChanged: {
+            if (facialrecognition.visible === true)
+            {
+                interactiveFace.setCameraImageCallBack(callback_cameraImageGather, null, callback_cameraImageRemain);
+                interactiveFace.cameraImagePlay();
+
+                facialrecognition_text_result.text = "";
+            }
+            else
+            {
+                interactiveFace.cameraImageStop();
+            }
+        }
+    }
+
+
+    // 重新拍摄
+    Button {
+        id: facialrecognition_btn_retake
+        x: 928
+        y: 835
+        width: 192
+        height: 75
+        visible: false
+
+        background: Rectangle {
+            color: "#ff9900"
+            radius: 10
+        }
+        text: qsTr("重新拍摄")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: facialrecognition_btn_retake
+            onClicked: {
+                facialrecognition_btn_affirm.visible = false;
+                facialrecognition_btn_retake.visible = false;
+                interactiveFace.cameraImagePlay();
+            }
+        }
+    }
+
+    // 确定
+    Button {
+        id: facialrecognition_btn_affirm
+        x: 1168
+        y: 835
+        width: 192
+        height: 75
+        visible: false
+
+        background: Rectangle {
+            color: "#ff0000" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("确定")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: facialrecognition_btn_affirm
+            onClicked: {
+                var userFace = setView.userFace;
+                if (userFace.length > 0)
+                {
+
+                    var inText = userFace.length > 0 ? "?recordIds=" : "";
+
+                    for (var i = 0; i < userFace.length; ++i)
+                    {
+                        inText += userFace[i];
+                        inText += (i !== userFace.length - 1) ? "," : "";
+                    }
+
+                    interactiveCore.appendTask(
+                                InteractiveTask.TypeHttpPost_deleteSysUserCharacteristicByRecordIds, inText,
+                                (json)=>{
+                                    var jsonObjData = JSON.parse(json);
+                                    if (jsonObjData.code === 200) {
+                                        var taskType = InteractiveTask.TypeHttpPost_insertUserFace;
+                                        interactiveCore.appendTask(taskType, "", call_insertUserFace_reply);
+                                        facialrecognition_btn_affirm.visible = false;
+                                        facialrecognition_btn_retake.visible = false;
+                                    }
+                                    else
+                                    {
+                                        infoPromptBox.title("人脸特征删除失败");
+                                        infoPromptBox.message(jsonObjData.msg);
+                                        infoPromptBox.button_clear();
+                                        infoPromptBox.button_push("#055eb3", "确定", null, null);
+                                        infoPromptBox.show();
+                                    }
+                                });
+
+                }
+                else
+                {
+                    var taskType = InteractiveTask.TypeHttpPost_insertUserFace;
+                    interactiveCore.appendTask(taskType, "", call_insertUserFace_reply);
+                    facialrecognition_btn_affirm.visible = false;
+                    facialrecognition_btn_retake.visible = false;
+                }
+
+            }
+        }
+    }
+
+    // 返回按钮
+    Button {
+        id: facialrecognition_btn_return
+        x: 1408
+        y: 835
+        width: 192
+        height: 75
+
+        background: Rectangle {
+            color: "#055eb3" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("返回")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: facialrecognition_btn_return
+            onClicked: {
+                facialrecognition_btn_affirm.visible = false;
+                facialrecognition_btn_retake.visible = false;
+                facialrecognition.visible = false
+                setView.visible = true;
+            }
+        }
+    }
+
+
+    Rectangle {
+        id: facialrecognition_rect
+        width: 1600
+        height: 800
+        color: "#272b7ae9"
+        radius: 20
+        clip: true
+
+        Rectangle {
+            x: 0
+            y: 0
+            width: 1600
+            height: 800
+            color: "#000000"
+            border.color: "#47bfff"
+
+            Image {
+                id: facialrecognition_image_facial
+                anchors.fill: parent
+                visible: true
+
+                layer.smooth: true
+                layer.enabled: true
+                cache: false
+
+                fillMode: Image.PreserveAspectFit
+            }
+        }
+
+    }
+
+
+    Rectangle {
+        id: delaymatrailstocknotice
+        x: 0
+        y: 823
+        width: 300
+        height: 75 // 减去顶部圆角矩形的高度
+        color: "#00ffffff"
+        visible: true
+
+        // Image {
+        //     x: 0
+        //     y: 0
+        //     width: 75
+        //     height: 75
+        //     visible: true
+        //     source: "qrc:/png/takeback.png"
+        //     fillMode: Image.PreserveAspectFit
+        // }
+
+        Text {
+            id: facialrecognition_text_result
+            x: 80
+            y: 0
+            width: 389
+            height: 75
+            visible: true
+            text: ""
+            font.pixelSize: 30
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            color: "#ffffff"
+        }
+    }
+
+    function callback_cameraImageGather(url)
+    {
+        facialrecognition_image_facial.source = url;
+    }
+
+    function callback_cameraImageRemain(url)
+    {
+        facialrecognition_btn_affirm.visible = true;
+        facialrecognition_btn_retake.visible = true;
+
+        interactiveFace.cameraImageStop();
+        facialrecognition_image_facial.source = url;
+    }
+
+    // 插入人脸数据回复
+    function call_insertUserFace_reply(json)
+    {
+        console.log("完成人脸提交");
+        var jsonObjRoot = JSON.parse(json);
+        var text = jsonObjRoot["text"];
+        facialrecognition_text_result.text = text;
+    }
+
+}

+ 128 - 0
content/HangPromptBox.qml

@@ -0,0 +1,128 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+
+Window {
+    id: hangpromptbox
+    visibility: Window.FullScreen;
+    flags: Qt.Dialog | Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
+    modality: Qt.ApplicationModal
+    color: "transparent"
+
+    property var _message : string("");
+    property var _urlIcon : string("");
+    property var _cancelCallback;
+    property var _cancelUserargs;
+
+    Rectangle {
+        anchors.centerIn : parent
+        width: 360
+        height: 360
+        color: "#980e57ea"
+        radius: 16
+
+        Image {
+            anchors.top: parent.top
+            anchors.topMargin: 32
+            anchors.horizontalCenter: parent.horizontalCenter
+
+            width: 200
+            height: 200
+            opacity: 0.5
+            source: _urlIcon
+        }
+
+
+        Text {
+            anchors.bottom: parent.bottom
+            anchors.bottomMargin: 64
+            anchors.horizontalCenter: parent.horizontalCenter
+            text: _message
+            color: "#ffffff"
+            font.pixelSize: 32
+            font.bold: true
+        }
+
+        Text {
+            anchors.bottom: parent.bottom
+            anchors.bottomMargin: 16
+            anchors.horizontalCenter: parent.horizontalCenter
+            text: qsTr("取消")
+            color: "#ffffff"
+            font.pixelSize: 24
+            font.underline: true
+            font.bold: false
+
+            MouseArea {
+                anchors.fill: parent
+                onClicked:
+                {
+                    if (typeof _cancelCallback === "function")
+                    {
+                        // 如果存在用户参数
+                        if (_cancelUserargs !== null)
+                        {
+                            _cancelCallback(_cancelUserargs);
+                        }
+                        else
+                        {
+                            _cancelCallback();
+                        }
+                    }
+                    hide();
+                }
+            }
+        }
+    }
+
+    // 设置取消按钮回调函数
+    function setCancelCallBack(callback, userargs)
+    {
+        _cancelCallback = callback;
+        _cancelUserargs = userargs;
+    }
+
+    // 隐藏并且执行回调
+    function hideExecuteCallback()
+    {
+        if (typeof _cancelCallback === "function")
+        {
+            // 如果存在用户参数
+            if (_cancelUserargs !== null)
+            {
+                _cancelCallback(_cancelUserargs);
+            }
+            else
+            {
+                _cancelCallback();
+            }
+            _cancelCallback = null;
+        }
+        visible = false;
+    }
+
+    // 消息
+    function message(message)
+    {
+        _message = message
+    }
+
+    // 图标
+    function urlIcon(urlIcon)
+    {
+        _urlIcon = urlIcon;
+    }
+
+    // 显示
+    function show()
+    {
+        visible = true;
+    }
+
+    // 隐藏
+    function hide()
+    {
+        _cancelCallback = null;
+        visible = false;
+    }
+
+}

+ 196 - 0
content/InfoPromptBox.qml

@@ -0,0 +1,196 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Window {
+    id: infopromptbox
+    visibility: Window.FullScreen;
+    flags: Qt.Dialog | Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
+    modality: Qt.ApplicationModal
+    color: "transparent"
+
+    property var _buttons : [];
+    property var _message : string("提示信息");
+    property var _title : string("标题信息");
+
+    Rectangle {
+        anchors.centerIn: parent
+        width: 640
+        height: 480
+        color: "#e0e0e0"
+        radius: 16
+
+        Label {
+            id: infopromptbox_label_title
+            anchors.top: parent.top
+            anchors.margins: 0
+            width: parent.width
+            height: 64
+            color: "#ffffff"
+
+            background : Rectangle {
+                color: "#3498db"
+            }
+
+            leftPadding: 20
+            text: _title
+            font.pixelSize: 25
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+        }
+
+        Rectangle {
+            id: infopromptbox_rect_message
+            anchors.top: infopromptbox_label_title.bottom
+            anchors.bottom: infopromptbox_rect_buttons.top
+            anchors.margins: 0
+            width: parent.width
+
+            Label {
+                anchors.fill: parent
+                color: "#000000"
+
+                background : Rectangle {
+                    color: "#ffffff"
+                }
+
+                text: _message
+                wrapMode: Text.Wrap
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+        }
+
+        Rectangle {
+            id: infopromptbox_rect_buttons
+            anchors.bottom: parent.bottom
+            anchors.margins: 0
+            width: parent.width
+            height: 64
+            color: "#bfbfbf"
+
+            Row {
+                anchors.right: parent.right
+                anchors.verticalCenter: parent.verticalCenter
+
+                spacing: 10
+                layoutDirection: Qt.RightToLeft
+                leftPadding: 20
+                rightPadding: 20
+
+
+                Repeater {
+                    id : infopromptbox_repeater_buttons
+                    model: _buttons
+                    delegate: Button {
+
+                        padding: 10
+                        hoverEnabled: false
+
+                        implicitWidth: Math.max(contentItem.implicitWidth + leftPadding + rightPadding, 96);
+                        implicitHeight: Math.max(contentItem.implicitHeight + topPadding + bottomPadding, 48);
+
+                        background: Rectangle {
+                            color: modelData.hasOwnProperty("color") ? modelData["color"] : "#ff0000";
+                            radius: 10
+                        }
+
+                        text: modelData.hasOwnProperty("text") ? modelData["text"] : "关闭";
+                        font.pixelSize: 25
+                        palette.buttonText: "white"
+
+                        onClicked: {
+                            // 本界面退出
+                            infopromptbox.close();
+                            // 判断是否存在回调函数
+                            if (modelData.hasOwnProperty("callback"))
+                            {
+                                // 进行回调函数校验
+                                if (typeof modelData["callback"] === "function")
+                                {
+                                    // 如果存在用户参数
+                                    if (modelData.hasOwnProperty("userargs"))
+                                    {
+                                        modelData.callback(modelData["userargs"]);
+                                    }
+                                    else
+                                    {
+                                        modelData.callback();
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+
+    function title(title)
+    {
+        _title = title;
+    }
+
+    function message(message)
+    {
+        _message = message;
+    }
+
+    function buttons_reset(buttons)
+    {
+        if (!Array.isArray(buttons))
+        {
+            return;
+        }
+
+        for (var i = 0; i < bottons.length; ++i)
+        {
+            _buttons.push(buttons[i]);
+        }
+    }
+
+    function button_clear()
+    {
+        _buttons = [];
+    }
+
+    function button_push(color, text, callback, userargs)
+    {
+        var item = {};
+        if (color !== null)
+        {
+            item["color"] = color;
+        }
+        if (text !== null)
+        {
+            item["text"] = text;
+        }
+        if (callback !== null)
+        {
+            item["callback"] = callback;
+        }
+        if (userargs !== null)
+        {
+            item["userargs"] = userargs;
+        }
+        _buttons.push(item);
+    }
+
+    function show()
+    {
+        if (_buttons.length <= 0)
+        {
+            button_push("#3498db", "确定", null, null);
+        }
+        infopromptbox_repeater_buttons.model = _buttons;
+        visible = true;
+    }
+    function hide()
+    {
+        visible = false;
+    }
+
+}

+ 862 - 0
content/Login.qml

@@ -0,0 +1,862 @@
+/*
+This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only.
+It is supposed to be strictly declarative and only uses a subset of QML. If you edit
+this file manually, you might introduce QML code that is not supported by Qt Design Studio.
+Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files.
+*/
+import QtQuick 6.5
+import QtQuick.Controls 6.5
+import QtQuick.VirtualKeyboard
+import com.lock 1.0  // 导入 C++ 类
+
+// import com.InteractiveCore 1.0
+import com.InteractiveTask 1.0
+
+Item {
+    id: login
+
+    property string cardID : ""
+    property int errorNoticeTimeout: 3
+    property int enterSet: 0
+    property int enterSetTimeout: 5
+
+    signal signal_login(int type, string username, string password)
+    signal signal_fingerWork(bool stat)
+
+    onVisibleChanged:
+    {
+        if (visible)
+        {
+            proThread.getError(get_error_callback);
+            proThread.moveCursorTo(0, 0);
+        }
+
+        if (visible === true)
+        {
+
+
+            interactiveHand.setFingerImageAppearCallBack(
+                        (url)=>{
+                            waitPromptBox.show();
+                            // visible = false;
+                           interactiveHand.fingerImageStop();
+                            interactiveCore.appendTask(
+                                InteractiveTask.TypeHttpPost_loginByFingerprintDat, null, (json)=>{
+                                    waitPromptBox.hide();
+
+                                    var jsonObjRoot = JSON.parse(json);
+
+                                    var stat = jsonObjRoot["stat"];
+                                    var str = jsonObjRoot["str"];
+                                    var name = jsonObjRoot["name"];
+                                    var outh = jsonObjRoot["outh"];
+
+                                    if (stat === 0)
+                                    {
+                                        mainScreen.login_return_param(name, outh);
+                                        loginScreen.login_return_stat(stat, str);
+                                        proThread.slot_feature_login();
+                                    }
+                                    else
+                                    {
+                                        loginScreen.login_return_stat(stat, str);
+                                        interactiveHand.fingerImagePlay();
+                                    }
+                                });
+                        });
+            interactiveHand.fingerImagePlay();
+        }
+        else
+        {
+            interactiveHand.fingerImageStop();
+        }
+    }
+
+
+    function set_cardID(value) {
+        switch(value)
+        {
+        case Qt.Key_0:cardID = cardID + "0";break;
+        case Qt.Key_1:cardID = cardID + "1";break;
+        case Qt.Key_2:cardID = cardID + "2";break;
+        case Qt.Key_3:cardID = cardID + "3";break;
+        case Qt.Key_4:cardID = cardID + "4";break;
+        case Qt.Key_5:cardID = cardID + "5";break;
+        case Qt.Key_6:cardID = cardID + "6";break;
+        case Qt.Key_7:cardID = cardID + "7";break;
+        case Qt.Key_8:cardID = cardID + "8";break;
+        case Qt.Key_9:cardID = cardID + "9";break;
+        case Qt.Key_A:cardID = cardID + "A";break;
+        case Qt.Key_B:cardID = cardID + "B";break;
+        case Qt.Key_C:cardID = cardID + "C";break;
+        case Qt.Key_D:cardID = cardID + "D";break;
+        case Qt.Key_E:cardID = cardID + "E";break;
+        case Qt.Key_F:cardID = cardID + "F";break;
+        case Qt.Key_Return:{
+            console.log("card:" + cardID);
+            card_login()
+            cardID = "";
+        }
+        }
+    }
+
+    focus: true  // 确保 Rectangle 能够接收键盘事件
+
+
+
+
+    // 强制保持焦点
+    onFocusChanged: {
+        if(cardInput.visible === true)
+        {
+            if (!focus) {
+                forceActiveFocus()
+            }
+        }
+    }
+
+    Keys.onPressed: {
+        console.log("key:" + event.key);
+        if(visible === true)
+        {
+            set_cardID(event.key)
+        }
+    }
+
+    function get_error_callback(isError)
+    {
+        login_toolbutton_error.visible = isError;
+    }
+
+
+    Image {
+        id: logoImage
+        x: 73
+        y: 61
+        width: 200
+        height: 50
+        source: "qrc:/png/bozz.png"
+        fillMode: Image.PreserveAspectFit
+        MouseArea {
+            anchors.fill: parent  // 让MouseArea覆盖整个Image区域
+            onClicked: {
+                enterSetTimeout = 5;
+                if(enterSet >= 4)
+                {
+                    enterSet = 0
+                    setView.load_configParam(true)
+                    setView.fingerVisible = false
+                    setView.visible = true
+                }
+                else{
+                    enterSet++
+                }
+            }
+        }
+    }
+
+    Label {
+        id: loginNotice
+        x:0
+        y:900
+        width: 1920
+        color: "#ffffff"
+        text: qsTr("您可以通过刷卡或者指纹直接登录系统")
+        font.pixelSize: 42
+        horizontalAlignment: Text.AlignHCenter
+        verticalAlignment: Text.AlignVCenter
+        font.bold: true
+        visible: true
+    }
+
+    ToolButton
+    {
+        id: login_toolbutton_error
+        x: 1572
+        y: 49
+        width: 300
+        height: 110
+        enabled: false                          // 不可点击
+        display: AbstractButton.TextBesideIcon  // 文字在图标旁边
+        visible: false
+
+        icon.source: "qrc:/png/exception_handle.png"
+        icon.width: 81
+        icon.height: 72
+
+        text: "物资错放"
+        palette.buttonText: "#ff0000"
+        font {
+            pixelSize: 40
+            // bold: true
+        }
+
+        background: Rectangle {
+            color: "#00ffffff"
+            border.color: "#ff0000"
+            border.width: 2 // 边框宽度
+            radius: 20 // 可选,设置圆角
+        }
+    }
+
+    Label {
+        id: label1
+        x: 720
+        y: 181
+        color: "#ddffffff"
+        text: qsTr("物资管理系统")
+        font.pixelSize: 80
+        horizontalAlignment: Text.AlignHCenter
+        verticalAlignment: Text.AlignVCenter
+        font.bold: true
+    }
+
+    Rectangle {
+        id: rectangle1
+        x: 227
+        y: 342
+        width: 1466
+        height: 512
+        color: "#00ffffff"
+
+        // 人脸登录
+        Button {
+            id: face_sel
+            x: 103
+            y: 56
+            width: 300
+            height: 400
+
+            background: Rectangle {
+                id: face_sel_background
+                color: "#982b7ae9"
+                border.color: "#4c2b7ae9"
+                border.width: 2 // 边框宽度
+                radius: 20 // 可选,设置圆角
+            }
+            icon.height: 150
+            icon.width: 120
+            display: AbstractButton.TextUnderIcon
+            icon.source: "qrc:/png/face.png"
+            icon.color: "#00ffffff"
+            text: qsTr("人脸登录")
+            font.pixelSize: 40
+            spacing: 20
+            palette.buttonText: "#7fffffff"  // 设置字体颜色为绿
+            activeFocusOnTab: false
+
+            Connections {
+                target: face_sel
+                onClicked: {
+                    cardInput.visible = false;
+                    passLogin_rec.visible = false;
+                    fingerInput.visible = false;
+                    faceInput.visible = true;
+                }
+            }
+        }
+
+        // 工卡登录
+        Button {
+            id: card_sel
+            x: 423
+            y: 56
+            width: 300
+            height: 400
+
+            background: Rectangle {
+                id: card_sel_background
+                color: "#982b7ae9"
+                border.color: "#4c2b7ae9"
+                border.width: 2 // 边框宽度
+                radius: 20 // 可选,设置圆角
+            }
+            icon.height: 150
+            icon.width: 120
+            display: AbstractButton.TextUnderIcon
+            icon.source: "qrc:/png/card.png"
+            icon.color: "#00ffffff"
+            text: qsTr("工卡登录")
+            font.pixelSize: 40
+            spacing: 20
+            palette.buttonText: "#7fffffff"  // 设置字体颜色为绿
+            activeFocusOnTab: false
+
+            Connections {
+                target: card_sel
+                onClicked: {
+                    passLogin_rec.visible = false;
+                    password_sel.enabled = true;
+                    fingerInput.visible = false;
+                    faceInput.visible = false;
+                    cardInput.visible = true;
+                    cardID = "";
+                }
+            }
+        }
+
+        Button {
+            id: password_sel
+            x: 743
+            y: 56
+            width: 300
+            height: 400
+
+            background: Rectangle {
+                id: password_sel_background
+                color: "#982b7ae9"
+                border.color: "#4c2b7ae9"
+                border.width: 2 // 边框宽度
+                radius: 20 // 可选,设置圆角
+            }
+            icon.height: 150
+            icon.width: 120
+            display: AbstractButton.TextUnderIcon
+            icon.source: "qrc:/png/user.png"
+            icon.color: "#00ffffff"
+            text: qsTr("用户名登录")
+            font.pixelSize: 40
+            spacing: 20
+            palette.buttonText: "#7fffffff"  // 设置字体颜色为绿
+            activeFocusOnTab: false
+
+            Connections {
+                target: password_sel
+                onClicked: {
+                    cardInput.visible = false;
+                    faceInput.visible = false;
+                    fingerInput.visible = false;
+                    passLogin_rec.visible = true
+                    password_sel.enabled = false
+                    usernameText.text = ""
+                    passwordText.text = ""
+                }
+            }
+        }
+
+        Button {
+            id: finger_sel
+            x: 1063
+            y: 56
+            width: 300
+            height: 400
+
+            background: Rectangle {
+                id: finger_sel_background
+                color: "#982b7ae9"
+                border.color: "#4c2b7ae9"
+                border.width: 2 // 边框宽度
+                radius: 20 // 可选,设置圆角
+            }
+            icon.height: 150
+            icon.width: 120
+            display: AbstractButton.TextUnderIcon
+            icon.source: "qrc:/png/finger.png"
+            icon.color: "#00ffffff"
+            text: qsTr("指纹登录")
+            font.pixelSize: 40
+            spacing: 20
+            palette.buttonText: "#7fffffff"  // 设置字体颜色为绿
+            activeFocusOnTab: false
+
+            Connections {
+                target: finger_sel
+                onClicked: {
+                    cardInput.visible = false;
+                    passLogin_rec.visible = false;
+                    password_sel.enabled = true;
+                    fingerInput.visible = true;
+                    faceInput.visible = false;
+                }
+            }
+        }
+    }
+
+    Rectangle {
+        id: passLogin_rec
+        x: 711
+        y: 371
+        width: 497
+        height: 438
+        visible: false
+        color: "#980e57ea"
+        radius: 20
+
+        Column {
+            id: column
+            x: 0
+            y: 0
+            width: 497
+            height: 438
+            visible: true
+            spacing: 30
+            padding: 0
+            topPadding: 46
+
+            Rectangle {
+                x: 72
+                width: 353
+                height: 68
+                color: "#00ffffff"
+                border.color: "#a3ffffff"
+                border.width: 3
+                radius: 10
+
+                TextField {
+                    id: usernameText
+                    anchors.fill: parent
+                    anchors.margins: 2
+                    font.pointSize: 15
+                    focus: false
+                    color: "#a3ffffff"
+                    background: Rectangle {
+                        color: "transparent" // 使TextField背景透明
+                    }
+                    placeholderText: qsTr("请输入用户名")
+                    font.pixelSize: 30
+                    horizontalAlignment: Text.AlignLeft
+                    verticalAlignment: Text.AlignVCenter
+                    wrapMode: Text.NoWrap
+                    selectionColor: "#a300aaff"
+                    placeholderTextColor: "#60ffffff"
+                    bottomPadding: 5
+                    topPadding: 5
+                    rightPadding: 20
+                    leftPadding: 20
+                    renderType: Text.QtRendering
+                    font.styleName: "Regular"
+                }
+            }
+
+            Rectangle {
+                x: 72
+                width: 353
+                height: 68
+                color: "#00ffffff"
+                border.color: "#a3ffffff"
+                border.width: 3
+                radius: 10
+
+                TextField {
+                    id: passwordText
+                    anchors.fill: parent
+                    anchors.margins: 2
+                    font.pointSize: 15
+                    focus: false
+                    color: "#a3ffffff"
+                    background: Rectangle {
+                        color: "transparent" // 使TextField背景透明
+                    }
+                    placeholderText: qsTr("请输入密码")
+                    echoMode: TextInput.Password // 设置echoMode为Password
+                    font.pixelSize: 30
+                    selectionColor: "#a300aaff"
+                    horizontalAlignment: Text.AlignLeft
+                    verticalAlignment: Text.AlignVCenter
+                    wrapMode: Text.NoWrap
+                    placeholderTextColor: "#60ffffff"
+                    bottomPadding: 5
+                    topPadding: 5
+                    rightPadding: 20
+                    leftPadding: 20
+                    renderType: Text.QtRendering
+                    font.styleName: "Regular"
+                }
+            }
+
+            Button {
+                id: button_enter
+                x: 72
+                width: 353
+                height: 68
+                text: qsTr("登录")
+                contentItem: Label {
+                    id: label3
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "#a3ffffff" // 设置字体颜色
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                background: Rectangle {
+                    color: "#a300aaff"
+                    radius: 10 // 设置圆角半径
+                }
+
+                Connections {
+                    target: button_enter
+                    onClicked: {
+                        username_login()
+                    }
+                }
+            }
+
+            Button {
+                id: button_cancel
+                x: 72
+                width: 353
+                height: 68
+                text: qsTr("取消")
+                contentItem: Label {
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "#a3ffffff" // 设置字体颜色
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                background: Rectangle {
+                    color: "#00ffffff"
+                    border.color: "#a3ffffff"
+                    border.width: 3
+                    radius: 10 // 设置圆角半径
+                }
+
+                Connections {
+                    target: button_cancel
+                    onClicked: {
+                        console.log("username return:");
+                        passLogin_rec.visible = false
+                        password_sel.enabled = true
+                        usernameText.text = ""
+                        passwordText.text = ""
+                    }
+                }
+            }
+        }
+    }
+
+    Rectangle {
+        id: faceInput
+        x: (mainScreen.width - width) / 2 - parent.x
+        y: 420
+        width: 350
+        height: 350
+        visible: false
+        color: "#980e57ea"
+        radius: 20
+        onVisibleChanged: {
+
+            if (faceInput.visible === true)
+            {
+
+                interactiveFace.setCallBackFaceStatus(
+                            (status)=>{
+                                if (!status)
+                                {
+                                    loginScreen.login_return_stat(-1, "未检测到人脸");
+                                }
+                            }
+                            );
+                interactiveFace.setCameraImageCallBack(
+                            null, (url)=>{
+                                waitPromptBox.show();
+                                // interactiveFace.cameraImageStop();
+                                faceInput.visible = false;
+                                interactiveCore.appendTask(
+                                    InteractiveTask.TypeHttpPost_loginByFace, null, (json)=>{
+                                        waitPromptBox.hide();
+
+                                        var jsonObjRoot = JSON.parse(json);
+
+                                        var stat = jsonObjRoot["stat"];
+                                        var str = jsonObjRoot["str"];
+                                        var name = jsonObjRoot["name"];
+                                        var outh = jsonObjRoot["outh"];
+
+
+                                        if (stat === 0)
+                                        {
+                                            mainScreen.login_return_param(name, outh);
+                                            loginScreen.login_return_stat(stat, str);
+
+
+                                            proThread.slot_feature_login();
+                                        }
+                                        else
+                                        {
+                                            loginScreen.login_return_stat(stat, str);
+                                            // interactiveFace.cameraImagePlay();
+                                        }
+                                    });
+                            }, null);
+                interactiveFace.cameraImagePlay();
+            }
+            else
+            {
+                interactiveFace.setCallBackFaceStatus(null);
+                interactiveFace.cameraImageStop();
+                proThread.moveCursorTo(0, 0);
+            }
+        }
+
+        Column {
+            x: 0
+            y: 0
+            width: 350
+            height: 350
+            visible: true
+            spacing: 30
+            padding: 0
+            topPadding: 46
+
+            Image {
+                width: 200
+                height: 200
+                opacity: 0.5
+                anchors.horizontalCenter: parent.horizontalCenter
+                source: "qrc:/png/faceNotice.png"
+            }
+
+            Label {
+                id: cardNotice
+                anchors.horizontalCenter: parent.horizontalCenter
+                color: "#9affffff"
+                text: qsTr("请刷人脸")
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+            }
+        }
+    }
+
+
+    Rectangle {
+        id: cardInput
+        x: (mainScreen.width - width) / 2 - parent.x
+        y: 420
+        width: 350
+        height: 350
+        visible: false
+        color: "#980e57ea"
+        radius: 20
+
+        Column {
+            x: 0
+            y: 0
+            width: 350
+            height: 350
+            visible: true
+            spacing: 30
+            padding: 0
+            topPadding: 46
+
+            Image {
+                width: 200
+                height: 200
+                opacity: 0.5
+                anchors.horizontalCenter: parent.horizontalCenter
+                source: "qrc:/png/cardNotice.png"
+            }
+
+            Label {
+                id: faceNotice
+                anchors.horizontalCenter: parent.horizontalCenter
+                color: "#9affffff"
+                text: qsTr("请刷工卡")
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+            }
+        }
+    }
+
+    Rectangle {
+        id: fingerInput
+        x: (mainScreen.width - width) / 2 - parent.x
+        y: 420
+        width: 350
+        height: 350
+        visible: false
+        color: "#980e57ea"
+        radius: 20
+
+        Column {
+            x: 0
+            y: 0
+            width: 350
+            height: 350
+            visible: true
+            spacing: 30
+            padding: 0
+            topPadding: 46
+
+            Image {
+                width: 200
+                height: 200
+                opacity: 0.5
+                anchors.horizontalCenter: parent.horizontalCenter
+                source: "qrc:/png/fingerNotice.png"
+            }
+
+            Label {
+                id: fingerNotice
+                anchors.horizontalCenter: parent.horizontalCenter
+                color: "#9affffff"
+                text: qsTr("请刷指纹")
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+            }
+        }
+
+        onVisibleChanged: {
+            // signal_fingerWork(visible)
+
+        }
+
+    }
+
+    Rectangle {
+        id: errorLogin
+        x: 785
+        y: 415
+        width: 350
+        height: 350
+        visible: false
+        color: "#66ea3a0e"
+        radius: 20
+
+        onVisibleChanged: {
+            errorNotice.visible = errorLogin.visible
+        }
+
+        Column {
+            x: 0
+            y: 0
+            width: 350
+            height: 350
+            visible: true
+            spacing: 30
+            padding: 0
+            topPadding: 46
+
+            Image {
+                width: 200
+                height: 200
+                opacity: 0.5
+                anchors.horizontalCenter: parent.horizontalCenter
+                source: "qrc:/png/error.png"
+            }
+
+            Label {
+                id: errorNotice_old
+                anchors.horizontalCenter: parent.horizontalCenter
+                color: "#9affffff"
+                text: qsTr("登录失败")
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+            }
+        }
+    }
+
+
+    Label {
+        id: errorNotice
+        y:835
+        anchors.horizontalCenter: errorLogin.horizontalCenter
+        color: "#9affffff"
+        text: qsTr("用户名密码错误")
+        font.pixelSize: 30
+        horizontalAlignment: Text.AlignHCenter
+        verticalAlignment: Text.AlignVCenter
+        font.bold: true
+        visible: false
+    }
+
+    Timer {
+        interval: 1000
+        running: true
+        repeat: true
+        onTriggered: {
+            if(errorNoticeTimeout > 0)
+            {
+                errorNoticeTimeout--;
+            }
+            else{
+                errorLogin.visible = false;
+            }
+
+            if(enterSetTimeout > 0)
+            {
+                enterSetTimeout--;
+            }
+        }
+    }
+
+    function username_login() {
+        var username = usernameText.text;
+        var password = passwordText.text;
+        if(username.length > 0)
+        {
+            signal_login(0, username, password);
+        }
+        else{
+            login_return_stat(-99, "请输入用户名");
+        }
+    }
+
+    function card_login() {
+        if(cardID.length > 0)
+        {
+            signal_login(1, cardID, cardID);
+        }
+    }
+
+
+    function login_return_stat(stat, notice)
+    {
+        if(stat === 0)
+        {
+            // 获取http 异常类型字典值
+            interactiveCore.appendTask(
+                        InteractiveTask.TypeHttpGet_exception_type, null, null);
+            // 获取http 严重等级字典值
+            interactiveCore.appendTask(
+                        InteractiveTask.TypeHttpGet_severity_level, null, null);
+
+            // 通过物资Code获取物资柜ID
+            interactiveCore.appendTask(
+                        InteractiveTask.TypeHttpGet_selectIsMaterialsCabinetByCode, null, null);
+
+            // 获取用户登录信息
+            interactiveCore.appendTask(
+                        InteractiveTask.TypeHttpGet_getInfo, null, null);
+            interactiveCore.appendTask(
+                        InteractiveTask.TypeDataCacheRefresh, null, null);
+
+            usernameText.text = "";
+            passwordText.text = "";
+            passLogin_rec.visible = false;
+            password_sel.enabled = true;
+            cardInput.visible = false;
+            fingerInput.visible = false;
+            loginScreen.visible = false;
+            mainScreen.resetLogin_timeout();
+            mainScreen.visible = true;
+            materialSelmodel.visible = true;
+
+        }
+        else {
+            passwordText.text = "";
+            errorNotice.text = qsTr(notice);
+            errorLogin.visible = true
+            errorNoticeTimeout = 3
+        }
+    }
+
+    Item {
+        id: __materialLibrary__
+    }
+
+    states: [
+        State {
+            name: "clicked"
+        }
+    ]
+
+}

+ 645 - 0
content/MainScreen.qml

@@ -0,0 +1,645 @@
+import QtQuick
+import QtQuick.Controls
+import com.lock 1.0  // 导入 C++ 类
+
+import com.InteractiveTask 1.0
+
+Item {
+    id: mainscreen
+    width: 1920
+    height: 1080
+
+    property int login_timeout: 99
+    property bool loginStat: false
+    property bool opendoor: false
+
+    property string lastItemStr : "";
+
+    signal signal_logout
+
+    Connections {
+        target: mainscreen
+        onVisibleChanged: {
+            if (mainscreen.visible === true)
+            {
+                proThread.moveCursorTo(0, 0);
+
+                material_sel_background.opacity = 1;
+                material_exc_background.opacity = 0;
+                set_sel_background.opacity = 0;
+            }
+        }
+    }
+
+    Rectangle {
+        id: rectangle
+        x: 0
+        y: 0
+        width: 267
+        height: 1080
+        color: "#4c2b7ae9"
+
+        Image {
+            id: logoImage
+            x: 34
+            y: 40
+            width: 200
+            height: 50
+            source: "qrc:/png/bozz.png"
+            fillMode: Image.PreserveAspectFit
+        }
+
+        Label {
+            id: label1
+            x: 54
+            y: 105
+            text: qsTr("物资管理")
+            color: "#ddffffff"
+            font.pixelSize: 40
+            font.bold: true
+        }
+
+        Canvas {
+            anchors.fill: parent
+            onPaint: {
+                var ctx = getContext("2d");
+                ctx.lineWidth = 5; // 设置线的宽度
+                ctx.strokeStyle = "white"; // 设置线的颜色为白色
+                ctx.beginPath();
+                ctx.moveTo(45, 165); // 直线的起点
+                ctx.lineTo(225, 165); // 直线的终点
+                ctx.stroke(); // 绘制直线
+
+                ctx.beginPath();
+                ctx.moveTo(45, 930); // 直线的起点
+                ctx.lineTo(225, 930); // 直线的终点
+                ctx.stroke(); // 绘制直线
+            }
+        }
+
+        Rectangle {
+            id: rectangle1
+            x: 44
+            y: 176
+            width: 180
+            height: 560
+            color: "#00ffffff"
+
+            Button {
+                id: material_sel
+                x: 0
+                y: 10
+                width: 180
+                height: 180
+                hoverEnabled: false
+
+                background: Rectangle {
+                    id:material_sel_background
+                    color: "#942b7ae9" // 设置背景为透明
+                    radius: 10 // 可选,设置圆角
+                    opacity: 1
+                }
+                icon.height: 120
+                icon.width: 120
+                display: AbstractButton.TextUnderIcon
+                icon.source: "qrc:/png/material.png"
+                icon.color: "#00ffffff"
+                text: qsTr("物资管理")
+                font.pixelSize: 30
+                palette.buttonText: "white"  // 设置字体颜色为绿
+                Connections {
+                    target: material_sel
+                    onClicked: {
+                        if(setView.visible === true || materialException.visible === true)
+                        {
+                            material_sel_background.opacity = 1;
+                            material_exc_background.opacity = 0;
+                            set_sel_background.opacity = 0;
+
+
+                            switchViewOff();
+                            changeModel_text(material_sel.text);
+                            materialSelmodel.visible = true;
+
+                            // proThread.moveCursorTo(0, 0);
+                        }
+                    }
+                }
+            }
+
+            Button {
+                id: material_exc
+                x: 0
+                y: 200
+                width: 180
+                height: 180
+                hoverEnabled: false
+                visible: true
+
+                background: Rectangle {
+                    id:material_exc_background
+                    color: "#942b7ae9" // 设置背景为透明
+                    radius: 10 // 可选,设置圆角
+                    opacity: 0
+                }
+                icon.height: 120
+                icon.width: 120
+                display: AbstractButton.TextUnderIcon
+                icon.source: "qrc:/png/exception.png"
+                icon.color: "#00ffffff"
+                text: qsTr("异常处理")
+                font.pixelSize: 30
+                palette.buttonText: "white"  // 设置字体颜色为绿
+                Connections {
+                    target: material_exc
+                    onClicked: {
+                        if(setView.visible === true || materialSelmodel.visible === true)
+                        {
+                            material_sel_background.opacity = 0;
+                            material_exc_background.opacity = 1;
+                            set_sel_background.opacity = 0;
+
+                            switchViewOff();
+                            changeModel_text(material_exc.text);
+
+                            materialSelmodel.visible = false;
+                            materialException.visible = true;
+
+                            // proThread.moveCursorTo(0, 0);
+                        }
+                    }
+                }
+            }
+        }
+
+
+        Button {
+            id: set_sel
+            x: 44
+            y: 740
+            width: 180
+            height: 180
+            hoverEnabled: false
+
+            background: Rectangle {
+                id: set_sel_background
+                color: "#942b7ae9" // 设置背景为透明
+                radius: 10 // 可选,设置圆角
+                opacity: 0
+            }
+            icon.height: 120
+            icon.width: 120
+            display: AbstractButton.TextUnderIcon
+            icon.source: "qrc:/png/set.png"
+            icon.color: "#00ffffff"
+            text: qsTr("设置")
+            font.pixelSize: 30
+            palette.buttonText: "white"  // 设置字体颜色为绿色
+            visible: true
+            Connections {
+                target: set_sel
+                onClicked: {
+                    if(materialSelmodel.visible === true || materialException.visible === true)
+                    {
+                        material_sel_background.opacity = 0;
+                        material_exc_background.opacity = 0;
+                        set_sel_background.opacity = 1;
+                        switchViewOff();
+                        changeModel_text(set_sel.text);
+                        setView.load_configParam(false);
+                        setView.fingerVisible = true;
+                        setView.visible = true;
+
+                        // proThread.moveCursorTo(0, 0);
+                    }
+                }
+            }
+        }
+
+        Text {
+            id: timeDisplay
+            x: 44
+            y: 950
+            font.pixelSize: 32
+            color: "white"
+            text: Qt.formatDateTime(new Date(), "yyyy-MM-dd\nhh:mm:ss")
+            horizontalAlignment: Text.AlignHCenter
+            verticalAlignment: Text.AlignVCenter
+            anchors.verticalCenterOffset: 451
+            anchors.horizontalCenterOffset: 0
+            // 添加颜色渐变动画
+            // Behavior on color {
+            //     ColorAnimation { duration: 500 }
+            // }
+        }
+    }
+
+    Rectangle {
+        x: 326
+        y: 21
+        width: 185
+        height: 84
+        color: "transparent"
+
+        // 图片
+        Image {
+            id: model_icon
+            source: "qrc:/png/material.png" // 图片路径(可以是本地文件或资源文件)
+            width: 60
+            height: 60
+            anchors.left: parent.left
+            anchors.verticalCenter: parent.verticalCenter
+        }
+
+        // 文字
+        Text {
+            id: model_text
+            text: "物资管理"
+            color: "white"
+            font.pixelSize: 30
+            anchors.left: model_icon.right // 文字在图片右侧
+            anchors.leftMargin: 10  // 图片和文字之间的间距
+            anchors.verticalCenter: parent.verticalCenter
+        }
+    }
+
+    Rectangle {
+        x: 1375
+        y: 21
+        width: 524
+        height: 84
+        color: "transparent"
+
+        Text {
+            id: user_timeout
+            visible: false
+            text: "系统将于 " + formatNumber(login_timeout) + " 秒后退出"
+            color: "white"
+            font.pixelSize: 30
+            anchors.left: parent.left
+            anchors.verticalCenter: parent.verticalCenter
+        }
+
+        // 图片
+        Image {
+            id: user_icon
+            source: "qrc:/png/user_title.png" // 图片路径(可以是本地文件或资源文件)
+            width: 60
+            height: 60
+            anchors.left: user_timeout.right
+            anchors.leftMargin: 10
+            anchors.verticalCenter: parent.verticalCenter
+        }
+
+        Button {
+            id: user_text
+            background: Rectangle {
+                radius: 2 // 可选,设置圆角
+                opacity: 0
+            }
+            text: ""
+            anchors.left: user_icon.right // 文字在图片右侧
+            anchors.leftMargin: 10  // 图片和文字之间的间距
+            anchors.verticalCenter: parent.verticalCenter
+            font.pixelSize: 30
+            palette.buttonText: "white"  // 设置字体颜色为绿
+            onClicked: {
+                if(opendoor === false)
+                {
+                    logout()
+                }
+            }
+        }
+    }
+
+    Timer {
+        interval: 1000
+        running: true
+        repeat: true
+        onTriggered: {
+            timeDisplay.text = Qt.formatDateTime(new Date(), "yyyy-MM-dd\nhh:mm:ss")
+            // timeDisplay.color = Qt.rgba(Math.random(), Math.random(), Math.random(), 1) // 随机颜色
+            if(opendoor === false)
+            {
+                if(mainScreen.visible === true && login_timeout > 0)
+                {
+                    login_timeout = login_timeout - 1
+                    if(login_timeout == 30)
+                    {
+                        user_timeout.visible = true;
+                    }
+                }
+                else{
+                    if(loginStat == true)
+                    {
+                        logout()
+                    }
+                }
+            }
+            else{
+                login_timeout = pConfig.sloginTimeout;
+            }
+        }
+    }
+
+    // 格式化函数:将整数格式化为两位数字并补零
+    function formatNumber(number) {
+        // 使用 padStart 方法补零
+        return number.toString().padStart(2, '0');
+    }
+
+    function lockStat_callback(left, right) {
+        if(left === false || right === false)
+        {
+            opendoor = true;
+        }
+        else if(left === true && right === true)
+        {
+            opendoor = false;
+        }
+    }
+
+    function login_return_param(name, auth){
+        user_text.text = name;
+        loginStat = true;
+    }
+
+    function changeModel_text(value) {
+        // refreshListMode();
+        if (value === material_sel.text || value === set_sel.text || value === material_exc.text)
+        {
+            set_sel.opacity = 1
+            material_exc.opacity = 1
+        }
+        else
+        {
+            set_sel.opacity = 0.5
+            material_exc.opacity = 0.5
+        }
+
+        if(value === material_sel.text)
+        {
+            model_text.text = material_sel.text;
+            model_icon.source = "qrc:/png/takeback.png";
+            resetLogin_timeout();
+        }
+        else if(value === set_sel.text)
+        {
+            model_text.text = set_sel.text;
+            model_icon.source = "qrc:/png/set.png";
+            resetLogin_timeout();
+        }
+        else if(value === "物资取还")
+        {
+            model_text.text = "物资取还";
+            model_icon.source = "qrc:/png/takeback.png";
+            resetLogin_timeout();
+        }
+
+        else if(value === "物资使用说明")
+        {
+            model_text.text = "物资使用说明";
+            model_icon.source = "qrc:/png/instructions.png";
+            resetLogin_timeout();
+        }
+
+        else if(value === "物资检查")
+        {
+            model_text.text = "物资检查计划";
+            model_icon.source = "qrc:/png/inspection.png";
+            resetLogin_timeout();
+        }
+        else if(value === "物资检查表")
+        {
+            model_text.text = "物资检查表";
+            model_icon.source = "qrc:/png/inspection.png";
+            resetLogin_timeout();
+        }
+
+        else if(value === "维修/更换")
+        {
+            model_text.text = "维修/更换";
+            model_icon.source = "qrc:/png/replacement.png";
+            resetLogin_timeout();
+        }
+        else if(value === "异常处理")
+        {
+            model_text.text = "异常处理";
+            model_icon.source = "qrc:/png/exception_handle.png";
+            resetLogin_timeout();
+        }
+    }
+
+    function changeModel_text_Instructions(value) {
+        model_text.text = value;
+        model_icon.source = "qrc:/png/instructions.png";
+
+    }
+
+    function resetLogin_timeout()
+    {
+        user_timeout.visible = false;
+        login_timeout = pConfig.sloginTimeout;
+    }
+
+    function logout()
+    {
+        user_timeout.visible = false;
+        loginStat = false;
+        materialStatistics.visible = false;
+        materialTakeBack.visible = false;
+
+        materialInstructions.visible = false;
+
+        materialCheckPlan.visible = false;
+        materialCheckForm.visible = false;
+        materialCheckSign.visible = false;
+        materialCheckUpdate.visible = false;
+
+        materialReplace.visible = false;
+        materialReplaceHand.visible = false;
+        materialReplaceAuto.visible = false;
+        materialManualReplace.visible = false;
+
+        materialException.visible = false;
+        // materialExceptionUpdate.visible = false;
+        materialExceptionReport.visible = false;
+        // materialExceptionFinish.visible = false;
+
+        facialRecognition.visible = false;
+
+        materialStocktaking.visible = false;
+
+        waitPromptBox.hide();
+        hangPromptBox.hideExecuteCallback();
+        infoPromptBox.hide();
+
+        materialSelmodel.visible = false;
+        setView.visible = false;
+        mainScreen.visible = false;
+        loginScreen.visible = true;
+        loginScreen.focus = true;
+        signal_logout();
+    }
+
+    function switchViewOff()
+    {
+        materialSelmodel.visible = false;
+        setView.fingerVisible = false;
+        setView.visible = false;
+
+        materialStatistics.visible = false;
+        materialTakeBack.visible = false;
+
+        materialInstructions.visible = false;
+
+        materialCheckPlan.visible = false;
+        materialCheckForm.visible = false;
+        materialCheckSign.visible = false;
+        materialCheckUpdate.visible = false;
+
+        materialReplace.visible = false;
+        materialReplaceHand.visible = false;
+        materialReplaceAuto.visible = false;
+        materialManualReplace.visible = false;
+
+
+        materialException.visible = false;
+        // materialExceptionUpdate.visible = false;
+        materialExceptionReport.visible = false;
+        // materialExceptionFinish.visible = false;
+
+        materialStocktaking.visible = false;
+
+        facialRecognition.visible = false;
+
+        waitPromptBox.hide();
+        hangPromptBox.hideExecuteCallback();
+        infoPromptBox.hide();
+    }
+
+    function switchViewOnEx()
+    {
+        if (lastItemStr === "materialCheckPlan")
+        {
+            materialCheckPlan.visible = true;
+        }
+        else if (lastItemStr === "materialCheckForm")
+        {
+            materialCheckForm.visible = true;
+        }
+        else if (lastItemStr === "materialCheckSign")
+        {
+            materialCheckSign.visible = true;
+        }
+
+        else if (lastItemStr === "materialTakeBack")
+        {
+            materialTakeBack.visible = true;
+        }
+        else if (lastItemStr === "materialReplace")
+        {
+            materialReplace.visible = true;
+        }
+        else if (lastItemStr === "materialManualReplace")
+        {
+            materialManualReplace.visible = true;
+        }
+        else if (lastItemStr === "materialException")
+        {
+            materialException.visible = true;
+        }
+
+    }
+
+    function switchViewOffEx()
+    {
+        if (materialCheckPlan.visible === true)
+        {
+            lastItemStr = "materialCheckPlan";
+        }
+        else if (materialCheckForm.visible === true)
+        {
+            lastItemStr = "materialCheckForm";
+        }
+        else if (materialCheckSign.visible === true)
+        {
+            lastItemStr = "materialCheckSign";
+        }
+        else if (materialTakeBack.visible === true)
+        {
+            lastItemStr = "materialTakeBack";
+        }
+        else if (materialReplace.visible === true)
+        {
+            lastItemStr = "materialReplace";
+        }
+        else if (materialManualReplace.visible === true)
+        {
+            lastItemStr = "materialManualReplace";
+        }
+        else if (materialException.visible === true)
+        {
+            lastItemStr = "materialException";
+        }
+
+
+        materialSelmodel.visible = false;
+        setView.fingerVisible = false;
+        setView.visible = false;
+
+        materialStatistics.visible = false;
+        materialTakeBack.visible = false;
+
+        materialInstructions.visible = false;
+
+        materialCheckPlan.visible = false;
+        materialCheckForm.visible = false;
+        materialCheckSign.visible = false;
+        materialCheckUpdate.visible = false;
+
+        materialReplace.visible = false;
+        materialReplaceHand.visible = false;
+        materialReplaceAuto.visible = false;
+        materialManualReplace.visible = false;
+
+
+        materialException.visible = false;
+        // materialExceptionUpdate.visible = false;
+        materialExceptionReport.visible = false;
+        // materialExceptionFinish.visible = false;
+
+        materialStocktaking.visible = false;
+
+        facialRecognition.visible = false;
+
+        waitPromptBox.hide();
+        hangPromptBox.hideExecuteCallback();
+        infoPromptBox.hide();
+    }
+
+
+
+    function get_error_callback(isError)
+    {
+        material_exc.visible = isError;
+    }
+
+
+    // 刷新model列表
+    function refreshListMode()
+    {
+        var taskType = InteractiveTask.TypeMaterialExceptionRefreshListModel;
+        interactiveCore.appendTask(
+                    taskType, "", ()=>{
+                        if (materialexception_modelMaterialException.count() > 0)
+                        {
+                            material_exc.visible = true;
+                        }
+                        else
+                        {
+                            material_exc.visible = false;
+                        }
+                    });
+    }
+}

+ 1387 - 0
content/MaterialCheckForm.qml

@@ -0,0 +1,1387 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+import com.InteractiveTask 1.0
+
+Item {
+    id: materialcheckform
+    x: 290
+    y: 130
+    width: 1600
+    height: 920
+
+    property string strMaterialCheckFormGet: ""
+
+    signal signal_getMaterialCheckForm(int planId);
+
+    signal signal_postSaveForm(string data);
+
+    onVisibleChanged: {
+        if (visible === true)
+        {
+            proThread.moveCursorTo(0, 0);
+        }
+        if (visible === false)
+            materialcheckform_dialog_confirm.close();
+    }
+
+    PromptInfo
+    {
+        id: materialcheckform_prompt_info;
+    }
+
+    Connections {
+        target: materialcheckform
+        onVisibleChanged: {
+            if (materialcheckform.visible === true)
+            {
+                waitPromptBox.show();
+                signal_getMaterialCheckForm(materialCheckPlan.planId);
+            }
+            else
+            {
+                materialcheckform_tableModel.clear();
+                materialcheckform_tableModel_standard.clear();
+            }
+        }
+    }
+
+    ListModel {
+        id: materialcheckform_tableModel
+        // 物资标志
+        // materialFlag: 0 = 未定义、 1 = 正常、 2 = 损坏、 3 = 过期
+
+        // onDataChanged: {
+        //     // build_model_view()
+        // }
+    }
+
+    ListModel {
+        id: materialcheckform_tableModel_standard
+    }
+
+    Dialog {
+        id: materialcheckform_dialog_confirm
+        title: "操作确认"
+        x: parent.width / 2 - width / 2
+        y: parent.height / 2 - height / 2
+        width: 600
+        height: 400
+        clip: true
+        modal: true
+
+        property int flag: 0;
+
+
+        // 自定义背景(带圆角)
+        background: Rectangle {
+            color: "white"
+            clip: true
+        }
+
+        // 自定义标题栏
+        header: Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: 50 // 设置标题栏高度
+            color: "#ff3968e9" // 设置标题栏背景色
+            // 标题文本
+            Text {
+                x: 20
+                y: 0
+                width: 80
+                height: 50 // 设置标题栏高度
+                text: materialcheckform_dialog_confirm.title
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignLeft
+                verticalAlignment: Text.AlignVCenter
+                color: "white"
+            }
+        }
+
+        contentItem: Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: 200
+            color: "white"
+            Text {
+                id: materialcheckform_text_dialog_item;
+                width: parent.width
+                height: 100
+                text: ""
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+        }
+
+        // 单选按钮
+        Item {
+            id: materialcheckform_item_check
+            x: 0
+            y: 150
+            width: parent.width
+            height: 100
+            Row {
+                anchors.horizontalCenter: parent.horizontalCenter
+                spacing: 20
+
+                // 正常单选按钮
+                Rectangle {
+                    id: materialcheckform_btn_normal
+                    width: 164
+                    height: 61
+                    color: "#33008000"
+                    radius: 20
+                    clip: true
+
+                    ToolButton
+                    {
+                        anchors.centerIn: parent
+                        enabled: false                          // 不可点击
+                        display: AbstractButton.TextBesideIcon  // 文字在图标旁边
+
+                        icon.source: ""
+                        icon.width: 36
+                        icon.height: 30
+
+                        text: "正常"
+                        palette.buttonText: "#ffffff"
+                        font {
+                            pixelSize: 25
+                        }
+                    }
+
+                    MouseArea {
+                        anchors.fill: parent
+                        onClicked: {
+                            materialcheckform_dialog_confirm.flag =
+                                    (materialcheckform_dialog_confirm.flag === 1 ? 0 : 1);
+                        }
+                    }
+                }
+
+                Rectangle {
+                    id: materialcheckform_btn_expire;
+                    width: 164
+                    height: 61
+                    color: "#33ff9900"
+                    radius: 20
+                    clip: true
+
+                    ToolButton
+                    {
+                        anchors.centerIn: parent
+                        enabled: false                          // 不可点击
+                        display: AbstractButton.TextBesideIcon  // 文字在图标旁边
+
+                        icon.source: ""
+                        icon.width: 36
+                        icon.height: 30
+
+                        text: "过期"
+                        palette.buttonText: "#ffffff"
+                        font {
+                            pixelSize: 25
+                        }
+                    }
+                    MouseArea {
+                        anchors.fill: parent
+                        onClicked: {
+                            materialcheckform_dialog_confirm.flag =
+                                    (materialcheckform_dialog_confirm.flag === 2 ? 0 : 2);
+                        }
+                    }
+                }
+
+                Rectangle {
+                    id: materialcheckform_btn_damage;
+                    width: 164
+                    height: 61
+                    color: "#33ff0000"
+                    radius: 20
+                    clip: true
+
+                    ToolButton
+                    {
+                        anchors.centerIn: parent
+                        enabled: false                          // 不可点击
+                        display: AbstractButton.TextBesideIcon  // 文字在图标旁边
+
+                        icon.source: ""
+                        icon.width: 36
+                        icon.height: 30
+
+                        text: "损坏"
+                        palette.buttonText: "#ffffff"
+                        font {
+                            pixelSize: 25
+                        }
+                    }
+                    MouseArea {
+                        anchors.fill: parent
+                        onClicked: {
+                            materialcheckform_dialog_confirm.flag =
+                                    (materialcheckform_dialog_confirm.flag === 3 ? 0 : 3);
+                        }
+                    }
+                }
+            }
+        }
+
+        // 自定义 DialogButtonBox
+        DialogButtonBox {
+            id: materialcheckform_buttonBox
+            x: 0
+            y: 250
+            width: parent.width
+            height: 100
+
+            // 自定义按钮
+            Button {
+                implicitWidth: 120
+                implicitHeight: 50
+                text: "确认"
+                background: Rectangle {
+                    color: "green"
+                    radius: 5
+                }
+                contentItem: Text {
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "white"
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                onClicked: {
+                    if (materialcheckform_dialog_confirm.flag != 0)
+                    {
+                        for (var i = 0; i < materialcheckform_tableModel.count; i++)
+                        {
+                            var item = materialcheckform_tableModel.get(i);
+                            if (item.materialFlag === 0)
+                            {
+                                item.materialFlag = materialcheckform_dialog_confirm.flag;
+                            }
+                        }
+                    }
+
+                    materialcheckform_dialog_confirm.close()
+                }
+            }
+
+            Button {
+                implicitWidth: 120
+                implicitHeight: 50
+                text: "取消"
+                background: Rectangle {
+                    color: "red"
+                    radius: 5
+                }
+                contentItem: Text {
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "white"
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                onClicked: {
+                    materialcheckform_dialog_confirm.reject()
+                }
+            }
+        }
+
+        onFlagChanged: {
+            materialcheckform_btn_normal.color= "#33008000";
+            materialcheckform_btn_expire.color= "#33FF9900";
+            materialcheckform_btn_damage.color= "#33FF0000";
+
+            switch (materialcheckform_dialog_confirm.flag)
+            {
+            case 1:{
+                materialcheckform_btn_normal.color= "#008000";
+            }break;
+            case 2:{
+                materialcheckform_btn_expire.color= "#FF9900";
+            }break;
+            case 3:{
+                materialcheckform_btn_damage.color= "#FF0000";
+            }break;
+            }
+        }
+    }
+
+
+
+    Dialog {
+        id: materialcheckform_dialog_confirm_prompt
+        title: "操作确认"
+        x: parent.width / 2 - width / 2
+        y: parent.height / 2 - height / 2
+        width: 600
+        height: 400
+        clip: true
+        modal: true
+
+        property int flag: 0;
+
+
+        // 自定义背景(带圆角)
+        background: Rectangle {
+            color: "white"
+            clip: true
+        }
+
+        // 自定义标题栏
+        header: Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: 50 // 设置标题栏高度
+            color: "#ff3968e9" // 设置标题栏背景色
+            // 标题文本
+            Text {
+                x: 20
+                y: 0
+                width: 80
+                height: 50 // 设置标题栏高度
+                text: materialcheckform_dialog_confirm_prompt.title
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignLeft
+                verticalAlignment: Text.AlignVCenter
+                color: "white"
+            }
+        }
+
+        contentItem: Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: 200
+            color: "white"
+            Text {
+                id: materialcheckform_text_dialog_prompt;
+                width: parent.width
+                height: 100
+                text: ""
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+        }
+
+
+        // 自定义 DialogButtonBox
+        DialogButtonBox {
+            x: 0
+            y: 250
+            width: parent.width
+            height: 100
+
+            // 自定义按钮
+            Button {
+                implicitWidth: 120
+                implicitHeight: 50
+                text: "确认"
+                background: Rectangle {
+                    color: "green"
+                    radius: 5
+                }
+                contentItem: Text {
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "white"
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                onClicked: {
+
+                    materialcheckform_dialog_confirm_prompt.close();
+                }
+            }
+
+            Button {
+                implicitWidth: 120
+                implicitHeight: 50
+                text: "取消"
+                background: Rectangle {
+                    color: "red"
+                    radius: 5
+                }
+                contentItem: Text {
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "white"
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                onClicked: {
+                    materialcheckform_dialog_confirm_prompt.reject()
+                }
+            }
+        }
+    }
+
+
+    // 一键检查
+    Button {
+        id: materialcheckform_btn_onekey_check
+        x: 928
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#ff9900" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("一键检查")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialcheckform_btn_onekey_check
+            onClicked: {
+                var iCount = 0;
+                for (var i = 0; i < materialcheckform_tableModel.count; i++)
+                {
+                    var item = materialcheckform_tableModel.get(i);
+                    if (item.materialFlag === 0)
+                    {
+                        iCount++;
+                    }
+                }
+
+                var strText;
+                if (iCount > 0)
+                {
+                    strText = "将待检查的" + iCount + "件物资,全部标注为:";
+                    materialcheckform_item_check.visible = true;
+                }
+                else
+                {
+                    strText = "没有待检查的物资";
+                    materialcheckform_item_check.visible = false;
+                }
+                materialcheckform_text_dialog_item.text = strText;
+
+                materialcheckform_dialog_confirm.open();
+            }
+        }
+    }
+
+    // 保存
+    Button {
+        id: materialcheckform_btn_save
+        x: 1168
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#ff0000" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("保存")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialcheckform_btn_save
+            onClicked: {
+                infoPromptBox.title("操作确认");
+                infoPromptBox.message("确定要保存检查结果吗?");
+                infoPromptBox.button_clear();
+                infoPromptBox.button_push("red", "取消", null, null);
+                infoPromptBox.button_push(
+                            "#055eb3", "确定", ()=>{
+                                var taskType = InteractiveTask.TypeHttpPost_insertCheckRecord;
+
+                                var jsonObjRoot = {};
+                                var jsonArrList = [];
+                                for (var i = 0; i < materialcheckform_tableModel.count; i++)
+                                {
+                                    var item = materialcheckform_tableModel.get(i);
+                                    var jsonObjList = item.materialJson;
+
+                                    if (item.materialFlag === 0)
+                                    {
+                                        jsonObjList["status"] = "";
+                                        jsonObjList["reason"] = "";
+                                    }
+                                    else if (item.materialFlag === 1)
+                                    {
+                                        jsonObjList["status"] = "0";
+                                        jsonObjList["reason"] = "";
+                                    }
+                                    else if (item.materialFlag === 2)
+                                    {
+                                        jsonObjList["status"] = "1";
+                                        jsonObjList["reason"] = "2";
+                                    }
+                                    else if (item.materialFlag === 3)
+                                    {
+                                        jsonObjList["status"] = "1";
+                                        jsonObjList["reason"] = "1";
+                                    }
+
+                                    jsonArrList.push(jsonObjList);
+                                }
+
+                                jsonObjRoot["list"] = jsonArrList;
+                                var strJson = JSON.stringify(jsonObjRoot);
+
+                                // 添加提交任务
+                                interactiveCore.appendTask(
+                                    taskType, strJson, (json)=>{
+                                        var jsonObjRoot = JSON.parse(json);
+                                        if (jsonObjRoot.code === 200)
+                                        {
+                                            var iWait = 0;
+                                            var iNormal = 0;
+                                            var iExpire = 0;
+                                            var iDamage = 0;
+
+                                            var text = "";
+
+                                            for (var i = 0; i < materialcheckform_tableModel.count; i++)
+                                            {
+                                                var item = materialcheckform_tableModel.get(i);
+                                                switch (item.materialFlag)
+                                                {
+                                                    case 0: iWait++; break;
+                                                    case 1: iNormal++; break;
+                                                    case 2: iExpire++; break;
+                                                    case 3: iDamage++; break;
+                                                }
+                                            }
+
+                                            materialcheckform_text_wait_check.text = "待检查:" + iWait
+                                            materialcheckform_text_normal_check.text = "正常:" + iNormal
+                                            materialcheckform_text_expire_check.text = "过期:" + iExpire
+                                            materialcheckform_text_damage_check.text = "损坏:" + iDamage
+
+                                            if (iWait > 0)
+                                            {
+                                                text = "保存成功,还有" + iWait + "件物资待检查";
+                                            }
+                                            else
+                                            {
+                                                text = "保存成功,没有物资待检查";
+                                            }
+
+                                            infoPromptBox.title("保存成功");
+                                            infoPromptBox.message(text);
+                                            infoPromptBox.button_clear();
+                                            infoPromptBox.button_push("#055eb3", "确定", null, null);
+                                            infoPromptBox.show();
+                                        }
+                                        else
+                                        {
+                                            infoPromptBox.title("保存失败");
+                                            infoPromptBox.message(jsonObjRoot.msg);
+                                            infoPromptBox.button_clear();
+                                            infoPromptBox.button_push("#055eb3", "确定", null, null);
+                                            infoPromptBox.show();
+                                        }
+                                    });
+                            }, null);
+                infoPromptBox.show();
+            }
+        }
+    }
+
+    // 返回按钮
+    Button {
+        id: materialcheckform_btn_return
+        x: 1408
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#055eb3" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("返回")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialcheckform_btn_return
+            onClicked: {
+                if (pConfig.sopenDoor)
+                {
+                    infoPromptBox.title("提示");
+                    infoPromptBox.message("开柜状态下不允许该操作");
+                    infoPromptBox.button_clear();
+                    infoPromptBox.button_push("#055eb3", "确定", null, null);
+                    infoPromptBox.show();
+                }
+                else
+                {
+                    materialcheckform.visible = false;
+                    materialCheckPlan.visible = true;
+                    mainScreen.changeModel_text("物资检查");
+                    mainScreen.resetLogin_timeout();
+                }
+            }
+        }
+    }
+
+    // 待检查 文字区域
+    Text {
+        id: materialcheckform_text_wait_check
+        x: 0
+        y: 810
+        width: 1600
+        height: 90
+        text: "待检查:0"
+        font.pixelSize: 30
+        color: "#d7d7d2"
+        horizontalAlignment: Text.AlignLeft
+        verticalAlignment: Text.AlignVCenter
+        leftPadding: 20  // 添加左边距使文本不紧贴边缘
+    }
+
+    // 正常 文字区域
+    Text {
+        id: materialcheckform_text_normal_check
+        x: 0
+        y: 810
+        width: 1600
+        height: 90
+        text: "正常:0"
+        font.pixelSize: 30
+        color: "#d7d7d2"
+        horizontalAlignment: Text.AlignLeft
+        verticalAlignment: Text.AlignVCenter
+        leftPadding: 250  // 添加左边距使文本不紧贴边缘
+    }
+
+    // 过期 文字区域
+    Text {
+        id: materialcheckform_text_expire_check
+        x: 0
+        y: 810
+        width: 1600
+        height: 90
+        text: "过期:0"
+        font.pixelSize: 30
+        color: "#d7d7d2"
+        horizontalAlignment: Text.AlignLeft
+        verticalAlignment: Text.AlignVCenter
+        leftPadding: 450  // 添加左边距使文本不紧贴边缘
+    }
+
+    // 损坏 文字区域
+    Text {
+        id: materialcheckform_text_damage_check
+        x: 0
+        y: 810
+        width: 1600
+        height: 90
+        text: "损坏:0"
+        font.pixelSize: 30
+        color: "#d7d7d2"
+        horizontalAlignment: Text.AlignLeft
+        verticalAlignment: Text.AlignVCenter
+        leftPadding: 650  // 添加左边距使文本不紧贴边缘
+    }
+
+    // 主体区域
+    Rectangle {
+        id: materialcheckform_rect_main
+        width: 1600
+        height: 800
+        color: "#272b7ae9"
+        radius: 20
+        clip: true
+
+
+        // 表格区域
+        Rectangle {
+            x: 0
+            y: 0
+            width: 1110
+            height: 800
+            color: "#272b7ae9"
+            radius: 20
+
+            // 表格
+            Column {
+                anchors.fill: parent
+                spacing: 0
+
+                // 表头
+                Row {
+                    id: materialcheckform_header
+                    width: parent.width
+                    height: 100
+                    spacing: 0
+
+                    // 编号
+                    Rectangle {
+                        width: 100
+                        height: parent.height
+                        color: "#33ffffff"
+                        border.color: "#47bfff"
+
+                        Text {
+                            anchors.centerIn: parent
+                            text: "编号"
+                            font.pixelSize: 25
+                            color: "#d7d7d2"
+                            font.bold: true
+                        }
+                    }
+
+                    // 物资类型
+                    Rectangle {
+                        width: 140
+                        height: parent.height
+                        color: "#33ffffff"
+                        border.color: "#47bfff"
+
+                        Text {
+                            anchors.centerIn: parent
+                            text: "物资类型"
+                            font.pixelSize: 25
+                            color: "#d7d7d2"
+                            font.bold: true
+                        }
+                    }
+
+                    // 物资名称
+                    Rectangle {
+                        width: 180
+                        height: parent.height
+                        color: "#33ffffff"
+                        border.color: "#47bfff"
+
+                        Text {
+                            anchors.centerIn: parent
+                            text: "物资名称"
+                            font.pixelSize: 25
+                            color: "#d7d7d2"
+                            font.bold: true
+                        }
+                    }
+
+                    // RFID
+                    Rectangle {
+                        width: 220
+                        height: parent.height
+                        color: "#33ffffff"
+                        border.color: "#47bfff"
+
+                        Text {
+                            anchors.centerIn: parent
+                            text: "RFID"
+                            font.pixelSize: 25
+                            color: "#d7d7d2"
+                            font.bold: true
+                        }
+                    }
+
+                    // 正常
+                    Rectangle {
+                        width: 80
+                        height: parent.height
+                        color: "#33ffffff"
+                        border.color: "#47bfff"
+
+                        Image {
+                            anchors.centerIn: parent
+                            visible: true
+                            source: "qrc:/png/title_normal.png"
+                            fillMode: Image.PreserveAspectFit
+                        }
+                    }
+
+                    // 过期
+                    Rectangle {
+                        width: 80
+                        height: parent.height
+                        color: "#33ffffff"
+                        border.color: "#47bfff"
+
+                        Image {
+                            anchors.centerIn: parent
+                            visible: true
+                            source: "qrc:/png/title_expire.png"
+                            fillMode: Image.PreserveAspectFit
+                        }
+                    }
+
+                    // 损坏
+                    Rectangle {
+                        width: 80
+                        height: parent.height
+                        color: "#33ffffff"
+                        border.color: "#47bfff"
+
+                        Image {
+                            anchors.centerIn: parent
+                            visible: true
+                            source: "qrc:/png/title_damage.png"
+                            fillMode: Image.PreserveAspectFit
+                        }
+                    }
+
+                    // 措施
+                    Rectangle {
+                        width: 230
+                        height: parent.height
+                        color: "#33ffffff"
+                        border.color: "#47bfff"
+
+                        Text {
+                            anchors.centerIn: parent
+                            text: "措施"
+                            font.pixelSize: 25
+                            color: "#d7d7d2"
+                            font.bold: true
+                        }
+                    }
+
+                }
+
+                // 表格内容
+                ListView {
+                    width: parent.width
+                    height: parent.height - materialcheckform_header.height
+                    clip: true
+                    model: materialcheckform_tableModel
+
+                    property var _materialTextArr: [];
+
+                    delegate: Row {
+                        width: 1110
+                        height: Math.max(materialNameRfid.implicitHeight, 100)
+                        spacing: 0
+
+                        QtObject {
+                            id: itemData
+                            property int flag: model.materialFlag
+                            onFlagChanged: {
+
+                                materialcheckform_rect_normal.color= "#272b7ae9";
+                                materialcheckform_rect_expire.color= "#272b7ae9";
+                                materialcheckform_rect_damage.color= "#272b7ae9";
+
+                                switch (flag)
+                                {
+                                case 1:{
+                                    materialcheckform_rect_normal.color= "#008000";
+                                }break;
+                                case 2:{
+                                    materialcheckform_rect_expire.color= "#FF9900";
+                                }break;
+                                case 3:{
+                                    materialcheckform_rect_damage.color= "#FF0000";
+                                }break;
+                                }
+
+                            }
+                        }
+
+                        // 编号
+                        Rectangle {
+                            width: 100
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+                            clip: true
+
+                            Text {
+                                anchors.centerIn: parent
+                                font.pixelSize: 20
+                                color: "#d7d7d2"
+                                text: model.materialCode
+                                wrapMode: Text.WordWrap
+                            }
+                        }
+
+                        // 物资类型
+                        Rectangle {
+                            width: 140
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+                            clip: true
+
+                            ToolButton
+                            {
+                                anchors.centerIn: parent
+                                enabled: false                          // 不可点击
+                                display: AbstractButton.TextUnderIcon
+
+                                icon.source: model.materialIcon
+                                icon.width: 36
+                                icon.height: 30
+
+                                text: model.materialType
+                                palette.buttonText: "#d7d7d2"
+                                font {
+                                    pixelSize: 20
+                                }
+                            }
+                        }
+
+                        // 物资名称
+                        Rectangle {
+                            width: 180
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+                            clip: true
+
+                            Text {
+                                anchors.centerIn: parent
+                                font.pixelSize: 20
+                                color: "#d7d7d2"
+                                text: model.materialName
+                                wrapMode: Text.WordWrap
+                            }
+                        }
+
+                        // RFID
+                        Rectangle {
+                            width: 220
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+                            clip: true
+
+                            Text {
+                                id: materialNameRfid
+                                width: parent.width - 10    // 留点边距
+                                anchors.horizontalCenter: parent.horizontalCenter
+                                anchors.verticalCenter: parent.verticalCenter
+                                horizontalAlignment: Text.AlignHCenter
+                                verticalAlignment: Text.AlignVCenter
+                                wrapMode: Text.WordWrap
+                                font.pixelSize: 20
+                                color: "#d7d7d2"
+                                text: model.materialRfid
+                                elide: Text.ElideRight
+
+                                ToolTip {
+                                    visible: materialNameRfid.truncated && textHoverArea.containsMouse
+                                    delay: 500
+                                    text: materialNameRfid.text
+                                }
+
+                                MouseArea {
+                                    id: textHoverArea
+                                    anchors.fill: parent
+                                    hoverEnabled: true
+                                }
+                            }
+                        }
+
+                        // 正常
+                        Rectangle {
+                            id: materialcheckform_rect_normal
+                            width: 80
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+
+                            Image {
+                                anchors.centerIn: parent
+                                visible: true
+                                source: "qrc:/png/title_normal.png"
+                                fillMode: Image.PreserveAspectFit
+                            }
+
+                            MouseArea {
+                                anchors.fill: parent  // 让MouseArea覆盖整个Image区域
+                                onClicked: {
+                                    model.materialFlag = (model.materialFlag === 1 ? 0 : 1);
+                                    model.materialText = (model.materialFlag === 1 ? "" : "")
+                                }
+                            }
+                        }
+
+                        // 过期
+                        Rectangle {
+                            id: materialcheckform_rect_expire
+                            width: 80
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+
+                            Image {
+                                anchors.centerIn: parent
+                                visible: true
+                                source: "qrc:/png/title_expire.png"
+                                fillMode: Image.PreserveAspectFit
+                            }
+                            MouseArea {
+                                anchors.fill: parent  // 让MouseArea覆盖整个Image区域
+                                onClicked: {
+                                    model.materialFlag = (model.materialFlag === 2 ? 0 : 2);
+                                    model.materialText = (model.materialFlag === 2 ? "更换" : "")
+                                }
+                            }
+                        }
+
+                        // 损坏
+                        Rectangle {
+                            id: materialcheckform_rect_damage
+                            width: 80
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+
+                            Image {
+                                anchors.centerIn: parent
+                                visible: true
+                                source: "qrc:/png/title_damage.png"
+                                fillMode: Image.PreserveAspectFit
+                            }
+                            MouseArea {
+                                anchors.fill: parent  // 让MouseArea覆盖整个Image区域
+                                onClicked: {
+                                    model.materialFlag = (model.materialFlag === 3 ? 0 : 3);
+                                    model.materialText = (model.materialFlag === 3 ? "更换或维修" : "")
+                                }
+                            }
+                        }
+
+                        // 措施
+                        Rectangle {
+                            width: 230
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+                            clip: true
+
+
+                            Text {
+                                anchors.centerIn: parent
+                                font.pixelSize: 20
+                                color: "#d7d7d2"
+                                font.bold: true
+                                text: model.materialText
+                                wrapMode: Text.WordWrap
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // 检查标准
+        Rectangle {
+            x: 1140
+            y: 0
+            width: 460
+            height: 800
+            color: "#272b7ae9"
+            radius: 20
+
+            //
+            Column {
+                anchors.fill: parent
+                spacing: 0
+
+                //
+                Row {
+                    id: materialcheckform_header_standard
+                    width: parent.width
+                    height: 100
+                    spacing: 0
+
+                    // 编号
+                    Rectangle {
+                        width: 460
+                        height: parent.height
+                        color: "#33ffffff"
+                        border.color: "#47bfff"
+
+                        Text {
+                            anchors.centerIn: parent
+                            text: "检查标准"
+                            font.pixelSize: 25
+                            color: "#d7d7d2"
+                            font.bold: true
+                        }
+                    }
+                }
+
+                // 表格内容
+                ListView {
+                    width: parent.width
+                    height: parent.height - materialcheckform_header_standard.height
+                    clip: true
+                    model: materialcheckform_tableModel_standard
+
+                    delegate: Row {
+                        id: materialcheckform_content_row;
+                        width: parent.width
+                        spacing: 0
+
+                        // 文本内容
+                        Rectangle {
+                            width: parent.width
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+
+                            ToolButton
+                            {
+                                id : materialcheckform_content_head
+                                anchors.centerIn: parent
+                                enabled: false                          // 不可点击
+                                display: AbstractButton.TextBesideIcon  // 文字在图标旁边
+
+                                icon.source: model.standardIcon
+                                icon.width: 45
+                                icon.height: 37
+
+                                text: model.standardType
+                                palette.buttonText: "#d7d7d2"
+                                font {
+                                    pixelSize: 30
+                                }
+                            }
+
+                            Text {
+                                id : materialcheckform_content_text
+                                width: parent.width;
+                                anchors.centerIn: parent
+                                font.pixelSize: 20
+                                color: "#d7d7d2"
+                                font.bold: true
+                                wrapMode: Text.WordWrap
+                                text: model.standardText
+                            }
+
+                            Component.onCompleted: {
+                                if (model.standardHead)
+                                {
+                                    materialcheckform_content_row.height = 100;
+                                    materialcheckform_content_head.visible = true;
+                                    materialcheckform_content_text.visible = false;
+                                }
+                                else
+                                {
+                                    materialcheckform_content_row.height =
+                                            materialcheckform_content_text.implicitHeight;
+                                    materialcheckform_content_head.visible = false;
+                                    materialcheckform_content_text.visible = true;
+                                }
+                            }
+                        }
+
+                    }
+                }
+            }
+        }
+    }
+
+    function slot_getMaterialCheckForm(data)
+    {
+        slot_postSaveForm(data);
+
+        strMaterialCheckFormGet = data;
+
+        materialcheckform_tableModel.clear();
+        materialcheckform_tableModel_standard.clear();
+
+        var jsonObjRoot = JSON.parse(data);
+        if (jsonObjRoot.code === 200)
+        {
+            var jsonObjData = jsonObjRoot.data;
+
+
+            // 物资检查列表
+            var jsonArrList = jsonObjData.list;
+            for (var i = 0; i < jsonArrList.length; ++i)
+            {
+                var jsonObjList = jsonArrList[i];
+
+                var materialCode = jsonObjList.materialsId;
+                var materialType = jsonObjList.materialsTypeName;
+                var materialIcon = jsonObjList.materialsTypeIcon;
+                var materialName = jsonObjList.materialsName;
+                var materialRfid = jsonObjList.materialsRfid;
+                var materialText = jsonObjList.measure;
+                materialRfid = (materialRfid === null ? "" : materialRfid);
+                materialText = (materialText === null ? "" : materialText);
+
+                var materialFlag = 0;
+
+                if(jsonObjList.status === "0")
+                {
+                    materialFlag = 1;
+                }
+                else if (jsonObjList.status === "1")
+                {
+                    if (jsonObjList.reason === "2")
+                    {
+                        materialFlag = 2;
+                    }
+                    else if (jsonObjList.reason === "1")
+                    {
+                        materialFlag = 3;
+                    }
+                }
+
+                materialcheckform_tableModel.append({
+                                                        materialFlag: materialFlag,
+                                                        materialCode: materialCode,
+                                                        materialType: materialType,
+                                                        materialIcon: materialIcon,
+                                                        materialName: materialName,
+                                                        materialRfid: materialRfid,
+                                                        materialText: materialText,
+                                                        materialJson: jsonObjList,
+                                                    });
+            }
+
+            // 物资检查标准
+            var jsonArrStandards = jsonObjData.standards;
+            for (var j = 0; j < jsonArrStandards.length; ++j)
+            {
+                var jsonObjStandard = jsonArrStandards[j];
+
+                var standardType = jsonObjStandard.materialsTypeName;
+                var standardIcon = jsonObjStandard.materialsTypeIcon;
+                var standardText = jsonObjStandard.checkStandard;
+
+                materialcheckform_tableModel_standard.append({
+                                                                 standardHead: true,
+                                                                 standardType: standardType,
+                                                                 standardIcon: standardIcon,
+                                                             });
+
+                materialcheckform_tableModel_standard.append({
+                                                                 standardHead: false,
+                                                                 standardText: standardText,
+                                                             });
+            }
+        }
+
+        build_model_view()
+        waitPromptBox.hide();
+    }
+
+
+    function build_model_view()
+    {
+        var iWait = 0;
+        var iNormal = 0;
+        var iExpire = 0;
+        var iDamage = 0;
+
+        for (var i = 0; i < materialcheckform_tableModel.count; i++)
+        {
+            var item = materialcheckform_tableModel.get(i);
+            switch (item.materialFlag)
+            {
+            case 0: iWait++; break;
+            case 1: iNormal++; break;
+            case 2: iExpire++; break;
+            case 3: iDamage++; break;
+            }
+
+        }
+
+        materialcheckform_text_wait_check.text = "待检查:" + iWait
+        materialcheckform_text_normal_check.text = "正常:" + iNormal
+        materialcheckform_text_expire_check.text = "过期:" + iExpire
+        materialcheckform_text_damage_check.text = "损坏:" + iDamage
+    }
+
+    function show_dialog()
+    {
+        var iWait = 0;
+
+        for (var i = 0; i < materialcheckform_tableModel.count; i++)
+        {
+            var item = materialcheckform_tableModel.get(i);
+            switch (item.materialFlag)
+            {
+            case 0: iWait++; break;
+
+            }
+
+        }
+
+        if (iWait > 0)
+        {
+            materialcheckform_text_dialog_prompt.text = "保存成功,还有" + iWait + "件物资待检查";
+            materialcheckform_dialog_confirm_prompt.open();
+        }
+        else
+        {
+            materialcheckform_text_dialog_prompt.text = "保存成功,没有物资待检查";
+            materialcheckform_dialog_confirm_prompt.open();
+        }
+    }
+
+    // 返回检查结果
+    function save_check_result()
+    {
+        var jsonObjRoot = {};
+
+        var jsonArrList = [];
+        for (var i = 0; i < materialcheckform_tableModel.count; i++)
+        {
+            var item = materialcheckform_tableModel.get(i);
+            var jsonObjList = item.materialJson;
+
+            if (item.materialFlag === 0)
+            {
+                jsonObjList["status"] = "";
+                jsonObjList["reason"] = "";
+            }
+            else if (item.materialFlag === 1)
+            {
+                jsonObjList["status"] = "0";
+                jsonObjList["reason"] = "";
+            }
+            else if (item.materialFlag === 2)
+            {
+                jsonObjList["status"] = "1";
+                jsonObjList["reason"] = "2";
+            }
+            else if (item.materialFlag === 3)
+            {
+                jsonObjList["status"] = "1";
+                jsonObjList["reason"] = "1";
+            }
+
+            jsonArrList.push(jsonObjList);
+        }
+
+        jsonObjRoot["list"] = jsonArrList;
+        var strJson = JSON.stringify(jsonObjRoot);
+
+        console.log(jsonObjRoot);
+
+        signal_postSaveForm(strJson);
+    }
+
+    function slot_postSaveForm(data)
+    {
+        var jsonObjRoot = JSON.parse(data);
+        if (jsonObjRoot.code === 200)
+        {
+            // materialcheckform_prompt_info.promptInfoTimeout = 3;
+            // materialcheckform_prompt_info.promptInfoText = jsonObjRoot.msg;
+            // materialcheckform_prompt_info.promptInfoIcon = "qrc:/png/error.png"
+            // materialcheckform_prompt_info.promptInfoColor = "#6600ff00"
+
+        }
+        else
+        {
+            materialcheckform_prompt_info.promptInfoTimeout = 3;
+            materialcheckform_prompt_info.promptInfoText = jsonObjRoot.msg;
+            materialcheckform_prompt_info.promptInfoIcon = "qrc:/png/error.png"
+            materialcheckform_prompt_info.promptInfoColor = "#66ea3a0e"
+        }
+
+    }
+}

+ 743 - 0
content/MaterialCheckPlan.qml

@@ -0,0 +1,743 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+import com.InteractiveTask 1.0
+
+Item {
+    id: materialcheckplan
+    x: 290
+    y: 130
+    width: 1600
+    height: 920
+
+    signal signal_getMaterialCheckPlan();
+    signal signal_postSubmit();
+
+    property int planId: 0
+    property string strMaterialCheckPlanGet: "";
+
+    property bool takebackstat : false
+    property bool opendoor : false
+
+    signal startReader();
+    signal signal_openLock();
+    signal signal_takebackstat(bool stat);
+
+    PromptInfo {
+        id:materialcheckplan_prompt_info
+    }
+
+    Connections {
+        target: materialcheckplan
+        onVisibleChanged: {
+            if (visible === true)
+            {
+                proThread.moveCursorTo(0, 0);
+            }
+
+            if (materialcheckplan.visible === true)
+            {
+                materialcheckplan_btn_submit.visible = false;
+                materialcheckplan_btn_proceed_check.visible = false;
+                materialcheckplan_btn_sign.visible = false;
+                materialcheckplan_btn_start_check.visible = false;
+                materialcheckplan_btn_return.visible = true;
+
+                materialcheckplan_rect_main.visible = false;
+
+                // signal_getMaterialCheckPlan();
+
+                materialCheckSign.imageData = "";
+
+                waitPromptBox.show();
+                var taskType = InteractiveTask.TypeHttpGet_getLastCheckPlanByCabinetCode;
+                interactiveCore.appendTask(
+                            taskType, null, (data) =>{
+                                // 解析返回结果
+                                var jsonObjRoot = JSON.parse(data);
+                                if (jsonObjRoot.code === 200)
+                                {
+                                    var jsonObjData = jsonObjRoot.data;
+
+                                    planId = jsonObjData.planId;
+
+                                    pConfig.setScurrentPlanId(parseInt(planId));
+
+                                    var planDate = jsonObjData.planDate;
+                                    var planStat = jsonObjData.status;
+                                    var strPlanStat = "未定义";
+
+                                    var signatureImg = jsonObjData.signatureImg;
+
+                                    if (planStat === "0")
+                                    {
+                                        strPlanStat = "待开始";
+                                        materialcheckplan_btn_submit.visible = false;
+                                        materialcheckplan_btn_proceed_check.visible = false;
+                                        materialcheckplan_btn_sign.visible = false;
+                                        materialcheckplan_btn_start_check.visible = true;
+                                        materialcheckplan_btn_return.visible = true;
+
+                                        materialcheckplan_rect_main.visible = true;
+                                        materialcheckplan_text_plan_title.visible = false;
+                                    }
+                                    else if (planStat === "2")
+                                    {
+                                        strPlanStat = "进行中";
+                                        materialcheckplan_btn_submit.visible = true;
+                                        materialcheckplan_btn_proceed_check.visible = true;
+                                        materialcheckplan_btn_sign.visible = true;
+                                        materialcheckplan_btn_start_check.visible = false;
+                                        materialcheckplan_btn_return.visible = true;
+
+                                        materialcheckplan_rect_main.visible = true;
+                                        materialcheckplan_text_plan_title.visible = false;
+                                    }
+                                    else if (planStat === "1")
+                                    {
+                                        strPlanStat = "已完成";
+                                        materialcheckplan_btn_submit.visible = false;
+                                        materialcheckplan_btn_proceed_check.visible = false;
+                                        materialcheckplan_btn_sign.visible = false;
+                                        materialcheckplan_btn_start_check.visible = false;
+                                        materialcheckplan_btn_return.visible = true;
+
+                                        materialcheckplan_rect_main.visible = false;
+                                        materialcheckplan_text_plan_title.visible = true;
+                                    }
+                                    else
+                                    {
+                                        materialcheckplan_btn_submit.visible = false;
+                                        materialcheckplan_btn_proceed_check.visible = false;
+                                        materialcheckplan_btn_sign.visible = false;
+                                        materialcheckplan_btn_start_check.visible = true;
+                                        materialcheckplan_btn_return.visible = true;
+
+                                        materialcheckplan_rect_main.visible = false;
+                                        materialcheckplan_text_plan_title.visible = false;
+                                    }
+
+
+                                    materialcheckplan_text_plan_date.text = "计划日期:" + planDate;
+                                    materialcheckplan_text_plan_stat.text = "计划状态:" + strPlanStat;
+
+
+                                    if (signatureImg === "" || signatureImg === null)
+                                    {
+                                        materialcheckplan_text_sign.visible = true;
+                                        materialcheckplan_image_sign.visible = false;
+                                        materialcheckplan_image_sign.source  = "";
+
+                                        materialCheckSign.imageData = "";
+                                    }
+                                    else
+                                    {
+                                        materialcheckplan_text_sign.visible = false;
+                                        materialcheckplan_image_sign.visible = true;
+                                        materialcheckplan_image_sign.source = signatureImg;
+
+                                        materialCheckSign.imageData = signatureImg;
+                                    }
+
+                                    var jsonArrList = jsonObjData.list;
+                                    for (var i = 0; i < jsonArrList.length; ++i)
+                                    {
+                                        var jsonObjList = jsonArrList[i];
+                                        var materialType = jsonObjList.materialsTypeName;
+                                        var materialIcon = jsonObjList.materialsTypeIcon;
+
+                                        var mainNumber = jsonObjList.allNumber;
+                                        var lendNumber = jsonObjList.loanNumber;
+                                        var waitNumber = jsonObjList.checkNumber;
+                                        var normalNumber = jsonObjList.normalNumber;
+                                        var expireNumber = jsonObjList.timeoutNumber;
+                                        var damageNumber = jsonObjList.badNumber;
+
+                                        materialcheckplan_tableModel.append({
+                                                                                materialType: materialType,
+                                                                                materialIcon: materialIcon,
+                                                                                mainNumber: mainNumber,
+                                                                                lendNumber: lendNumber,
+                                                                                waitNumber: waitNumber,
+                                                                                normalNumber: normalNumber,
+                                                                                expireNumber: expireNumber,
+                                                                                damageNumber: damageNumber,
+                                                                            });
+                                    }
+                                }
+                                else
+                                {
+                                    materialcheckplan_text_plan_date.text = "";
+                                    materialcheckplan_text_plan_stat.text = "";
+
+                                    // infoPromptBox.title("提示");
+                                    // infoPromptBox.message(jsonObjRoot.msg);
+                                    // infoPromptBox.button_clear();
+                                    // infoPromptBox.button_push("#055eb3", "确定", null, null);
+                                    // infoPromptBox.show();
+
+                                    materialcheckplan_btn_submit.visible = false;
+                                    materialcheckplan_btn_proceed_check.visible = false;
+                                    materialcheckplan_btn_sign.visible = false;
+                                    materialcheckplan_btn_start_check.visible = false;
+                                    materialcheckplan_btn_return.visible = true;
+
+                                    materialcheckplan_rect_main.visible = false;
+                                    materialcheckplan_text_plan_title.visible = true;
+                                }
+
+                                waitPromptBox.hide();
+                            });
+            }
+            else
+            {
+                materialcheckplan_tableModel.clear();
+                materialcheckplan_btn_submit.visible = false;
+                materialcheckplan_btn_proceed_check.visible = false;
+                materialcheckplan_btn_sign.visible = false;
+                materialcheckplan_btn_start_check.visible = true;
+                materialcheckplan_btn_return.visible = true;
+            }
+
+        }
+    }
+
+    ListModel {
+        id: materialcheckplan_tableModel
+    }
+
+
+    // 提交结果
+    Button {
+        id: materialcheckplan_btn_submit
+        x: 928
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#ff9900"
+            radius: 10
+        }
+        text: qsTr("提交结果")
+        font.pixelSize: 30
+        palette.buttonText: "white"
+        Connections {
+            target: materialcheckplan_btn_submit
+            onClicked: {
+                // materialcheckplan_dialog_submit.open();
+
+                infoPromptBox.title("操作确认");
+                infoPromptBox.message("确定要开始提交结果吗?");
+                infoPromptBox.button_clear();
+                infoPromptBox.button_push("red", "取消", null, null);
+                infoPromptBox.button_push(
+                            "#055eb3", "确定", ()=>{
+                                var taskType = InteractiveTask.TypeHttpPost_insertSubmitPlan;
+                                interactiveCore.appendTask(
+                                    taskType, null, (data) =>{
+                                        // 解析返回结果
+                                        var jsonObjRoot = JSON.parse(data);
+                                        if (jsonObjRoot.code === 200)
+                                        {
+                                            infoPromptBox.title("提交成功");
+                                            infoPromptBox.message("检查结果提交成功");
+                                            infoPromptBox.button_clear();
+                                            infoPromptBox.button_push("#055eb3", "确定", null, null);
+                                            infoPromptBox.show();
+
+                                            materialCheckPlan.visible = false;
+                                            materialSelmodel.visible = true;
+
+                                            proThread.slot_getMaterial();
+                                        }
+                                        else
+                                        {
+                                            infoPromptBox.title("提交失败");
+                                            infoPromptBox.message(jsonObjRoot.msg);
+                                            infoPromptBox.button_clear();
+                                            infoPromptBox.button_push("#055eb3", "确定", null, null);
+                                            infoPromptBox.show();
+                                        }
+                                    });
+
+                            }, null);
+                infoPromptBox.show();
+            }
+        }
+    }
+
+    // 继续检查
+    Button {
+        id: materialcheckplan_btn_proceed_check
+        x: 1168
+        y: 835
+        width: 192
+        height: 75
+        visible: false
+
+        background: Rectangle {
+            color: "#ff0000" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("继续检查")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialcheckplan_btn_proceed_check
+            onClicked: {
+                mainScreen.changeModel_text("物资检查表");
+                materialCheckForm.visible = true;
+                materialCheckPlan.visible = false;
+                mainScreen.resetLogin_timeout();
+
+                takebackstat = true;
+                pConfig.mtakebackstat = true;
+                pConfig.imaterworkstat = 4;
+                signal_openLock();
+            }
+        }
+    }
+
+    // 开始检查
+    Button {
+        id: materialcheckplan_btn_start_check
+        x: 1168
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#ff0000" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("开始检查")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialcheckplan_btn_start_check
+            onClicked: {
+                // materialcheckplan_dialog_confirm.open();
+
+                infoPromptBox.title("操作确认");
+                infoPromptBox.message("确定要开始检查物资吗?");
+                infoPromptBox.button_clear();
+                infoPromptBox.button_push("red", "取消", null, null);
+                infoPromptBox.button_push(
+                            "#055eb3", "确定", ()=>{
+                                var taskType = InteractiveTask.TypeHttpPost_startCheckPlan;
+                                interactiveCore.appendTask(
+                                    taskType, null, ()=>{
+                                        mainScreen.changeModel_text("物资检查表");
+                                        materialCheckForm.visible = true;
+                                        materialCheckPlan.visible = false;
+                                        mainScreen.resetLogin_timeout();
+
+                                        takebackstat = true;
+                                        pConfig.mtakebackstat = true;
+                                        pConfig.imaterworkstat = 4;
+                                        signal_openLock();
+                                    });
+                            }, null);
+                infoPromptBox.show();
+            }
+        }
+    }
+
+    // 返回按钮
+    Button {
+        id: materialcheckplan_btn_return
+        x: 1408
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#055eb3" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("返回")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialcheckplan_btn_return
+            onClicked: {
+                materialcheckplan.visible = false;
+                materialSelmodel.visible = true;
+                mainScreen.resetLogin_timeout();
+            }
+        }
+    }
+
+    // 标题区域
+    Text {
+        id: materialcheckplan_text_plan_title
+        x: 0
+        y: 0
+        width: 1600
+        height: 90
+        text: "当前无可执行的检查计划"
+        font.pixelSize: 30
+        color: "#d7d7d2"
+        horizontalAlignment: Text.AlignLeft
+        verticalAlignment: Text.AlignVCenter
+        leftPadding: 20  // 添加左边距使文本不紧贴边缘
+    }
+
+
+    // 主体区域
+    Rectangle {
+        id: materialcheckplan_rect_main
+        width: 1600
+        height: 800
+        color: "#272b7ae9"
+        radius: 20
+        clip: true
+
+        // 签名
+        Rectangle {
+            id: materialcheckplan_btn_sign
+            x: 1400
+            y: 25
+            width: 180
+            height: 50
+            color: "#008000"
+            radius: 10
+
+            Text
+            {
+                id: materialcheckplan_text_sign
+                // anchors.fill: parent
+                anchors.centerIn: parent
+                text: qsTr("签名")
+                font.pixelSize: 30
+                color: "#ffffff"
+            }
+
+            Image {
+                id: materialcheckplan_image_sign;
+                anchors.fill: parent
+            }
+
+            MouseArea
+            {
+                anchors.fill: parent
+
+                onClicked: {
+                    materialCheckPlan.visible = false;
+                    materialCheckSign.visible = true;
+                    mainScreen.resetLogin_timeout();
+                }
+            }
+        }
+
+
+
+        // 计划日期区域
+        Text {
+            id: materialcheckplan_text_plan_date
+            x: 0
+            y: 0
+            width: 1600
+            height: 90
+            text: "计划日期:"
+            font.pixelSize: 30
+            color: "#d7d7d2"
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            leftPadding: 20  // 添加左边距使文本不紧贴边缘
+        }
+
+        // 计划状态区域
+        Text {
+            id: materialcheckplan_text_plan_stat
+            x: 0
+            y: 0
+            width: 1600
+            height: 90
+            text: "计划状态:"
+            font.pixelSize: 30
+            color: "#d7d7d2"
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            leftPadding: 360  // 添加左边距使文本不紧贴边缘
+        }
+
+
+        // 表格区域
+        Rectangle {
+            x: 10
+            y: 90
+            width: 1580
+            height: 700
+            color: "#272b7ae9"
+            radius: 20
+
+
+            // 表格
+            Column {
+                anchors.fill: parent
+                spacing: 0
+
+                // 表头
+                Row {
+                    id: materialcheckplan_header
+                    width: parent.width
+                    height: 100
+                    spacing: 0
+
+                    Repeater {
+                        model: ["物资类型", "总数量", "借出数量", "待检数量", "正常数量", "过期数量", "损坏数量"]
+                        Rectangle {
+                            width: parent.width / 7
+                            height: parent.height
+                            color: "#33ffffff"
+                            border.color: "#47bfff"
+                            clip: true
+
+                            Text {
+                                anchors.centerIn: parent
+                                text: modelData
+                                font.pixelSize: 25
+                                color: "#d7d7d2"
+                                font.bold: true
+                            }
+                        }
+                    }
+                }
+
+                // 表格内容
+                ListView {
+                    width: parent.width
+                    height: parent.height - materialcheckplan_header.height
+                    clip: true
+                    model: materialcheckplan_tableModel
+
+                    delegate: Row {
+                        width: 1580
+                        height: 100
+                        spacing: 0
+
+                        property var rowData: [mainNumber, lendNumber, waitNumber, normalNumber, expireNumber, damageNumber]
+
+                        Rectangle {
+                            width: parent.width / 7
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+
+                            ToolButton
+                            {
+                                anchors.centerIn: parent
+                                enabled: false                          // 不可点击
+                                display: AbstractButton.TextBesideIcon  // 文字在图标旁边
+
+                                icon.source: model.materialIcon
+                                icon.width: 36
+                                icon.height: 30
+
+                                text: model.materialType
+                                palette.buttonText: "#d7d7d2"
+                                font {
+                                    pixelSize: 25
+
+                                }
+                            }
+                        }
+
+                        Repeater {
+                            model: 6
+                            Rectangle {
+                                width: parent.width / 7
+                                height: parent.height
+                                color: "#272b7ae9"
+                                border.color: "#47bfff"
+
+                                Text {
+                                    anchors.centerIn: parent
+                                    font.pixelSize: 25
+                                    color: "#d7d7d2"
+                                    text: parent.parent.rowData[index]
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    function slot_getMaterialCheckPlan(data)
+    {
+        slot_postSubmit(data);
+
+        strMaterialCheckPlanGet = data;
+
+        materialcheckplan_tableModel.clear();
+        materialCheckSign.imageData = "";
+
+        var jsonObjRoot = JSON.parse(data);
+        if (jsonObjRoot.code === 200)
+        {
+            var jsonObjData = jsonObjRoot.data;
+
+            planId = jsonObjData.planId;
+
+            pConfig.setScurrentPlanId(parseInt(planId));
+
+            var planDate = jsonObjData.planDate;
+            var planStat = jsonObjData.status;
+            var strPlanStat = "未定义";
+
+            var signatureImg = jsonObjData.signatureImg;
+
+            if (planStat === "0")
+            {
+                strPlanStat = "待开始";
+                materialcheckplan_btn_submit.visible = false;
+                materialcheckplan_btn_proceed_check.visible = false;
+                materialcheckplan_btn_sign.visible = false;
+                materialcheckplan_btn_start_check.visible = true;
+                materialcheckplan_btn_return.visible = true;
+            }
+            else if (planStat === "1")
+            {
+                strPlanStat = "已完成";
+                materialcheckplan_btn_submit.visible = false;
+                materialcheckplan_btn_proceed_check.visible = false;
+                materialcheckplan_btn_sign.visible = false;
+                materialcheckplan_btn_start_check.visible = false;
+                materialcheckplan_btn_return.visible = true;
+            }
+            else if (planStat === "2")
+            {
+                strPlanStat = "进行中";
+                materialcheckplan_btn_submit.visible = true;
+                materialcheckplan_btn_proceed_check.visible = true;
+                materialcheckplan_btn_sign.visible = true;
+                materialcheckplan_btn_start_check.visible = false;
+                materialcheckplan_btn_return.visible = true;
+            }else
+            {
+                materialcheckplan_btn_submit.visible = false;
+                materialcheckplan_btn_proceed_check.visible = false;
+                materialcheckplan_btn_sign.visible = false;
+                materialcheckplan_btn_start_check.visible = true;
+                materialcheckplan_btn_return.visible = true;
+            }
+
+
+            materialcheckplan_text_plan_date.text = "计划日期:" + planDate;
+            materialcheckplan_text_plan_stat.text = "计划状态:" + strPlanStat;
+
+
+            if (signatureImg === "" || signatureImg === null)
+            {
+                materialcheckplan_text_sign.visible = true;
+                materialcheckplan_image_sign.visible = false;
+                materialCheckSign.imageData = "";
+            }
+            else
+            {
+                materialcheckplan_text_sign.visible = false;
+                materialcheckplan_image_sign.visible = true;
+                materialcheckplan_image_sign.source = signatureImg;
+                materialCheckSign.imageData = signatureImg;
+            }
+
+            var jsonArrList = jsonObjData.list;
+            for (var i = 0; i < jsonArrList.length; ++i)
+            {
+                var jsonObjList = jsonArrList[i];
+                var materialType = jsonObjList.materialsTypeName;
+                var materialIcon = jsonObjList.materialsTypeIcon;
+
+                var mainNumber = jsonObjList.allNumber;
+                var lendNumber = jsonObjList.loanNumber;
+                var waitNumber = jsonObjList.checkNumber;
+                var normalNumber = jsonObjList.normalNumber;
+                var expireNumber = jsonObjList.timeoutNumber;
+                var damageNumber = jsonObjList.badNumber;
+
+                materialcheckplan_tableModel.append({
+                                                        materialType: materialType,
+                                                        materialIcon: materialIcon,
+                                                        mainNumber: mainNumber,
+                                                        lendNumber: lendNumber,
+                                                        waitNumber: waitNumber,
+                                                        normalNumber: normalNumber,
+                                                        expireNumber: expireNumber,
+                                                        damageNumber: damageNumber,
+                                                    });
+            }
+        }
+    }
+
+
+    function slot_postSubmit(data)
+    {
+        var jsonObjRoot = JSON.parse(data);
+        if (jsonObjRoot.code === 200)
+        {
+            // materialchecksign_prompt_info.promptInfoTimeout = 3;
+            // materialchecksign_prompt_info.promptInfoText = jsonObjRoot.msg;
+            // materialchecksign_prompt_info.promptInfoIcon = "qrc:/png/error.png"
+            // materialchecksign_prompt_info.promptInfoColor = "#6600ff00"
+        }
+        else
+        {
+            materialcheckplan_prompt_info.promptInfoTimeout = 3;
+            materialcheckplan_prompt_info.promptInfoText = jsonObjRoot.msg;
+            materialcheckplan_prompt_info.promptInfoIcon = "qrc:/png/error.png"
+            materialcheckplan_prompt_info.promptInfoColor = "#66ea3a0e"
+        }
+    }
+
+
+    function lockStat_callback(left, right)
+    {
+
+        if(left === false || right === false)
+        {
+            opendoor = true;
+            if(takebackstat === true)
+            {
+                signal_takebackstat(true);
+            }
+        }
+        else if(left === true && right === true)
+        {
+            opendoor = false;
+            if(takebackstat === true)
+            {
+                startReader();
+
+                takebackstat = false;
+                signal_takebackstat(false);
+
+                pConfig.smaterialStock = true;
+
+                // 开始读rfid
+                mainScreen.switchViewOffEx();
+                materialStocktaking.set_userinfo();
+                materialStocktaking.materiallistclear();
+                materialStocktaking.visible = true;
+
+                mainScreen.resetLogin_timeout();
+            }
+        }
+    }
+
+    function start_plan(isStart)
+    {
+        mainScreen.changeModel_text("物资检查表");
+        materialCheckForm.visible = true;
+        materialCheckPlan.visible = false;
+
+        materialcheckplan_dialog_confirm.close()
+
+
+        takebackstat = true;
+        pConfig.mtakebackstat = true;
+        pConfig.imaterworkstat = 4;
+        signal_openLock();
+    }
+}

+ 464 - 0
content/MaterialCheckSave.qml

@@ -0,0 +1,464 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Item {
+    id: materialchecksave
+    x: 290
+    y: 130
+    width: 1600
+    height: 920
+
+    property int planId: 0
+    property string strMaterialCheckPlanGet: ""
+
+    Connections {
+        target: materialchecksave
+        onVisibleChanged: {
+            if (materialchecksave.visible === true)
+            {
+                build_view();
+            }
+        }
+    }
+
+    ListModel {
+        id: materialchecksave_tableModel
+    }
+
+
+    // 确认操作弹出框
+    Dialog {
+        id: materialchecksave_dialog_confirm
+        title: "操作确认"
+        x: parent.width / 2 - width / 2
+        y: parent.height / 2 - height / 2
+        width: 600
+        height: 400
+        clip: true
+        modal: true
+
+        // 自定义背景(带圆角)
+        background: Rectangle {
+            color: "white"
+            clip: true
+        }
+        // 自定义标题栏
+        header: Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: 50 // 设置标题栏高度
+            color: "#ff3968e9" // 设置标题栏背景色
+            // 标题文本
+            Text {
+                x: 20
+                y: 0
+                width: 80
+                height: 50 // 设置标题栏高度
+                text: materialchecksave_dialog_confirm.title
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignLeft
+                verticalAlignment: Text.AlignVCenter
+                color: "white"
+            }
+        }
+
+        contentItem: Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: 200
+            color: "white"
+            Text {
+                width: parent.width
+                height: 200
+                text: "确定要提交检查结果吗?"
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+        }
+
+        // 自定义 DialogButtonBox
+        DialogButtonBox {
+            id: materialchecksave_buttonBox
+            x: 0
+            y: 250
+            width: parent.width
+            height: 100
+
+            // 自定义按钮
+            Button {
+                implicitWidth: 120
+                implicitHeight: 50
+                text: "确认"
+                background: Rectangle {
+                    color: "green"
+                    radius: 5
+                }
+                contentItem: Text {
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "white"
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                onClicked: {
+                    mainScreen.changeModel_text("物资检查表");
+
+                    submit_check_result();
+
+                    materialCheckPlan.visible = true;
+                    // materialCheckSave.visible = false;
+                    materialchecksave_dialog_confirm.close()
+                }
+            }
+
+            Button {
+                implicitWidth: 120
+                implicitHeight: 50
+                text: "取消"
+                background: Rectangle {
+                    color: "red"
+                    radius: 5
+                }
+                contentItem: Text {
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "white"
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                onClicked: {
+                    materialchecksave_dialog_confirm.reject()
+                }
+            }
+        }
+    }
+
+    // 提交结果
+    Button {
+        id: materialcheckform_btn_submit
+        x: 928
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#ff9900"
+            radius: 10
+        }
+        text: qsTr("提交结果")
+        font.pixelSize: 30
+        palette.buttonText: "white"
+        Connections {
+            target: materialcheckform_btn_submit
+            onClicked: {
+                materialchecksave_dialog_confirm.open();
+            }
+        }
+    }
+    // 继续检查
+    Button {
+        id: materialchecksave_btn_proceed_check
+        x: 1168
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#ff0000" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("继续检查")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialchecksave_btn_proceed_check
+            onClicked: {
+                // materialCheckSave.visible = false;
+                materialCheckForm.visible = true;
+                mainScreen.resetLogin_timeout();
+            }
+        }
+    }
+
+    // 返回按钮
+    Button {
+        id: materialchecksave_btn_return
+        x: 1408
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#055eb3"
+            radius: 10
+        }
+        text: qsTr("返回")
+        font.pixelSize: 30
+        palette.buttonText: "white"
+        Connections {
+            target: button_return_instructions
+            onClicked: {
+                // materialCheckSave.visible = false;
+                materialSelmodel.visible = true;
+                mainScreen.resetLogin_timeout();
+            }
+        }
+    }
+
+    // 主体区域
+    Rectangle {
+        id: materialchecksave_rect_main
+        width: 1600
+        height: 800
+        color: "#272b7ae9"
+        radius: 20
+        clip: true
+
+        // 签名
+        Rectangle {
+            id: materialchecksave_btn_sign
+            x: 1400
+            y: 25
+            width: 180
+            height: 50
+            color: "#008000"
+            radius: 10
+
+            Text
+            {
+                id: materialchecksave_text_sign
+                // anchors.fill: parent
+                anchors.centerIn: parent
+                text: qsTr("签名")
+                font.pixelSize: 30
+                color: "#ffffff"
+            }
+
+            Image {
+                id: materialchecksave_image_sign;
+                anchors.fill: parent
+            }
+
+            MouseArea
+            {
+                anchors.fill: parent
+
+                onClicked: {
+                    // materialCheckSave.visible = false;
+                    materialCheckSign.visible = true;
+                    mainScreen.resetLogin_timeout();
+                }
+            }
+        }
+
+        // 计划日期区域
+        Text {
+            id: materialchecksave_text_plan_date
+            x: 0
+            y: 0
+            width: 1600
+            height: 90
+            text: "计划日期:"
+            font.pixelSize: 30
+            color: "#d7d7d2"
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            leftPadding: 20  // 添加左边距使文本不紧贴边缘
+        }
+
+        // 计划状态区域
+        Text {
+            id: materialchecksave_text_plan_stat
+            x: 0
+            y: 0
+            width: 1600
+            height: 90
+            text: "计划状态:"
+            font.pixelSize: 30
+            color: "#d7d7d2"
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            leftPadding: 360  // 添加左边距使文本不紧贴边缘
+        }
+
+
+        // 表格区域
+        Rectangle {
+            x: 10
+            y: 90
+            width: 1580
+            height: 700
+            color: "#272b7ae9"
+            radius: 20
+
+
+            // 表格
+            Column {
+                anchors.fill: parent
+                spacing: 0
+
+                // 表头
+                Row {
+                    id: materialchecksave_header
+                    width: parent.width
+                    height: 100
+                    spacing: 0
+
+                    Repeater {
+                        model: ["物资类型", "总数量", "借出数量", "待检数量", "正常数量", "过期数量", "损坏数量"]
+                        Rectangle {
+                            width: parent.width / 7
+                            height: parent.height
+                            color: "#33ffffff"
+                            border.color: "#47bfff"
+                            clip: true
+
+                            Text {
+                                anchors.centerIn: parent
+                                text: modelData
+                                font.pixelSize: 25
+                                color: "#d7d7d2"
+                                font.bold: true
+                            }
+                        }
+                    }
+                }
+
+                // 表格内容
+                ListView {
+                    width: parent.width
+                    height: parent.height - materialchecksave_header.height
+                    clip: true
+                    model: materialchecksave_tableModel
+
+                    delegate: Row {
+                        width: 1580
+                        height: 100
+                        spacing: 0
+
+                        property var rowData: [mainNumber, lendNumber, waitNumber, normalNumber, expireNumber, damageNumber]
+
+                        Rectangle {
+                            width: parent.width / 7
+                            height: parent.height
+                            color: "#272b7ae9"
+                            border.color: "#47bfff"
+
+                            ToolButton
+                            {
+                                anchors.centerIn: parent
+                                enabled: false                          // 不可点击
+                                display: AbstractButton.TextBesideIcon  // 文字在图标旁边
+
+                                icon.source: model.materialIcon
+                                icon.width: 36
+                                icon.height: 30
+
+                                text: model.materialType
+                                palette.buttonText: "#d7d7d2"
+                                font {
+                                    pixelSize: 25
+
+                                }
+                            }
+                        }
+
+                        Repeater {
+                            model: 6
+                            Rectangle {
+                                width: parent.width / 7
+                                height: parent.height
+                                color: "#272b7ae9"
+                                border.color: "#47bfff"
+
+                                Text {
+                                    anchors.centerIn: parent
+                                    font.pixelSize: 25
+                                    color: "#d7d7d2"
+                                    text: parent.parent.rowData[index]
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    function build_view()
+    {
+
+        materialchecksave_tableModel.clear();
+
+        var jsonObjRoot = JSON.parse(materialCheckPlan.strMaterialCheckPlanGet);
+        if (jsonObjRoot.code === 200)
+        {
+            var jsonObjData = jsonObjRoot.data;
+
+            planId = jsonObjData.planId;
+
+            var planDate = jsonObjData.planDate;
+            var planStat = jsonObjData.status;
+
+            planStat = (planStat === "0" ? "进行中" : planStat === "1" ? "已完成" : "未定义");
+
+            materialchecksave_text_plan_date.text = "计划日期:" + planDate;
+            materialchecksave_text_plan_stat.text = "计划状态:" + planStat;
+
+            var jsonArrList = jsonObjData.list;
+            for (var i = 0; i < jsonArrList.length; ++i)
+            {
+                var jsonObjList = jsonArrList[i];
+                var materialType = jsonObjList.materialsTypeName;
+                var materialIcon = jsonObjList.materialsTypeIcon;
+
+                var mainNumber = jsonObjList.allNumber;
+                var lendNumber = jsonObjList.badNumber;
+                var waitNumber = jsonObjList.checkNumber;
+                var normalNumber = jsonObjList.loanNumber;
+                var expireNumber = jsonObjList.normalNumber;
+                var damageNumber = jsonObjList.timeoutNumber;
+
+                materialchecksave_tableModel.append({
+                                                        materialType: materialType,
+                                                        materialIcon: materialIcon,
+                                                        mainNumber: mainNumber,
+                                                        lendNumber: lendNumber,
+                                                        waitNumber: waitNumber,
+                                                        normalNumber: normalNumber,
+                                                        expireNumber: expireNumber,
+                                                        damageNumber: damageNumber,
+                                                    });
+            }
+        }
+    }
+
+    function image_show(fileUrl)
+    {
+        if (fileUrl === "")
+        {
+            materialchecksave_text_sign.visible = true;
+            materialchecksave_image_sign.visible = false;
+        }
+        else
+        {
+            materialchecksave_text_sign.visible = false;
+            materialchecksave_image_sign.visible = true;
+            materialchecksave_image_sign.source = fileUrl;
+        }
+    }
+
+    function submit_check_result()
+    {
+        // var jsonObjRoot;
+        // jsonObjRoot["list"] = materialCheckForm.ret_check_result();
+        // var strJson = JSON.stringify(jsonObjRoot);
+
+        // console.log(jsonObjRoot);
+
+    }
+}
+http://192.168.0.10:9191/dev-api/iscs/hardware/material-api/getLastCheckPlanByCabinetCode?cabinetCode=CABINET_006
+
+http://192.168.0.10:9191/dev-api/iscs/hardware/material-api/getCheckMaterialsByCabinetCode?cabinetCode=CABINET_006&planId=85

+ 391 - 0
content/MaterialCheckSign.qml

@@ -0,0 +1,391 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Item {
+    id: materialchecksign
+    x: 290
+    y: 130
+    width: 1600
+    height: 920
+
+    property string imagePath : "image/png";
+    property string imageData : "";
+
+
+    signal signal_postCheckSign(int planId, string path);
+
+    PromptInfo
+    {
+        id: materialchecksign_prompt_info;
+    }
+
+
+    onVisibleChanged: {
+        if (materialchecksign.visible === true)
+        {
+            proThread.moveCursorTo(0, 0);
+
+            // 如果图片Base64为空字符
+            if (imageData === "") {
+                materialchecksign_btn_reset.visible = false;
+                materialchecksign_btn_confirm.visible = true;
+                materialchecksign_btn_purge.visible = true;
+                materialchecksign_mouseArea.enabled = true;
+                materialchecksign_image_sign.source = imageData;
+            }
+            else
+            {
+                materialchecksign_btn_reset.visible = true;
+                materialchecksign_btn_confirm.visible = false;
+                materialchecksign_btn_purge.visible = false;
+                materialchecksign_mouseArea.enabled = false;
+                materialchecksign_image_sign.source = imageData;
+            }
+        }
+        else
+        {
+            materialchecksign_canvas.clear();
+        }
+    }
+
+
+    // 确认操作弹出框
+    Dialog {
+        id: materialchecksign_dialog_confirm
+        title: "操作确认"
+        x: parent.width / 2 - width / 2
+        y: parent.height / 2 - height / 2
+        width: 600
+        height: 400
+        clip: true
+        modal: true
+
+        // 自定义背景(带圆角)
+        background: Rectangle {
+            color: "white"
+            clip: true
+        }
+        // 自定义标题栏
+        header: Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: 50 // 设置标题栏高度
+            color: "#ff3968e9" // 设置标题栏背景色
+            // 标题文本
+            Text {
+                x: 20
+                y: 0
+                width: 80
+                height: 50 // 设置标题栏高度
+                text: materialchecksign_dialog_confirm.title
+                font.pixelSize: 20
+                horizontalAlignment: Text.AlignLeft
+                verticalAlignment: Text.AlignVCenter
+                color: "white"
+            }
+        }
+
+        contentItem: Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: 200
+            color: "white"
+            Text {
+                width: parent.width
+                height: 200
+                text: "确定要保存签名吗?"
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+        }
+
+        // 自定义 DialogButtonBox
+        DialogButtonBox {
+            id: materialcheckplan_buttonBox
+            x: 0
+            y: 250
+            width: parent.width
+            height: 100
+
+            // 自定义按钮
+            Button {
+                implicitWidth: 120
+                implicitHeight: 50
+                text: "确认"
+                background: Rectangle {
+                    color: "green"
+                    radius: 5
+                }
+                contentItem: Text {
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "white"
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                onClicked: {
+                    var dataUrl = materialchecksign_canvas.toDataURL(imagePath);
+                    signal_postCheckSign(materialCheckPlan.planId, dataUrl);  // 检查签名
+                    materialchecksign_dialog_confirm.close()
+                }
+            }
+
+            Button {
+                implicitWidth: 120
+                implicitHeight: 50
+                text: "取消"
+                background: Rectangle {
+                    color: "red"
+                    radius: 5
+                }
+                contentItem: Text {
+                    text: parent.text
+                    font.pixelSize: 30
+                    color: "white"
+                    horizontalAlignment: Text.AlignHCenter
+                    verticalAlignment: Text.AlignVCenter
+                }
+                onClicked: {
+                    materialchecksign_dialog_confirm.reject()
+                }
+            }
+        }
+    }
+
+
+    // 保存
+    Button {
+        id: materialchecksign_btn_confirm
+        x: 928
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#ff9900"
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("保存")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialchecksign_btn_confirm
+            onClicked: {
+                if (materialchecksign_canvas.pathPoints.length === 0)
+                {
+                }
+                else
+                {
+                    materialchecksign_dialog_confirm.open();
+                }
+            }
+        }
+    }
+
+
+    // 重新签名
+    Button {
+        id: materialchecksign_btn_reset
+        x: 1168
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#ff0000"
+            radius: 10
+        }
+        text: qsTr("重新签名")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialchecksign_btn_reset
+            onClicked: {
+                materialchecksign_btn_reset.visible = false;
+                materialchecksign_btn_confirm.visible = true;
+                materialchecksign_btn_purge.visible = true;
+                materialchecksign_mouseArea.enabled = true;
+                materialchecksign_image_sign.source = "";
+            }
+        }
+    }
+
+    // 清除
+    Button {
+        id: materialchecksign_btn_purge
+        x: 1168
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#ff0000"
+            radius: 10
+        }
+        text: qsTr("清除")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialchecksign_btn_purge
+            onClicked: {
+                materialchecksign_canvas.clear();
+            }
+        }
+    }
+
+    // 返回按钮
+    Button {
+        id: materialchecksign_btn_return
+        x: 1408
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#055eb3"
+            radius: 10
+        }
+        text: qsTr("返回")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: materialchecksign_btn_return
+            onClicked: {
+                materialCheckSign.visible = false;
+                materialCheckPlan.visible = true;
+            }
+        }
+    }
+
+
+    // 主体区域
+    Rectangle {
+        id: materialchecksign_rect_main
+        width: 1600
+        height: 800
+        color: "#1affffff"
+        radius: 20
+        clip: true
+
+
+
+        Canvas {
+            anchors.fill: parent
+
+            onPaint: {
+                var ctx = getContext("2d")
+                ctx.strokeStyle = "#ffffff"
+                ctx.lineWidth = 3
+                ctx.beginPath()
+                ctx.moveTo(160, 20)
+                ctx.lineTo(20, 20)
+                ctx.lineTo(20, 160)
+                ctx.stroke()
+
+                ctx.beginPath()
+                ctx.moveTo(160, 780)
+                ctx.lineTo(20, 780)
+                ctx.lineTo(20, 640)
+                ctx.stroke()
+
+                ctx.beginPath()
+                ctx.moveTo(1580, 160)
+                ctx.lineTo(1580, 20)
+                ctx.lineTo(1440, 20)
+                ctx.stroke()
+
+                ctx.beginPath()
+                ctx.moveTo(1580, 640)
+                ctx.lineTo(1580, 780)
+                ctx.lineTo(1440, 780)
+                ctx.stroke()
+            }
+        }
+
+
+        Canvas {
+            id: materialchecksign_canvas
+            anchors.fill: parent
+            antialiasing: true
+
+            // 存储绘制路径的点
+            property var pathPoints: []  // QList<QList<QPointF>>
+
+            // 开始绘制
+            onPaint: {
+                var ctx = getContext("2d")
+                ctx.clearRect(0, 0, width, height)  // 清空画布
+                ctx.lineWidth = 10
+                ctx.strokeStyle = "#ffffff"
+
+                for (var j = 0; j < pathPoints.length; ++j)
+                {
+                    if (pathPoints[j].length > 0) {
+                        ctx.beginPath()
+                        ctx.moveTo(pathPoints[j][0].x, pathPoints[j][0].y)
+
+                        for (var i = 0; i < pathPoints[j].length; i++) {
+                            ctx.lineTo(pathPoints[j][i].x, pathPoints[j][i].y)
+                        }
+
+                        ctx.stroke()
+                    }
+                }
+            }
+
+            // 清空签名
+            function clear() {
+                pathPoints = []
+                requestPaint()
+            }
+        }
+
+        // MouseArea 用于监听鼠标事件
+        MouseArea {
+            id: materialchecksign_mouseArea
+            anchors.fill: parent
+            onPressed: {
+                var index = materialchecksign_canvas.pathPoints.length;
+                materialchecksign_canvas.pathPoints[index] = [];
+                materialchecksign_canvas.pathPoints[index].push(Qt.point(mouse.x, mouse.y));
+                materialchecksign_canvas.requestPaint();
+            }
+            onPositionChanged: {
+                if (pressed) {
+                    var index = materialchecksign_canvas.pathPoints.length - 1;
+                    materialchecksign_canvas.pathPoints[index].push(Qt.point(mouse.x, mouse.y));
+                    materialchecksign_canvas.requestPaint();
+                }
+            }
+        }
+
+
+        Image {
+            id: materialchecksign_image_sign;
+            anchors.fill: parent
+        }
+    }
+
+    function slot_postCheckSign(data)
+    {
+        var jsonObjRoot = JSON.parse(data);
+        if (jsonObjRoot.code === 200)
+        {
+            // materialchecksign_prompt_info.promptInfoTimeout = 3;
+            // materialchecksign_prompt_info.promptInfoText = jsonObjRoot.msg;
+            // materialchecksign_prompt_info.promptInfoIcon = "qrc:/png/error.png"
+            // materialchecksign_prompt_info.promptInfoColor = "#6600ff00"
+
+
+            materialCheckSign.visible = false;
+            materialCheckPlan.visible = true;
+        }
+        else
+        {
+            materialchecksign_prompt_info.promptInfoTimeout = 3;
+            materialchecksign_prompt_info.promptInfoText = jsonObjRoot.msg;
+            materialchecksign_prompt_info.promptInfoIcon = "qrc:/png/error.png"
+            materialchecksign_prompt_info.promptInfoColor = "#66ea3a0e"
+        }
+    }
+}

+ 488 - 0
content/MaterialCheckUpdate.qml

@@ -0,0 +1,488 @@
+import QtQuick 2.15
+import QtQuick.Controls 2.15
+
+Item {
+    id: materialcheckupdate
+    x: 290
+    y: 130
+    width: 1600
+    height: 920
+
+    property string takeDatetime : "2025-03-02 13:16:25"
+    property string takeName : "张天乐"
+
+    property string backDatetime : "2025-03-02 13:16:25"
+    property string backName : "张天乐"
+
+    property bool takestock : true
+    property string takestocknotice : "物资盘点中,请耐心等待......"
+    property int takestockviewcount : 1
+    property int stockcountdown : 5
+    property string stockcountdownstr : "倒计时:99秒"
+
+    ListModel {
+        id: materialcheckupdate_append_listModel
+
+    }
+
+    ListModel {
+        id: materialcheckupdate_remove_listModel
+
+    }
+
+    Rectangle {
+        width: 1600
+        height: 800
+        color: "#272b7ae9"
+        radius: 20
+        clip: true
+        Rectangle {
+            width: 1600
+            height: 100 // 减去顶部圆角矩形的高度
+            radius: 20
+            clip: true
+            color: "#8f2b7ae9"
+
+            Text {
+                id: materialcheckupdate_text_title
+                x: 50
+                y: 25
+                width: 500
+                height: 50
+                visible: true
+                text: "本次物资取还记录如下:"
+                font.pixelSize: 30
+                horizontalAlignment: Text.AlignLeft
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+                color: "#ffffff"
+            }
+        }
+
+        Rectangle {
+            x: 0
+            y: 100
+            width: parent.width
+            height: (parent.height - 100) / 2
+            color: "#002b7ae9"
+
+            Text {
+                id: materialcheckupdate_text_takeDateTime
+                x: 50
+                y: 0
+                width: 260
+                height: 50
+                visible: true
+                text: takeDatetime
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignLeft
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+                color: "#ffffff"
+            }
+
+            Text {
+                id: materialcheckupdate_text_takeName
+                x: 310
+                y: 0
+                width: 120
+                height: 50
+                visible: true
+                text: takeName
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+                font.underline: true
+                font.bold: true
+                color: "#ffffff"
+            }
+
+            Text {
+                id: materialcheckupdate_text_takeText
+                x: 430
+                y: 0
+                width: 180
+                height: 50
+                visible: true
+                text: "领取以下物资:"
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+                color: "#ffffff"
+            }
+
+            GridView {
+                x: 25
+                y: 50
+                width: parent.width - 50
+                height: parent.height - 50
+                cellWidth: 250  // 每个单元格的宽度,这里是平均分配宽度给5列
+                cellHeight: 350       // 每个单元格的高度
+                model: materialcheckupdate_append_listModel
+                delegate: Rectangle{
+                    width: 250
+                    height: 350
+                    color: "#00ffffff"
+
+                    Rectangle {
+                        x: 25
+                        y: 25
+                        width: 200
+                        height: 300
+                        color: "#00ffffff"
+
+                        Image {
+                            x: 25
+                            y: 25
+                            width: 150
+                            height: 150
+                            visible: true
+                            source: model.png
+                            fillMode: Image.PreserveAspectFit
+                        }
+
+                        Text {
+                            x: 0
+                            y: 185
+                            width: parent.width
+                            height: 50
+                            visible: true
+                            text: model.name
+                            font.pixelSize: 30
+                            horizontalAlignment: Text.AlignHCenter
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#ffffff"
+                        }
+
+                        Text {
+                            x: 0
+                            y: 250
+                            width: parent.width
+                            height: 25
+                            visible: true
+                            text: model.rfid
+                            font.pixelSize: 12
+                            horizontalAlignment: Text.AlignHCenter
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#ffffff"
+                        }
+                    }
+
+                }
+            }
+        }
+
+        Rectangle {
+            x: 0
+            y: (parent.height - 100) / 2 + 100
+            width: parent.width
+            height: (parent.height - 100) / 2
+            color: "#002b7ae9"
+
+            Text {
+                id: materialcheckupdate_text_backDateTime
+                x: 50
+                y: 0
+                width: 260
+                height: 50
+                visible: true
+                text: backDatetime
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignLeft
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+                color: "#ffffff"
+            }
+
+            Text {
+                id: materialcheckupdate_text_backName
+                x: 310
+                y: 0
+                width: 120
+                height: 50
+                visible: true
+                text: backName
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+                font.underline: true
+                font.bold: true
+                color: "#ffffff"
+            }
+
+            Text {
+                id: materialcheckupdate_text_backText
+                x: 430
+                y: 0
+                width: 180
+                height: 50
+                visible: true
+                text: "归还以下物资:"
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+                color: "#ffffff"
+            }
+
+            GridView {
+                x: 25
+                y: 50
+                width: parent.width - 50
+                height: parent.height - 50
+                cellWidth: 250  // 每个单元格的宽度,这里是平均分配宽度给5列
+                cellHeight: 350       // 每个单元格的高度
+                model: materialcheckupdate_remove_listModel
+                delegate: Rectangle{
+                    width: 250
+                    height: 350
+                    color: "#00ffffff"
+
+                    Rectangle {
+                        x: 25
+                        y: 25
+                        width: 200
+                        height: 300
+                        color: "#00ffffff"
+
+                        Image {
+                            x: 25
+                            y: 25
+                            width: 150
+                            height: 150
+                            visible: true
+                            source: model.png
+                            fillMode: Image.PreserveAspectFit
+                        }
+
+                        Text {
+                            x: 0
+                            y: 185
+                            width: parent.width
+                            height: 50
+                            visible: true
+                            text: model.name
+                            font.pixelSize: 30
+                            horizontalAlignment: Text.AlignHCenter
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#ffffff"
+                        }
+
+                        Text {
+                            x: 0
+                            y: 250
+                            width: parent.width
+                            height: 25
+                            visible: true
+                            text: model.rfid
+                            font.pixelSize: 12
+                            horizontalAlignment: Text.AlignHCenter
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#ffffff"
+                        }
+                    }
+
+                }
+            }
+        }
+
+        Canvas {
+            anchors.fill: parent
+            onPaint: {
+                var ctx = getContext("2d");
+                ctx.lineWidth = 5; // 设置线的宽度
+                ctx.strokeStyle = "skyblue"; // 设置线的颜色为白色
+                ctx.beginPath();
+                ctx.moveTo(5, (parent.height - 100) / 2 + 100); // 直线的起点
+                ctx.lineTo(parent.width - 5, (parent.height - 100) / 2 + 100); // 直线的终点
+                ctx.stroke(); // 绘制直线
+            }
+        }
+    }
+
+    Button {
+        id: button_return
+        x: 1408
+        y: 835
+        width: 192
+        height: 75
+        background: Rectangle {
+            color: "#055eb3" // 设置背景为透明
+            radius: 10 // 可选,设置圆角
+        }
+        text: qsTr("确定")
+        font.pixelSize: 30
+        palette.buttonText: "white"  // 设置字体颜色为绿色
+        Connections {
+            target: button_return
+            onClicked: {
+                materialcheckupdate.visible = false;
+                mainScreen.switchViewOnEx();
+            }
+        }
+    }
+
+    Rectangle {
+        id: matrailcheckupdate_rect_takeback
+        x: 0
+        y: 823
+        width: 300
+        height: 75 // 减去顶部圆角矩形的高度
+        color: "#00ffffff"
+        visible: true
+
+        Image {
+            x: 0
+            y: 0
+            width: 75
+            height: 75
+            visible: true
+            source: "qrc:/png/takeback.png"
+            fillMode: Image.PreserveAspectFit
+        }
+
+        Text {
+            x: 80
+            y: 0
+            width: 389
+            height: 75
+            visible: true
+            text: takestocknotice
+            font.pixelSize: 30
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            color: "#ffffff"
+        }
+    }
+
+    Text {
+        x: 514
+        y: 823
+        width: 389
+        height: 75
+        visible: true
+        font.pixelSize: 30
+        horizontalAlignment: Text.AlignHCenter
+        verticalAlignment: Text.AlignVCenter
+        color: "#ffffff"
+        text: stockcountdownstr
+    }
+
+    Timer {
+        interval: 100
+        running: true
+        repeat: true
+        onTriggered: {
+            if(takestock == true)
+            {
+                materialcheckupdate_text_title.text = "请等待物资盘点结束";
+                materialcheckupdate_text_takeDateTime.visible = false;
+                materialcheckupdate_text_takeName.visible = false;
+                materialcheckupdate_text_takeText.visible = false;
+                materialcheckupdate_text_backDateTime.visible = false;
+                materialcheckupdate_text_backName.visible = false;
+                materialcheckupdate_text_backText.visible = false;
+
+                if(takestockviewcount > 0)
+                {
+                    takestockviewcount--;
+                }
+                else{
+                    takestockviewcount = 5;
+                    if(matrailcheckupdate_rect_takeback.visible === true)
+                    {
+                        matrailcheckupdate_rect_takeback.visible = false;
+                    }
+                    else{
+                        matrailcheckupdate_rect_takeback.visible = true;
+                    }
+                }
+
+                if(stockcountdown > 0)
+                {
+                    stockcountdown--;
+                    stockcountdownstr = "倒计时:" + parseInt(stockcountdown / 10) +"秒"
+                }
+                else{
+
+                }
+            }
+            else{
+                materialcheckupdate_text_title.text = "以下物资发生了变动:";
+
+                if (pConfig.stakeMaterialList.length === 0)
+                {
+                    materialcheckupdate_text_takeDateTime.visible = true;
+                    materialcheckupdate_text_takeName.visible = false;
+                    materialcheckupdate_text_takeText.visible = false;
+                    materialcheckupdate_text_takeDateTime.text = "本次没有发现物资被拿出";
+                }
+                else
+                {
+                    materialcheckupdate_text_takeDateTime.visible = true;
+                    materialcheckupdate_text_takeName.visible = true;
+                    materialcheckupdate_text_takeText.visible = true;
+                    materialcheckupdate_text_takeDateTime.text = takeDatetime;
+                    materialcheckupdate_text_takeText.text = "拿出以下物资:";
+                }
+
+                if (pConfig.sbackMaterialList.length === 0)
+                {
+                    materialcheckupdate_text_backDateTime.visible = true;
+                    materialcheckupdate_text_backName.visible = false;
+                    materialcheckupdate_text_backText.visible = false;
+                    materialcheckupdate_text_backDateTime.text = "本次没有发现物资被放入";
+                }
+                else
+                {
+                    materialcheckupdate_text_backDateTime.visible = true;
+                    materialcheckupdate_text_backName.visible = true;
+                    materialcheckupdate_text_backText.visible = true;
+                    materialcheckupdate_text_backDateTime.text = backDatetime;
+                    materialcheckupdate_text_backText.text = "放入以下物资:";
+                }
+
+                matrailcheckupdate_rect_takeback.visible = true;
+            }
+        }
+    }
+
+    function set_userinfo()
+    {
+        takeDatetime = Qt.formatDateTime(new Date(), "yyyy-MM-dd hh:mm:ss");
+        backDatetime = takeDatetime;
+        takeName = pConfig.susername;
+        backName = pConfig.susername;
+        stockcountdown = pConfig.srfidWorkTime / 100;
+        takestocknotice = "物资盘点中,请耐心等待......";
+        stockcountdownstr = "倒计时:" + parseInt(stockcountdown / 10) +"秒"
+        takestock = true;
+    }
+
+    function slot_updatetakebackMaterial()
+    {
+        takestock = false;
+        takestocknotice = "物资盘点完成!";
+        stockcountdownstr = "";
+        matrailcheckupdate_rect_takeback.visible = true;
+        var takelist = pConfig.stakeMaterialList;
+        var backlist = pConfig.sbackMaterialList;
+        var materialname = pConfig.smaterialNameList;
+        var materialpicture = pConfig.smaterialPictureList;
+
+        for (var i = 0; i < takelist.length; i++) {
+            materialcheckupdate_append_listModel.append({png:materialpicture[takelist[i]], name: materialname[takelist[i]], rfid: takelist[i]});
+        }
+
+        for (var j = 0; j < backlist.length; j++) {
+            materialcheckupdate_remove_listModel.append({png:materialpicture[backlist[j]], name: materialname[backlist[j]], rfid: backlist[j]});
+        }
+    }
+
+    function materiallistclear()
+    {
+        materialcheckupdate_append_listModel.clear();
+        materialcheckupdate_remove_listModel.clear();
+    }
+}

+ 89 - 0
content/MaterialDialog.qml

@@ -0,0 +1,89 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Window {
+    id: materialdialog
+    minimumWidth: 600
+    maximumWidth: 600
+    minimumHeight: 400
+    maximumHeight: 400
+    flags: Qt.Dialog | Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
+    modality: Qt.ApplicationModal
+    title: ""
+    color: "white"
+    visible: false
+
+    Rectangle {
+        x: 0
+        y: 0
+        width: parent.width
+        height: 50 // 设置标题栏高度
+        color: "#ff3968e9" // 设置标题栏背景色
+
+        Text {
+            x: 20
+            y: 0
+            width: 80
+            height: 50 // 设置标题栏高度
+            text: "超时提醒"
+            font.pixelSize: 25
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            color: "white"
+        }
+    }
+    Rectangle {
+        x: 0
+        y: 50
+        width: parent.width
+        height: 200
+        color: "white"
+        Text {
+            id: materialdialog_text
+            width: parent.width
+            height: 200
+            text: ""
+            font.pixelSize: 30
+            horizontalAlignment: Text.AlignHCenter
+            verticalAlignment: Text.AlignVCenter
+
+            color: "#000000"
+        }
+    }
+
+    DialogButtonBox {
+        id: materialdialog_buttonBox
+        x: 0
+        y: 300
+        width: parent.width
+        height: 100
+
+        // 自定义按钮
+        Button {
+            implicitWidth: 120
+            implicitHeight: 50
+            text: "关闭"
+            background: Rectangle {
+                color: "#055eb3"
+                radius: 5
+            }
+            contentItem: Text {
+                text: parent.text
+                font.pixelSize: 30
+                color: "white"
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+            onClicked: {
+                materialdialog.hide();
+            }
+        }
+    }
+
+
+    function timeout_refresh(epoch)
+    {
+        materialdialog_text.text = "物资柜超时未关闭" + epoch + "秒";
+    }
+}

+ 142 - 0
content/MaterialDialogBack.qml

@@ -0,0 +1,142 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Window {
+    id: materialdialogback
+    minimumWidth: 600
+    maximumWidth: 600
+    minimumHeight: 400
+    maximumHeight: 400
+    flags: Qt.Dialog | Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
+    modality: Qt.ApplicationModal
+    title: ""
+    color: "white"
+    visible: false
+
+    ListModel {
+        id: materialdialogback_materialbacklistModel
+        // ListElement { rfid: "0000000000" }
+        // ListElement { rfid: "11111111" }
+        // ListElement { rfid: "11111111" }
+        // ListElement { rfid: "11111111" }
+
+    }
+
+    Rectangle {
+        x: 0
+        y: 0
+        width: parent.width
+        height: 50 // 设置标题栏高度
+        color: "#ffff0000" // 设置标题栏背景色
+
+        Text {
+            x: 20
+            y: 0
+            width: 80
+            height: 50 // 设置标题栏高度
+            text: "以下不属于该柜子的物资被放入"
+            font.pixelSize: 25
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            color: "white"
+        }
+    }
+
+    Rectangle {
+        x: 0
+        y: 50
+        width: parent.width
+        height: 250
+        color: "white"
+
+        Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: parent.height
+            color: "#002b7ae9"
+
+            GridView {
+                x: 25
+                y: 0
+                width: parent.width - 50
+                height: parent.height
+                cellWidth: 550
+                cellHeight: 50
+                model: materialdialogback_materialbacklistModel
+                delegate: Rectangle{
+                    width: 550
+                    height: 50
+                    color: "#00ffffff"
+
+                    Rectangle {
+                        x: 0
+                        y: 0
+                        width: 550
+                        height: 50
+                        color: "#00ffffff"
+
+                        Text {
+                            x: 0
+                            y: 0
+                            width: parent.width
+                            height: 50
+                            visible: true
+                            text: model.rfid
+                            font.pixelSize: 20
+                            horizontalAlignment: Text.AlignLeft
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#000000"
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    DialogButtonBox {
+        id: materialdialogback_buttonBox
+        x: 0
+        y: 300
+        width: parent.width
+        height: 100
+
+        // 自定义按钮
+        Button {
+            implicitWidth: 120
+            implicitHeight: 50
+            text: "关闭"
+            background: Rectangle {
+                color: "#055eb3"
+                radius: 5
+            }
+            contentItem: Text {
+                text: parent.text
+                font.pixelSize: 30
+                color: "white"
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+            onClicked: {
+                materialdialogback.hide();
+            }
+        }
+    }
+
+    function slot_backRefresh()
+    {
+        mainScreen.refreshListMode();
+        materialdialogback_materialbacklistModel.clear();
+        var takelist = pConfig.sbackElseMaterialList;
+        var materialname = pConfig.smaterialNameList;
+        var materialpicture = pConfig.smaterialPictureList;
+
+        for (var i = 0; i < takelist.length; i++) {
+            materialdialogback_materialbacklistModel.append({png:materialpicture[takelist[i]], name: materialname[takelist[i]], rfid: "RFID:" + takelist[i]});
+        }
+
+        materialdialogback.visible = true;
+    }
+
+}

+ 239 - 0
content/MaterialDialogMisplace.qml

@@ -0,0 +1,239 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Window {
+    id: materialdialogmisplace
+    minimumWidth: 800
+    maximumWidth: 800
+    minimumHeight: 600
+    maximumHeight: 600
+    flags: Qt.Dialog | Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
+    modality: Qt.ApplicationModal
+    title: ""
+    color: "white"
+    visible: true
+
+    ListModel {
+        id: materialdialogmisplace_materialtakelistModel
+        // ListElement { rfid: "0000000000" }
+        // ListElement { rfid: "11111111" }
+        // ListElement { rfid: "11111111" }
+        // ListElement { rfid: "11111111" }
+
+    }
+
+    ListModel {
+        id: materialdialogmisplace_materialbacklistModel
+        ListElement { rfid: "0000000000" }
+        ListElement { rfid: "222222222" }
+        ListElement { rfid: "3333333" }
+        ListElement { rfid: "44444444" }
+    }
+
+    Rectangle {
+        x: 0
+        y: 0
+        width: parent.width
+        height: 50 // 设置标题栏高度
+        color: "#ff3968e9" // 设置标题栏背景色
+
+        Text {
+            x: 20
+            y: 0
+            width: 80
+            height: 50 // 设置标题栏高度
+            text: "物资错放提醒"
+            font.pixelSize: 25
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            color: "white"
+        }
+    }
+
+    Rectangle {
+        x: 0
+        y: 75
+        width: parent.width
+        height: 400
+        color: "white"
+
+        Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: (parent.height) / 2
+            color: "#002b7ae9"
+
+            Text {
+                x: 50
+                y: 0
+                width: 260
+                height: 50
+                visible: true
+                text: "不是本柜子的物资"
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignLeft
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+                color: "#000000"
+            }
+
+            GridView {
+                x: 25
+                y: 50
+                width: parent.width - 50
+                height: parent.height - 50
+                cellWidth: 250  // 每个单元格的宽度,这里是平均分配宽度给5列
+                cellHeight: 350       // 每个单元格的高度
+                model: materialdialogmisplace_materialtakelistModel
+                delegate: Rectangle{
+                    width: 250
+                    height: 50
+                    color: "#00ffffff"
+
+                    Rectangle {
+                        x: 0
+                        y: 0
+                        width: 250
+                        height: 50
+                        color: "#00ffffff"
+
+                        Text {
+                            x: 0
+                            y: 0
+                            width: parent.width
+                            height: 50
+                            visible: true
+                            text: model.rfid
+                            font.pixelSize: 12
+                            horizontalAlignment: Text.AlignHCenter
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#000000"
+                        }
+                    }
+                }
+            }
+        }
+
+        Rectangle {
+            x: 0
+            y: (parent.height) / 2
+            width: parent.width
+            height: (parent.height) / 2
+            color: "#002b7ae9"
+
+            Text {
+                x: 50
+                y: 0
+                width: 260
+                height: 50
+                visible: true
+                text: "不是本柜子的物资"
+                font.pixelSize: 25
+                horizontalAlignment: Text.AlignLeft
+                verticalAlignment: Text.AlignVCenter
+                font.bold: true
+                color: "#000000"
+            }
+
+            GridView {
+                x: 25
+                y: 50
+                width: parent.width - 50
+                height: parent.height - 50
+                cellWidth: 250  // 每个单元格的宽度,这里是平均分配宽度给5列
+                cellHeight: 350       // 每个单元格的高度
+                model: materialdialogmisplace_materialbacklistModel
+                delegate: Rectangle{
+                    width: 250
+                    height: 50
+                    color: "#00ffffff"
+
+                    Rectangle {
+                        x: 0
+                        y: 0
+                        width: 250
+                        height: 50
+                        color: "#00ffffff"
+
+                        Text {
+                            x: 0
+                            y: 0
+                            width: parent.width
+                            height: 50
+                            visible: true
+                            text: model.rfid
+                            font.pixelSize: 12
+                            horizontalAlignment: Text.AlignHCenter
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#000000"
+                        }
+                    }
+                }
+            }
+        }
+
+        Canvas {
+            anchors.fill: parent
+            onPaint: {
+                var ctx = getContext("2d");
+                ctx.lineWidth = 5; // 设置线的宽度
+                ctx.strokeStyle = "skyblue"; // 设置线的颜色为白色
+                ctx.beginPath();
+                ctx.moveTo(5, (parent.height) / 2 ); // 直线的起点
+                ctx.lineTo(parent.width - 5, (parent.height) / 2); // 直线的终点
+                ctx.stroke(); // 绘制直线
+            }
+        }
+
+    }
+
+    DialogButtonBox {
+        id: materialdialogmisplace_buttonBox
+        x: 0
+        y: 500
+        width: parent.width
+        height: 100
+
+        // 自定义按钮
+        Button {
+            implicitWidth: 120
+            implicitHeight: 50
+            text: "关闭"
+            background: Rectangle {
+                color: "green"
+                radius: 5
+            }
+            contentItem: Text {
+                text: parent.text
+                font.pixelSize: 30
+                color: "white"
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+            onClicked: {
+                materialdialogmisplace.hide();
+            }
+        }
+    }
+
+    function slot_misplaceRefresh()
+    {
+        materialdialogmisplace_materialtakelistModel.clear();
+        materialdialogmisplace_materialbacklistModel.clear()
+        var takelist = pConfig.stakeElseMaterialList;
+        var backlist = pConfig.sbackElseMaterialList;
+        var materialname = pConfig.smaterialNameList;
+        var materialpicture = pConfig.smaterialPictureList;
+
+        for (var i = 0; i < takelist.length; i++) {
+            materialdialogmisplace_materialtakelistModel.append({png:materialpicture[takelist[i]], name: materialname[takelist[i]], rfid: takelist[i]});
+        }
+
+        for (var j = 0; j < backlist.length; j++) {
+            materialdialogmisplace_materialbacklistModel.append({png:materialpicture[backlist[j]], name: materialname[backlist[j]], rfid: backlist[j]});
+        }
+    }
+
+}

+ 142 - 0
content/MaterialDialogTake.qml

@@ -0,0 +1,142 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+
+Window {
+    id: materialdialogtack
+    minimumWidth: 600
+    maximumWidth: 600
+    minimumHeight: 400
+    maximumHeight: 400
+    flags: Qt.Dialog | Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint
+    modality: Qt.ApplicationModal
+    title: ""
+    color: "white"
+    visible: false
+
+    ListModel {
+        id: materialdialogtack_materialtakelistModel
+        // ListElement { rfid: "0000000000" }
+        // ListElement { rfid: "11111111" }
+        // ListElement { rfid: "11111111" }
+        // ListElement { rfid: "11111111" }
+
+    }
+
+    Rectangle {
+        x: 0
+        y: 0
+        width: parent.width
+        height: 50 // 设置标题栏高度
+        color: "#ff3968e9" // 设置标题栏背景色
+
+        Text {
+            x: 20
+            y: 0
+            width: 80
+            height: 50 // 设置标题栏高度
+            text: "以下不属于该柜子的物资被拿出"
+            font.pixelSize: 25
+            horizontalAlignment: Text.AlignLeft
+            verticalAlignment: Text.AlignVCenter
+            color: "white"
+        }
+    }
+
+    Rectangle {
+        x: 0
+        y: 50
+        width: parent.width
+        height: 250
+        color: "white"
+
+        Rectangle {
+            x: 0
+            y: 0
+            width: parent.width
+            height: parent.height
+            color: "#002b7ae9"
+
+            GridView {
+                x: 25
+                y: 0
+                width: parent.width - 50
+                height: parent.height
+                cellWidth: 550
+                cellHeight: 50
+                model: materialdialogtack_materialtakelistModel
+                delegate: Rectangle{
+                    width: 550
+                    height: 50
+                    color: "#00ffffff"
+
+                    Rectangle {
+                        x: 0
+                        y: 0
+                        width: 550
+                        height: 50
+                        color: "#00ffffff"
+
+                        Text {
+                            x: 0
+                            y: 0
+                            width: parent.width
+                            height: 50
+                            visible: true
+                            text: model.rfid
+                            font.pixelSize: 20
+                            horizontalAlignment: Text.AlignLeft
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#000000"
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    DialogButtonBox {
+        id: materialdialogtack_buttonBox
+        x: 0
+        y: 300
+        width: parent.width
+        height: 100
+
+        // 自定义按钮
+        Button {
+            implicitWidth: 120
+            implicitHeight: 50
+            text: "关闭"
+            background: Rectangle {
+                color: "#055eb3"
+                radius: 5
+            }
+            contentItem: Text {
+                text: parent.text
+                font.pixelSize: 30
+                color: "white"
+                horizontalAlignment: Text.AlignHCenter
+                verticalAlignment: Text.AlignVCenter
+            }
+            onClicked: {
+                materialdialogtack.hide();
+            }
+        }
+    }
+
+    function slot_takeRefresh()
+    {
+        mainScreen.refreshListMode();
+        materialdialogtack_materialtakelistModel.clear();
+        var takelist = pConfig.stakeElseMaterialList;
+        var materialname = pConfig.smaterialNameList;
+        var materialpicture = pConfig.smaterialPictureList;
+
+        for (var i = 0; i < takelist.length; i++) {
+            materialdialogtack_materialtakelistModel.append({png:materialpicture[takelist[i]], name: materialname[takelist[i]], rfid: "RFID:" + takelist[i]});
+        }
+
+        materialdialogtack.visible = true;
+    }
+
+}

+ 437 - 0
content/MaterialException.qml

@@ -0,0 +1,437 @@
+import QtQuick
+import QtQuick.Layouts
+import QtQuick.Controls
+
+// import com.InteractiveCore 1.0
+import com.InteractiveTask 1.0
+
+Item {
+    id: materialexception
+    x: 290
+    y: 130
+
+    width: 1600
+    height: 920
+
+    property bool takebackstat : false
+    property bool opendoor : false
+
+    signal startReader();
+    signal signal_openLock();
+    signal signal_takebackstat(bool stat);
+
+    Connections {
+        target: materialexception
+        onVisibleChanged: {
+            // 刷新数据缓存
+            if (materialexception.visible === true )
+            {
+                proThread.moveCursorTo(0, 0);
+
+                materialexception_exce_misplace.visible = false;
+                // refreshListMode();
+                // materialexception_delayTimer.start();
+
+                waitPromptBox.show();
+                var taskType = InteractiveTask.TypeMaterialExceptionRefreshListModel;
+                interactiveCore.appendTask(
+                            taskType, "", ()=>{
+                                refreshInterface();
+
+                                waitPromptBox.hide();
+                            });
+            }
+        }
+    }
+
+    // Timer {
+    //     id: materialexception_delayTimer
+    //     interval: 500 // 1秒 = 1000毫秒
+    //     repeat: false  // 只触发一次
+    //     onTriggered: {
+    //         refreshListMode();
+    //     }
+    // }
+
+    // 主体区域
+    Rectangle {
+        id: materialexception_main
+        x: 0
+        y: 0
+        width: parent.width;
+        height: parent.height * 0.88
+        color: "#272b7ae9"
+        radius: 10
+
+        Row {
+            x: 20
+            y: 20
+            width: parent.width - 40
+            height: parent.height * 0.88 - 40
+
+            Rectangle {
+                id: materialexception_exce_noerror
+                width: parent.width
+                height: 64
+                color: "#00ffffff"
+                radius: 10
+                visible: false
+
+                Rectangle {
+                    x: 5
+                    y: 5
+                    width: 250
+                    height: 52
+                    color: "#ffffff"
+                    radius: 20
+                    Text {
+                        anchors.centerIn: parent
+                        font.pixelSize: 25
+                        // font.bold: true
+                        color: "#ff0000"
+                        text: "当前无异常发生"
+                    }
+                }
+
+            }
+
+            Rectangle {
+                id: materialexception_exce_misplace
+                width: parent.width
+                height: 400
+                color: "#1a3782"
+                radius: 10
+                visible: false
+
+                Rectangle {
+                    x: 5
+                    y: 5
+                    width: 250
+                    height: 52
+                    color: "#ffffff"
+                    radius: 20
+                    Text {
+                        anchors.centerIn: parent
+                        font.pixelSize: 25
+                        // font.bold: true
+                        color: "#ff0000"
+                        text: "异常类型:物资错放"
+                    }
+                }
+
+                Rectangle {
+                    x: 5
+                    y: 60
+                    width: 412
+                    height: 50
+                    color: "#1a3782"
+                    Text {
+                        horizontalAlignment: Text.AlignLeft
+                        verticalAlignment: Text.AlignVCenter
+                        anchors.fill: parent
+                        font.pixelSize: 20
+                        color: "#ffffff"
+                        text: "以下物资不属于该柜子,请取出!"
+                    }
+                }
+
+                GridView {
+                    x: 25
+                    y: 100
+                    width: parent.width - 50
+                    height: parent.height - 120
+                    cellWidth: 250
+                    cellHeight: 350
+                    model: materialexception_modelMaterialException
+                    delegate: Rectangle{
+                        width: 250
+                        height: 350
+                        color: "#00ffffff"
+
+                        Image {
+                            anchors.horizontalCenter: parent.horizontalCenter;
+                            y: 25
+                            width: 150
+                            height: 150
+                            visible: true
+                            source: model.materialsTypePicture
+                            fillMode: Image.PreserveAspectFit
+                        }
+
+                        Text {
+                            x: 0
+                            y: 185
+                            width: parent.width
+                            height: 50
+                            visible: true
+                            text: model.materialsName
+                            font.pixelSize: 30
+                            horizontalAlignment: Text.AlignHCenter
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#ffffff"
+                        }
+
+                        Text {
+                            x: 0
+                            y: 250
+                            width: parent.width
+                            height: 25
+                            visible: true
+                            text: model.materialsRfid
+                            font.pixelSize: 12
+                            horizontalAlignment: Text.AlignHCenter
+                            verticalAlignment: Text.AlignVCenter
+                            color: "#ffffff"
+                        }
+
+                        Rectangle {
+                            x: 25
+                            y: 125
+                            width: 150
+                            height: 50
+                            color: {
+                                if (model.status === "0") return "#00ff00";    // 正常 - 绿色
+                                if (model.status === "1") return "#ff0000";    // 损坏 - 红色
+                                if (model.status === "2") return "#ff9900";    // 过期 - 橙色
+                                if (model.status === "3") return "#ff9900";    // 放错柜子 - 橙色
+                                return "gray";                                 // 默认颜色
+                            }
+                            visible: {
+                                return false;
+                                // return model.status !== "0";
+                            }
+                            Text {
+                                anchors.centerIn: parent
+                                // text: "待还"
+                                text:{
+                                    if (model.status === "0") return "正常";
+                                    if (model.status === "1") return "损坏";
+                                    if (model.status === "2") return "过期";
+                                    if (model.status === "3") return "放错柜子";
+                                    return "未知状态"; // 默认值
+                                }
+                                font.pixelSize: 30
+                                horizontalAlignment: Text.AlignHCenter
+                                verticalAlignment: Text.AlignVCenter
+                                color: "#ffffff"
+                            }
+                        }
+                    }
+                }
+            }
+
+
+            Rectangle {
+                id: materialexception_exce_timeout
+
+                width: parent.width
+                height: 52
+                color: "#1a3782"
+                radius: 10
+                visible:  false
+
+                Rectangle {
+                    x: 5
+                    y: 5
+                    width: 250
+                    height: 52
+                    color: "#ffffff"
+                    radius: 20
+                    Text {
+                        anchors.centerIn: parent
+                        font.pixelSize: 25
+                        // font.bold: true
+                        color: "#ff0000"
+                        text: "异常类型:超时未关锁"
+                    }
+                }
+            }
+
+
+        }
+    }
+
+
+    // 状态栏
+    Rectangle {
+        id: materialexception_stat
+        x: 0
+        y: parent.height * 0.88
+        width: parent.width;
+        height: parent.height * 0.12
+        color: "#00ffffff"
+        radius: 10
+
+
+        // 左侧布局
+        Row {
+            anchors.left: parent.left  // 右对齐
+            spacing: 10
+
+            // 异常上报按钮
+            Button {
+                id: materialexception_btn_open
+                y: 25
+                width: 192
+                height: 75
+                background: Rectangle {
+                    color: "#ff0000"
+                    radius: 10
+                }
+                text: qsTr("异常上报")
+                font.pixelSize: 30
+                palette.buttonText: "white"
+                Connections {
+                    target: materialexception_btn_open
+                    onClicked: {
+                        materialExceptionReport.visible = true;
+                        materialexception.visible = false;
+                    }
+                }
+            }
+        }
+
+        // 右侧布局
+        Row {
+            anchors.right: parent.right  // 右对齐
+            spacing: 10
+
+            // 开柜按钮
+            Button {
+                id: materialexception_btn_cabinet
+                y: 25
+                width: 192
+                height: 75
+                background: Rectangle {
+                    color: "#ff0000"
+                    radius: 10
+                }
+                text: qsTr("开柜")
+                font.pixelSize: 30
+                palette.buttonText: "white"
+                Connections {
+                    target: materialexception_btn_cabinet
+                    onClicked: {
+                        takebackstat = true;
+                        pConfig.mtakebackstat = true;
+
+                        pConfig.imaterworkstat = 3;
+                        signal_openLock();
+                    }
+                }
+            }
+
+        }
+    }
+
+    Rectangle {
+        id: materialexception_rect_autoreplace
+        x: 250
+        y: 823
+        width: 500
+        height: 75 // 减去顶部圆角矩形的高度
+        color: "#00ffffff"
+        visible: false
+
+        Image {
+            x: 0
+            y: 0
+            width: 75
+            height: 75
+            visible: true
+            source: "qrc:/png/takeback.png"
+            fillMode: Image.PreserveAspectFit
+        }
+
+        Text {
+            x: 200
+            y: 0
+            width: 220
+            height: 75
+            visible: true
+            text: "等待取出不属于该柜子的物资......"
+            font.pixelSize: 30
+            horizontalAlignment: Text.AlignHCenter
+            verticalAlignment: Text.AlignVCenter
+            color: "#ffffff"
+        }
+    }
+
+
+    function lockStat_callback(left, right)
+    {
+        if (pConfig.imaterworkstat === 3)
+        {
+            if(left === false || right === false)
+            {
+                // materialreplace_btn_head_openLock.visible = false;  // 柜子开时,开柜按钮隐藏
+                materialexception_rect_autoreplace.visible = true;
+
+                // materialexception_btn_open.visible = false;
+                materialexception_btn_cabinet.enabled = false;
+
+                opendoor = true;
+                if(takebackstat === true)
+                {
+                    signal_takebackstat(true);
+                }
+            }
+            else if(left === true && right === true)
+            {
+                materialexception_rect_autoreplace.visible = false;
+
+                // materialexception_btn_open.visible = true;
+                materialexception_btn_cabinet.enabled = true;
+
+                opendoor = false;
+                if(takebackstat === true)
+                {
+                    startReader();
+
+                    takebackstat = false;
+                    signal_takebackstat(false);
+
+                    pConfig.smaterialStock = true;
+
+                    // 开始读rfid
+                    // materialexception.visible = false;
+                    mainScreen.switchViewOffEx();
+                    materialStocktaking.set_userinfo();
+                    materialStocktaking.materiallistclear();
+                    materialStocktaking.visible = true;
+
+                    // materialreplace_rect_autoreplace.visible = false;
+
+                    mainScreen.resetLogin_timeout();
+                }
+            }
+        }
+
+    }
+
+
+    // 刷新model列表
+    function refreshListMode()
+    {
+        var taskType = InteractiveTask.TypeMaterialExceptionRefreshListModel;
+        interactiveCore.appendTask(taskType, "", refreshInterface);
+    }
+    // 刷新界面显示
+    function refreshInterface()
+    {
+        if (materialexception_modelMaterialException.count() > 0)
+        {
+            materialexception_exce_misplace.visible = true;
+            materialexception_btn_cabinet.visible = true;
+            materialexception_exce_noerror.visible = false;
+        }
+        else
+        {
+            materialexception_exce_misplace.visible = false;
+            materialexception_btn_cabinet.visible = false;
+            materialexception_exce_noerror.visible = true;
+        }
+
+        materialexception_exce_timeout.visible = pConfig.blocktimeout;
+    }
+}

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio