2 次代碼提交 42529c1c63 ... 6a9f6c5158

作者 SHA1 備註 提交日期
  zhudongyong 6a9f6c5158 综合 - 字符串对比报告优化、显示对照文件、显示结果文件功能优化 1 年之前
  zhudongyong 4e99a505e1 字符对比 - 字符对比算法优化 1 年之前
共有 18 個文件被更改,包括 869 次插入139 次删除
  1. 48 20
      KdanAutoTest/KdanAuto.xcodeproj/project.pbxproj
  2. 二進制
      KdanAutoTest/KdanAuto.xcodeproj/project.xcworkspace/xcuserdata/zhudongyong.xcuserdatad/UserInterfaceState.xcuserstate
  3. 0 32
      KdanAutoTest/KdanAuto.xcodeproj/xcuserdata/zhudongyong.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist
  4. 0 6
      KdanAutoTest/KdanAuto/Class/AdvanceSettingViewController/AdvanceSettingPropertyRules.plist
  5. 0 23
      KdanAutoTest/KdanAuto/Class/AutoTestCase/StringAutoBackTest.swift
  6. 2 2
      KdanAutoTest/KdanAuto/Class/AutoTestCase/StringAutoCompareTest.swift
  7. 155 45
      KdanAutoTest/KdanAuto/Class/AutoTestCase/StringAutoTest.swift
  8. 0 0
      KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareView/CompareViewController.swift
  9. 0 0
      KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareView/CompareViewController.xib
  10. 0 0
      KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareView/ImageCompareCellView.swift
  11. 0 0
      KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareView/ImageCompareCellView.xib
  12. 127 0
      KdanAutoTest/KdanAuto/Class/CompareViewController/StringCompareView/StringCompareCellView.swift
  13. 83 0
      KdanAutoTest/KdanAuto/Class/CompareViewController/StringCompareView/StringCompareCellView.xib
  14. 296 0
      KdanAutoTest/KdanAuto/Class/CompareViewController/StringCompareView/StringCompareViewController.swift
  15. 129 0
      KdanAutoTest/KdanAuto/Class/CompareViewController/StringCompareView/StringCompareViewController.xib
  16. 11 4
      KdanAutoTest/KdanAuto/Class/Norrmal/AutoTestAdvanceSettingView.swift
  17. 17 6
      KdanAutoTest/KdanAuto/Class/Norrmal/Cell/TestCaseCellView.swift
  18. 1 1
      KdanAutoTest/KdanAuto/ViewController.swift

+ 48 - 20
KdanAutoTest/KdanAuto.xcodeproj/project.pbxproj

@@ -71,15 +71,19 @@
 		24A6FF4B2930939D00B34F2E /* TextColorAutoTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A6FF4A2930939D00B34F2E /* TextColorAutoTest.swift */; };
 		24A6FF4F2930A1E100B34F2E /* FontAutoTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A6FF4E2930A1E100B34F2E /* FontAutoTest.swift */; };
 		24A6FF512930AC4D00B34F2E /* AutoTestAdvanceSettingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24A6FF502930AC4D00B34F2E /* AutoTestAdvanceSettingView.swift */; };
-		24AE7B4D298BD98300462BD3 /* CompareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24AE7B4C298BD98300462BD3 /* CompareViewController.swift */; };
-		24CA2337298FD6BE00038E10 /* ImageCompareCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24CA2335298FD6BE00038E10 /* ImageCompareCellView.swift */; };
-		24CA2338298FD6BE00038E10 /* ImageCompareCellView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24CA2336298FD6BE00038E10 /* ImageCompareCellView.xib */; };
 		24CA233A298FEED300038E10 /* FileInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24CA2339298FEED300038E10 /* FileInfo.swift */; };
-		24CA233C298FF0F800038E10 /* CompareViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24CA233B298FF0F800038E10 /* CompareViewController.xib */; };
 		24CB61CA2994FA0800C5085F /* TestDegreeManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24CB61C92994FA0800C5085F /* TestDegreeManager.swift */; };
 		24D70000292B6FD100DAB5EE /* SettingViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24D7FFFF292B6FD100DAB5EE /* SettingViewController.xib */; };
 		24D70009292D14DA00DAB5EE /* AutoTestProtocal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24D70008292D14DA00DAB5EE /* AutoTestProtocal.swift */; };
 		24D7000B292D16BB00DAB5EE /* StringAutoTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24D7000A292D16BB00DAB5EE /* StringAutoTest.swift */; };
+		24D7803729FA61BF002F78C1 /* ImageCompareCellView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24D7803329FA61BF002F78C1 /* ImageCompareCellView.xib */; };
+		24D7803829FA61BF002F78C1 /* CompareViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24D7803429FA61BF002F78C1 /* CompareViewController.xib */; };
+		24D7803929FA61BF002F78C1 /* ImageCompareCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24D7803529FA61BF002F78C1 /* ImageCompareCellView.swift */; };
+		24D7803A29FA61BF002F78C1 /* CompareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24D7803629FA61BF002F78C1 /* CompareViewController.swift */; };
+		24D7804029FA62A9002F78C1 /* StringCompareCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24D7803C29FA62A8002F78C1 /* StringCompareCellView.swift */; };
+		24D7804129FA62A9002F78C1 /* StringCompareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24D7803D29FA62A8002F78C1 /* StringCompareViewController.swift */; };
+		24D7804229FA62A9002F78C1 /* StringCompareViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24D7803E29FA62A8002F78C1 /* StringCompareViewController.xib */; };
+		24D7804329FA62A9002F78C1 /* StringCompareCellView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 24D7803F29FA62A9002F78C1 /* StringCompareCellView.xib */; };
 		24D7FF9B29261A6400DAB5EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24D7FF9A29261A6400DAB5EE /* AppDelegate.swift */; };
 		24D7FF9D29261A6400DAB5EE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24D7FF9C29261A6400DAB5EE /* ViewController.swift */; };
 		24D7FF9F29261A6600DAB5EE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 24D7FF9E29261A6600DAB5EE /* Assets.xcassets */; };
@@ -108,7 +112,6 @@
 		24DCE8B529506CDE004EBA35 /* AutoTestProperty.plist in Resources */ = {isa = PBXBuildFile; fileRef = 24DCE8B429506CDE004EBA35 /* AutoTestProperty.plist */; };
 		24DCE8BB29518FD3004EBA35 /* ProcessThumbnal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 240509B62943479800B501B2 /* ProcessThumbnal.swift */; };
 		24E3165D29DC35A20009E358 /* UpdateSDK.sh in Resources */ = {isa = PBXBuildFile; fileRef = 24E3165C29DC35A20009E358 /* UpdateSDK.sh */; };
-		24E8AE3B29F6A4A900988963 /* StringAutoBackTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24E8AE3A29F6A4A900988963 /* StringAutoBackTest.swift */; };
 		24FE3FF329BAF9B8004F4DD4 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 24FE3FF229BAF9B8004F4DD4 /* CoreImage.framework */; };
 /* End PBXBuildFile section */
 
@@ -229,15 +232,19 @@
 		24A6FF4A2930939D00B34F2E /* TextColorAutoTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextColorAutoTest.swift; sourceTree = "<group>"; };
 		24A6FF4E2930A1E100B34F2E /* FontAutoTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontAutoTest.swift; sourceTree = "<group>"; };
 		24A6FF502930AC4D00B34F2E /* AutoTestAdvanceSettingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoTestAdvanceSettingView.swift; sourceTree = "<group>"; };
-		24AE7B4C298BD98300462BD3 /* CompareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompareViewController.swift; sourceTree = "<group>"; };
-		24CA2335298FD6BE00038E10 /* ImageCompareCellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCompareCellView.swift; sourceTree = "<group>"; };
-		24CA2336298FD6BE00038E10 /* ImageCompareCellView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ImageCompareCellView.xib; sourceTree = "<group>"; };
 		24CA2339298FEED300038E10 /* FileInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileInfo.swift; sourceTree = "<group>"; };
-		24CA233B298FF0F800038E10 /* CompareViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CompareViewController.xib; sourceTree = "<group>"; };
 		24CB61C92994FA0800C5085F /* TestDegreeManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestDegreeManager.swift; sourceTree = "<group>"; };
 		24D70001292B71FB00DAB5EE /* KdanAutoDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = KdanAutoDebug.entitlements; sourceTree = "<group>"; };
 		24D70008292D14DA00DAB5EE /* AutoTestProtocal.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoTestProtocal.swift; sourceTree = "<group>"; };
 		24D7000A292D16BB00DAB5EE /* StringAutoTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringAutoTest.swift; sourceTree = "<group>"; };
+		24D7803329FA61BF002F78C1 /* ImageCompareCellView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ImageCompareCellView.xib; sourceTree = "<group>"; };
+		24D7803429FA61BF002F78C1 /* CompareViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = CompareViewController.xib; sourceTree = "<group>"; };
+		24D7803529FA61BF002F78C1 /* ImageCompareCellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageCompareCellView.swift; sourceTree = "<group>"; };
+		24D7803629FA61BF002F78C1 /* CompareViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CompareViewController.swift; sourceTree = "<group>"; };
+		24D7803C29FA62A8002F78C1 /* StringCompareCellView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringCompareCellView.swift; sourceTree = "<group>"; };
+		24D7803D29FA62A8002F78C1 /* StringCompareViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringCompareViewController.swift; sourceTree = "<group>"; };
+		24D7803E29FA62A8002F78C1 /* StringCompareViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StringCompareViewController.xib; sourceTree = "<group>"; };
+		24D7803F29FA62A9002F78C1 /* StringCompareCellView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StringCompareCellView.xib; sourceTree = "<group>"; };
 		24D7FF9729261A6400DAB5EE /* KdanAuto.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KdanAuto.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		24D7FF9A29261A6400DAB5EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
 		24D7FF9C29261A6400DAB5EE /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
@@ -275,7 +282,6 @@
 		24DCE8B22950543C004EBA35 /* AutoTestCellInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoTestCellInfo.swift; sourceTree = "<group>"; };
 		24DCE8B429506CDE004EBA35 /* AutoTestProperty.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = AutoTestProperty.plist; sourceTree = "<group>"; };
 		24E3165C29DC35A20009E358 /* UpdateSDK.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = UpdateSDK.sh; sourceTree = "<group>"; };
-		24E8AE3A29F6A4A900988963 /* StringAutoBackTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StringAutoBackTest.swift; sourceTree = "<group>"; };
 		24FE3FF229BAF9B8004F4DD4 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; };
 /* End PBXFileReference section */
 
@@ -504,10 +510,8 @@
 		24AE7B4B298BD97300462BD3 /* CompareViewController */ = {
 			isa = PBXGroup;
 			children = (
-				24AE7B4C298BD98300462BD3 /* CompareViewController.swift */,
-				24CA233B298FF0F800038E10 /* CompareViewController.xib */,
-				24CA2335298FD6BE00038E10 /* ImageCompareCellView.swift */,
-				24CA2336298FD6BE00038E10 /* ImageCompareCellView.xib */,
+				24D7803B29FA61D0002F78C1 /* StringCompareView */,
+				24D7803229FA61BF002F78C1 /* ImageCompareView */,
 			);
 			path = CompareViewController;
 			sourceTree = "<group>";
@@ -532,7 +536,6 @@
 				24A6FF48293091E000B34F2E /* AutoTest.swift */,
 				246FE590299DCFC400706586 /* PDFCompareTest.swift */,
 				24D7000A292D16BB00DAB5EE /* StringAutoTest.swift */,
-				24E8AE3A29F6A4A900988963 /* StringAutoBackTest.swift */,
 				24848DE529F2A9E3002A7ED5 /* StringAutoCompareTest.swift */,
 				24A6FF4A2930939D00B34F2E /* TextColorAutoTest.swift */,
 				24A6FF4E2930A1E100B34F2E /* FontAutoTest.swift */,
@@ -540,6 +543,28 @@
 			path = AutoTestCase;
 			sourceTree = "<group>";
 		};
+		24D7803229FA61BF002F78C1 /* ImageCompareView */ = {
+			isa = PBXGroup;
+			children = (
+				24D7803329FA61BF002F78C1 /* ImageCompareCellView.xib */,
+				24D7803429FA61BF002F78C1 /* CompareViewController.xib */,
+				24D7803529FA61BF002F78C1 /* ImageCompareCellView.swift */,
+				24D7803629FA61BF002F78C1 /* CompareViewController.swift */,
+			);
+			path = ImageCompareView;
+			sourceTree = "<group>";
+		};
+		24D7803B29FA61D0002F78C1 /* StringCompareView */ = {
+			isa = PBXGroup;
+			children = (
+				24D7803C29FA62A8002F78C1 /* StringCompareCellView.swift */,
+				24D7803F29FA62A9002F78C1 /* StringCompareCellView.xib */,
+				24D7803D29FA62A8002F78C1 /* StringCompareViewController.swift */,
+				24D7803E29FA62A8002F78C1 /* StringCompareViewController.xib */,
+			);
+			path = StringCompareView;
+			sourceTree = "<group>";
+		};
 		24D7FF8E29261A6400DAB5EE = {
 			isa = PBXGroup;
 			children = (
@@ -872,7 +897,6 @@
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				24CA2338298FD6BE00038E10 /* ImageCompareCellView.xib in Resources */,
 				24848DDF29EF74AD002A7ED5 /* LogViewController.xib in Resources */,
 				242F966E298BAE2200CFF56C /* Toggle_on.png in Resources */,
 				24258DC529E581ED00027DEA /* Command Line Tool.sh in Resources */,
@@ -880,10 +904,12 @@
 				24DCE8A8295046A5004EBA35 /* TestCaseCellView.xib in Resources */,
 				24E3165D29DC35A20009E358 /* UpdateSDK.sh in Resources */,
 				24D7FF9F29261A6600DAB5EE /* Assets.xcassets in Resources */,
-				24CA233C298FF0F800038E10 /* CompareViewController.xib in Resources */,
 				24DCE8B529506CDE004EBA35 /* AutoTestProperty.plist in Resources */,
 				24848DB529ED1913002A7ED5 /* AdvanceSettingPropertyRules.plist in Resources */,
 				24848DC329ED2E4B002A7ED5 /* ASBOOLPropertyCell.xib in Resources */,
+				24D7803829FA61BF002F78C1 /* CompareViewController.xib in Resources */,
+				24D7804329FA62A9002F78C1 /* StringCompareCellView.xib in Resources */,
+				24D7803729FA61BF002F78C1 /* ImageCompareCellView.xib in Resources */,
 				24848DC629ED2FE4002A7ED5 /* ASFloatPropertyCell.xib in Resources */,
 				24848DB929ED2821002A7ED5 /* ASPropertyCell.xib in Resources */,
 				242F966F298BAE2200CFF56C /* Toggle_half.png in Resources */,
@@ -893,6 +919,7 @@
 				24848DBB29ED2852002A7ED5 /* ASIntPropertyCell.xib in Resources */,
 				24848DE229EFCE63002A7ED5 /* CDoucumnetAIResource.bundle in Resources */,
 				246FE5A6299E0FCD00706586 /* README.md in Resources */,
+				24D7804229FA62A9002F78C1 /* StringCompareViewController.xib in Resources */,
 				242F966D298BAE2200CFF56C /* Toggle_off.png in Resources */,
 				24848DBF29ED2B3F002A7ED5 /* ASSelectPropertyCell.xib in Resources */,
 				24848DB029ED0E2A002A7ED5 /* AdvanceSettingViewController.xib in Resources */,
@@ -956,20 +983,22 @@
 				2455C0D629E035A400800E8E /* PerformSelectTool.m in Sources */,
 				246FE5A7299E0FCD00706586 /* ZipArchive.m in Sources */,
 				24CA233A298FEED300038E10 /* FileInfo.swift in Sources */,
+				24D7803929FA61BF002F78C1 /* ImageCompareCellView.swift in Sources */,
+				24D7804029FA62A9002F78C1 /* StringCompareCellView.swift in Sources */,
 				24DCE8BB29518FD3004EBA35 /* ProcessThumbnal.swift in Sources */,
 				24848DB329ED187E002A7ED5 /* ASPropertyCell.swift in Sources */,
+				24D7804129FA62A9002F78C1 /* StringCompareViewController.swift in Sources */,
 				24D7FF9D29261A6400DAB5EE /* ViewController.swift in Sources */,
 				24A6FF512930AC4D00B34F2E /* AutoTestAdvanceSettingView.swift in Sources */,
 				24DCE8AD295046E7004EBA35 /* TestFileTypeCellView.swift in Sources */,
 				246FE591299DCFC400706586 /* PDFCompareTest.swift in Sources */,
 				24D7FFFE292B509000DAB5EE /* DataModel.swift in Sources */,
 				24848DE629F2A9E4002A7ED5 /* StringAutoCompareTest.swift in Sources */,
-				24CA2337298FD6BE00038E10 /* ImageCompareCellView.swift in Sources */,
 				24848DDA29EEBCBC002A7ED5 /* ASSizePropertyCell.swift in Sources */,
 				24D7FF9B29261A6400DAB5EE /* AppDelegate.swift in Sources */,
 				243DACD32940C6E8008A8AA6 /* ActivityView.swift in Sources */,
 				24848DC729ED2FE4002A7ED5 /* ASFloatPropertyCell.swift in Sources */,
-				24AE7B4D298BD98300462BD3 /* CompareViewController.swift in Sources */,
+				24D7803A29FA61BF002F78C1 /* CompareViewController.swift in Sources */,
 				24848DD629EEB9E2002A7ED5 /* ASRectPropertyCell.swift in Sources */,
 				240934B42992735200839CC8 /* FileConverter.swift in Sources */,
 				246FE5A4299E0FCD00706586 /* ioapi.c in Sources */,
@@ -986,7 +1015,6 @@
 				246FE5A3299E0FCD00706586 /* zip.c in Sources */,
 				24DCE8B1295047D8004EBA35 /* TestFileCellView.swift in Sources */,
 				24A6FF4B2930939D00B34F2E /* TextColorAutoTest.swift in Sources */,
-				24E8AE3B29F6A4A900988963 /* StringAutoBackTest.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

二進制
KdanAutoTest/KdanAuto.xcodeproj/project.xcworkspace/xcuserdata/zhudongyong.xcuserdatad/UserInterfaceState.xcuserstate


+ 0 - 32
KdanAutoTest/KdanAuto.xcodeproj/xcuserdata/zhudongyong.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist

@@ -180,37 +180,5 @@
             landmarkType = "7">
          </BreakpointContent>
       </BreakpointProxy>
-      <BreakpointProxy
-         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
-         <BreakpointContent
-            uuid = "7C3E1DCE-3161-4FA0-A0D3-E3CF0A2BC17A"
-            shouldBeEnabled = "Yes"
-            ignoreCount = "0"
-            continueAfterRunningActions = "No"
-            filePath = "KdanAuto/Class/AutoTestCase/StringAutoTest.swift"
-            startingColumnNumber = "9223372036854775807"
-            endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "160"
-            endingLineNumber = "160"
-            landmarkName = "autoTest(_:)"
-            landmarkType = "7">
-         </BreakpointContent>
-      </BreakpointProxy>
-      <BreakpointProxy
-         BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
-         <BreakpointContent
-            uuid = "CD09136A-8DA8-4715-8DC1-B1E16639E535"
-            shouldBeEnabled = "Yes"
-            ignoreCount = "0"
-            continueAfterRunningActions = "No"
-            filePath = "KdanAuto/Class/AutoTestCase/StringAutoTest.swift"
-            startingColumnNumber = "9223372036854775807"
-            endingColumnNumber = "9223372036854775807"
-            startingLineNumber = "174"
-            endingLineNumber = "174"
-            landmarkName = "autoTest(_:)"
-            landmarkType = "7">
-         </BreakpointContent>
-      </BreakpointProxy>
    </Breakpoints>
 </Bucket>

+ 0 - 6
KdanAutoTest/KdanAuto/Class/AdvanceSettingViewController/AdvanceSettingPropertyRules.plist

@@ -2198,12 +2198,6 @@
 				<key>Class</key>
 				<string>StringAutoTest</string>
 			</dict>
-			<dict>
-				<key>Name</key>
-				<string>字符逆序对比测试</string>
-				<key>Class</key>
-				<string>StringAutoBackTest</string>
-			</dict>
 			<dict>
 				<key>Name</key>
 				<string>跨平台字符对比测试</string>

+ 0 - 23
KdanAutoTest/KdanAuto/Class/AutoTestCase/StringAutoBackTest.swift

@@ -281,29 +281,6 @@ class StringAutoBackTest : StringAutoTest {
                             failString = failString.appending(subr as String) as NSString
                             resultStr = resultStr.substring(from:1) as NSString
                         }
-//                        //                    self.appendErrorInfo(skipString, failString: failString)
-//                        callback(attributeStringWith(skipString, failString: failString))
-//                        //                    failure(skipString, failString)
-//                        skipString = NSString()
-//                        failString = NSString()
-//
-//                        // C:a[bcde]fghij
-//                        // R:f[klmnbvcx]a
-//                        if (cRange.location < rRange.location) {
-//                            let cacheString = checkString.substring(to:cRange.location + cRange.length)
-//                            callback(attributeStringWith(cacheString as NSString, failString: ""))
-//                            //                        failure(cacheString as NSString, "")
-//                            //                        self.reportString?.append(NSMutableAttributedString.init(string: "对照字符串【\(cacheString)】未识别到\n",
-//                            //                                                                                 attributes:[.foregroundColor : NSColor.red]))
-//                            checkString = checkString.substring(from:cRange.location) as NSString
-//                        }else {
-//                            let cacheString = resultStr.substring(to:rRange.location)
-//                            callback(attributeStringWith("", failString: cacheString as NSString))
-//                            //                        failure("", cacheString as NSString)
-//                            //                        self.reportString?.append(NSMutableAttributedString.init(string: "字符串【\(cacheString)】识别出错\n",
-//                            //                                                                                 attributes:[.foregroundColor : NSColor.red]))
-//                            resultStr = resultStr.substring(from:rRange.location + rRange.length) as NSString
-//                        }
                     }
                 }else if (cRange.location != NSNotFound) {
                     //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一

+ 2 - 2
KdanAutoTest/KdanAuto/Class/AutoTestCase/StringAutoCompareTest.swift

@@ -72,7 +72,7 @@ class StringAutoCompareTest : StringAutoTest {
             let checkPath = NSString(string: checkDirectory).appendingPathComponent(fName+"."+self.extention())
             
             
-            self.reportString?.append(NSMutableAttributedString.init(string: "\n【\(String(self.fileType())) - \(self.name())】开始转换文件 \"\(fName)\"\n",
+            self.reportString?.append(NSMutableAttributedString.init(string: "\n【\(String(self.fileType())) - \(self.name())】开始对照文件 \"\(fName)\"\n",
                                                                 attributes:[.foregroundColor : NSColor.black]))
             // ...
             // 执行转换过程
@@ -113,7 +113,7 @@ class StringAutoCompareTest : StringAutoTest {
                                                                fileName: fileName)
                                 
                                 let successCount = Int(maxSize * Int(degree)/100)
-                                report.append(NSAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"比对完成,准确率\(degree)%(\(successCount)/\(maxSize))\n",
+                                report.append(NSAttributedString.init(string: "\n【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"比对完成,准确率\(degree)%(\(successCount)/\(maxSize))\n",
                                                                                   attributes:[.foregroundColor : color]))
                                 if (report != nil) {
                                     do {

+ 155 - 45
KdanAutoTest/KdanAuto/Class/AutoTestCase/StringAutoTest.swift

@@ -130,7 +130,7 @@ class StringAutoTest : AutoTest {
                                                                fileName: fileName)
                                 
                                 let successCount = Int(maxSize * Int(degree)/100)
-                                report.append(NSAttributedString.init(string: "【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"比对完成,准确率\(degree)%(\(successCount)/\(maxSize))\n",
+                                report.append(NSAttributedString.init(string: "\n【\(String(self.fileType())) - \(self.name())】文件 \"\(fName)\"比对完成,准确率\(degree)%(\(successCount)/\(maxSize))\n",
                                                                                   attributes:[.foregroundColor : color]))
                                 if (report != nil) {
                                     do {
@@ -300,6 +300,7 @@ class StringAutoTest : AutoTest {
                 
                 if subc.isEqual(to: subr) { // (A0 = B0)
                                             // Check Success
+                    // 两个字符相同
                     callback(attributeStringWith(skipString, failString: failString))
 //                    failure(skipString, failString)
 //                    self.appendErrorInfo(skipString, failString: failString)
@@ -312,33 +313,93 @@ class StringAutoTest : AutoTest {
                     successCount = successCount + 1
                     callback(NSAttributedString(string: subc as String))
                 }else if (["\n", "\r", " "].contains(subc)) {
+                    // 两个字符不相同,但 CheckString 首字符 为 空格或回车
                     callback(NSAttributedString(string: subc as String))
                     maxSize -= 1;
                     checkString = checkString.substring(from:1) as NSString
                 }else if (cRange.location != NSNotFound &&
                            rRange.location != NSNotFound) {
-                    if (min(cRange.location, rRange.location) >= 2) {
+                    // 两个字符均出现在另外一个字符 串中
+                    
+                    if min(cRange.location, rRange.location) >= 10 {
+//                        let pc = checkString.substring(with: NSMakeRange(0, min(checkString.length, cRange.location)))
+//                        let pr = resultStr.substring(with: NSMakeRange(0, min(resultStr.length, rRange.location)))
+//                        NSLog("C(\(cCount)):%.2f%%:\(pc)", cdegree)
+//                        NSLog("R(\(rCount)):%.2f%%:\(pr)", rdegree)
+                        if (cRange.location > rRange.location*3) {
+                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            failString = failString.appending(subr as String) as NSString
+                            resultStr = resultStr.substring(from:1) as NSString
+                        }else if (cRange.location*3 < rRange.location) {
+                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            skipString = skipString.appending(subc as String) as NSString
+                            checkString = checkString.substring(from:1) as NSString
+                        }else {
+                            let checkSubString = checkString.substring(with: NSMakeRange(0, cRange.location))
+                            let cCount = checkCountIn(checkSubString as NSString, inStr: resultStr);
+                            let rCount = checkCountIn(resultStr.substring(with: NSMakeRange(0, rRange.location)) as NSString, inStr: checkString)
+                            
+                            let cdegree = Float(cCount) / Float(cRange.location)
+                            let rdegree = Float(rCount) / Float(rRange.location)
+                            
+                            if (cdegree > 0.2) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                failString = failString.appending(subr as String) as NSString
+                                resultStr = resultStr.substring(from:1) as NSString
+                            }else if (rdegree > 0.2) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                skipString = skipString.appending(subc as String) as NSString
+                                checkString = checkString.substring(from:1) as NSString
+                            } else if (cdegree > rdegree * 2.0) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                failString = failString.appending(subr as String) as NSString
+                                resultStr = resultStr.substring(from:1) as NSString
+                            }else if (cdegree * 2.0 < rdegree) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                skipString = skipString.appending(subc as String) as NSString
+                                checkString = checkString.substring(from:1) as NSString
+                            }else if (cCount < rCount) {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                failString = failString.appending(subr as String) as NSString
+                                resultStr = resultStr.substring(from:1) as NSString
+                            }else {
+                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                                skipString = skipString.appending(subc as String) as NSString
+                                checkString = checkString.substring(from:1) as NSString
+                            }
+                        }
+                    }else if min(cRange.location, rRange.location) >= 2 {
+                        // 首部字符在对方字串中位置偏移最小值 大于 2
+                        var scale = (resultStr.length > 0) ? (Float(checkString.length) / Float(resultStr.length)) : Float(1.0)//, Float(1.0))
                         let nextc = checkString.substring(with: NSRange(location: 1, length: 1)) as NSString
                         let nextr = resultStr.substring(with: NSRange(location: 1, length: 1)) as NSString
-                        let ncRange = checkString.range(of: nextr as String)
-                        let nrRange = resultStr.range(of: nextc as String)
-                        
+                        var ncRange = checkString.range(of: nextr as String)
+                        var nrRange = resultStr.range(of: nextc as String)
+
+                        if nrRange.location == NSNotFound {
+                            nrRange.location = 100000;
+                        }
+                        if ncRange.location == NSNotFound {
+                            ncRange.location = 100000;
+                        }
+
                         if (min(nrRange.location, ncRange.location) < min(cRange.location, rRange.location)) {
-                            if (ncRange.location < nrRange.location) {
-                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一位
+                            // 第二位字符,在对方字串中位置偏移最小值小于 首字符偏移
+                            if ncRange.location < Int(Float(nrRange.location) * scale) {
+                                //‘subr' 字符串有在‘checkString’ 偏移 小于'subc'在’checkString‘中 的偏移,优先移除checkString第一位
                                 skipString = skipString.appending(subc as String) as NSString
                                 checkString = checkString.substring(from:1) as NSString
                             }else {
-                                //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一位
+                                //‘subr' 字符串有在‘checkString’ 偏移 不小于'subc'在’checkString‘中 的偏移,优先移除resultStr第一位
                                 failString = failString.appending(subr as String) as NSString
                                 resultStr = resultStr.substring(from:1) as NSString
                             }
-                        }else if (cRange.location < rRange.location) {
-                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                        }else if (cRange.location < Int(Float(rRange.location) * scale)) {
+                            //‘subr' 字符串有在‘checkString’ 偏移 小于'subc'在’checkString‘中 的偏移,优先移除checkString第一位
                             skipString = skipString.appending(subc as String) as NSString
                             checkString = checkString.substring(from:1) as NSString
                         }else {
-                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            //‘subr' 字符串有在‘checkString’ 偏移 不小于'subc'在’checkString‘中 的偏移,优先移除resultStr第一位
                             failString = failString.appending(subr as String) as NSString
                             resultStr = resultStr.substring(from:1) as NSString
                         }
@@ -353,46 +414,35 @@ class StringAutoTest : AutoTest {
 //                            resultStr = resultStr.substring(from:1) as NSString
 //                        }else
                         if (cRange.location < rRange.location) {
-                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            //‘subr' 字符串有在‘checkString’ 偏移 小于'subc'在’checkString‘中 的偏移,优先移除checkString第一位
                             skipString = skipString.appending(subc as String) as NSString
                             checkString = checkString.substring(from:1) as NSString
                         }else  {
-                            //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                            //‘subr' 字符串有在‘checkString’ 偏移 不小于'subc'在’checkString‘中 的偏移,优先移除resultStr第一位
                             failString = failString.appending(subr as String) as NSString
                             resultStr = resultStr.substring(from:1) as NSString
                         }
-//                        //                    self.appendErrorInfo(skipString, failString: failString)
-//                        callback(attributeStringWith(skipString, failString: failString))
-//                        //                    failure(skipString, failString)
-//                        skipString = NSString()
-//                        failString = NSString()
-//
-//                        // C:a[bcde]fghij
-//                        // R:f[klmnbvcx]a
-//                        if (cRange.location < rRange.location) {
-//                            let cacheString = checkString.substring(to:cRange.location + cRange.length)
-//                            callback(attributeStringWith(cacheString as NSString, failString: ""))
-//                            //                        failure(cacheString as NSString, "")
-//                            //                        self.reportString?.append(NSMutableAttributedString.init(string: "对照字符串【\(cacheString)】未识别到\n",
-//                            //                                                                                 attributes:[.foregroundColor : NSColor.red]))
-//                            checkString = checkString.substring(from:cRange.location) as NSString
-//                        }else {
-//                            let cacheString = resultStr.substring(to:rRange.location)
-//                            callback(attributeStringWith("", failString: cacheString as NSString))
-//                            //                        failure("", cacheString as NSString)
-//                            //                        self.reportString?.append(NSMutableAttributedString.init(string: "字符串【\(cacheString)】识别出错\n",
-//                            //                                                                                 attributes:[.foregroundColor : NSColor.red]))
-//                            resultStr = resultStr.substring(from:rRange.location + rRange.length) as NSString
-//                        }
                     }
                 }else if (cRange.location != NSNotFound) {
-                    //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
-                    skipString = skipString.appending(subc as String) as NSString
-                    checkString = checkString.substring(from:1) as NSString
+//                    let checkSubString = checkString.substring(with: cRange)
+//                    if (checkCountIn(checkSubString as NSString, inStr: resultStr) < Int(Float(cRange.location) * 0.6)) {
+                        //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                        skipString = skipString.appending(subc as String) as NSString
+                        checkString = checkString.substring(from:1) as NSString
+//                    }else {
+//                        failString = failString.appending(subr as String) as NSString
+//                        resultStr = resultStr.substring(from:1) as NSString
+//                    }
                 }else if (rRange.location != NSNotFound) {
-                    //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
-                    failString = failString.appending(subr as String) as NSString
-                    resultStr = resultStr.substring(from:1) as NSString
+//                    let resultSubString = resultStr.substring(with: rRange)
+//                    if (checkCountIn(resultSubString as NSString, inStr: checkString) < Int(Float(rRange.location) * 0.5)) {
+                        //‘subc' 字符串有在‘resultStr’中,但'subr'不在’checkString‘中,resultStr 往后推一
+                        failString = failString.appending(subr as String) as NSString
+                        resultStr = resultStr.substring(from:1) as NSString
+//                    }else {
+//                        skipString = skipString.appending(subc as String) as NSString
+//                        checkString = checkString.substring(from:1) as NSString
+//                    }
                 }else {
                     //  两个子字串均未找到
                     skipString = skipString.appending(subc as String) as NSString
@@ -415,6 +465,38 @@ class StringAutoTest : AutoTest {
         }
     }
     
+    func checkCountIn(_ subStr:NSString, inStr:NSString) -> Int {
+        let countInfo = NSMutableArray()
+        
+        for i in 0...(subStr.length - 3) {
+            let tStr = subStr.substring(with: NSMakeRange(i, 3))
+            let range = inStr.range(of: tStr)
+            if (range.location != NSNotFound) {
+                countInfo.add(range.location)
+            }
+        }
+        
+        return findLISLength(countInfo as! [Int]);
+    }
+    
+    func findLISLength(_ nums: [Int]) -> Int {
+        let n = nums.count
+        if n == 0 {
+            return 0
+        }
+        var dp = Array(repeating: 1, count: n)
+        var maxLen = 1
+        for i in 1 ..< n {
+            for j in 0 ..< i {
+                if nums[i] > nums[j] {
+                    dp[i] = max(dp[i], dp[j] + 1)
+                }
+            }
+            maxLen = max(maxLen, dp[i])
+        }
+        return maxLen
+    }
+    
     // Read File
     func readTextFile(_ filePath:NSString) -> String? {
         if NSArray(array: ["TXT", "txt"]).contains(filePath.pathExtension) {
@@ -502,14 +584,42 @@ class StringAutoTest : AutoTest {
     
     
     override func compareFiles() -> NSArray? {
-        return nil
+        let items = NSMutableArray()
+        let files = DataModel.shared.originFilesFor(_fileType, type: _type) as [String]
+        
+        for fileName in files {
+            let sItems = compareFiles(fileName)
+            if sItems != nil && sItems!.count != 0 {
+                items.addObjects(from: sItems as! [Any])
+            }
+        }
+        
+        return items
     }
     
     override func compareFiles(_ fileName: String) -> NSArray? {
-        return nil
+        let files = NSMutableArray()
+        
+        let checkDirectory = self.checkFileDirectory()
+        let resultDirectory = self.resultFileDirectory()
+        
+        let nName = NSString(string: fileName).deletingPathExtension.appending(".\(self.extention())")
+        let rComparePath = NSString(string: resultDirectory).appendingPathComponent(nName)
+        let cComparePath = NSString(string: checkDirectory).appendingPathComponent(nName)
+        
+        if (FileManager.default.fileExists(atPath: rComparePath) &&
+            FileManager.default.fileExists(atPath: rComparePath+".rtf")) {
+            let fileInfo = NSMutableDictionary.fileInfoWith(fileName,
+                                                            refFilePath: nil,
+                                                            resultPath: rComparePath,
+                                                            comparePath: cComparePath,
+                                                            objc: self)
+            files.add(fileInfo)
+        }
+        
+        return files
     }
     
-    
     /**
      Replace the refrence image for next image check test
      */

KdanAutoTest/KdanAuto/Class/CompareViewController/CompareViewController.swift → KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareView/CompareViewController.swift


KdanAutoTest/KdanAuto/Class/CompareViewController/CompareViewController.xib → KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareView/CompareViewController.xib


KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareCellView.swift → KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareView/ImageCompareCellView.swift


KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareCellView.xib → KdanAutoTest/KdanAuto/Class/CompareViewController/ImageCompareView/ImageCompareCellView.xib


+ 127 - 0
KdanAutoTest/KdanAuto/Class/CompareViewController/StringCompareView/StringCompareCellView.swift

@@ -0,0 +1,127 @@
+//
+//  ImageCompareCellView.swift
+//  KdanAuto
+//
+//  Created by 朱东勇 on 2022/11/21.
+//
+
+import Foundation
+import AppKit
+
+class StringCompareCellView : NSTableCellView {
+    @IBOutlet var _titleLbl : NSTextField!
+    @IBOutlet var _degreeInfoLbl : NSTextField!
+    
+    @IBOutlet var _contentView : NSView!
+    
+    @IBOutlet var _sepLine : NSView!
+    
+    @IBOutlet var m_textScrollView: NSScrollView!
+    @IBOutlet var m_textView: NSTextView!
+    
+    var _title : String!
+    var _fileInfo : NSMutableDictionary!
+    
+    class func shared() -> StringCompareCellView? {
+        var objects : NSArray!
+        
+        Bundle.main.loadNibNamed("StringCompareCellView", owner: nil, topLevelObjects: &objects)
+        
+        for tView in objects {
+            if let tv = tView as? StringCompareCellView {
+                return tv
+            }
+        }
+        
+        return nil
+    }
+    
+    override func awakeFromNib() {
+        _sepLine.wantsLayer = true;
+        _sepLine.layer?.backgroundColor = NSColor.lightGray.cgColor
+    }
+    
+    // Setter & Getter
+    public func setTitle(_ title:String) {
+        _title = title;
+        
+        _titleLbl.stringValue = _title ?? ""
+    }
+    
+    public func title() -> String? {
+        return _title
+    }
+    
+    public func setFileInfo(_ fileInfo:NSMutableDictionary) {
+        _fileInfo = fileInfo;
+        
+        if nil != _fileInfo {
+            autoreleasepool {
+                let resultPath = NSString(string: _fileInfo.resultPath()).appendingPathExtension("rtf")!
+                
+                let checkData = NSData.init(contentsOfFile: resultPath as String)! as Data
+                var documentAttributes:NSDictionary!
+                let attString = NSAttributedString.init(rtf: checkData, documentAttributes: &documentAttributes)
+                self.m_textView.textStorage?.setAttributedString(attString!)
+                
+                if (nil == _fileInfo.refFilePath()) {
+                    setTitle(String("[\(_fileInfo.objc().fileType()):\(_fileInfo.objc().name())]\(_fileInfo.fileName())"))
+                }else {
+                    let lastPathComponent = NSString(string: _fileInfo.refFilePath()!).lastPathComponent
+                    setTitle(String("[\(_fileInfo.objc().fileType()):\(_fileInfo.objc().name())]\(_fileInfo.fileName())/\(lastPathComponent)"))
+                }
+                
+                let degree = _fileInfo.degree()
+                if degree == -1 {
+                    _degreeInfoLbl.stringValue = "对照文件不存在"
+                    _degreeInfoLbl.textColor = NSColor.red
+                } else {
+                    if abs(degree - 100) > 0 {
+                        _degreeInfoLbl.textColor = NSColor.red
+                    }else {
+                        _degreeInfoLbl.textColor = NSColor.blue
+                    }
+                    _degreeInfoLbl.stringValue = NSString(format: "相似度:%.2f%%", degree) as String
+                }
+            }
+        }else {
+            setTitle("")
+            _degreeInfoLbl.stringValue = ""
+        }
+    }
+    
+    public func fileInfo() -> NSMutableDictionary {
+        return _fileInfo
+    }
+    
+}
+
+
+extension StringCompareCellView {
+    
+    class func heightFor(_ fileInfo:NSMutableDictionary) -> CGFloat {
+        let resultPath = NSString(string: fileInfo.resultPath()).appendingPathExtension("rtf")!
+        
+        let checkData = NSData.init(contentsOfFile: resultPath as String)! as Data
+        var documentAttributes:NSDictionary!
+        let attString = NSAttributedString.init(rtf: checkData, documentAttributes: &documentAttributes)
+        
+        var retSize = attString!.boundingRect(with: CGSizeMake(990, 1000),
+                                                                  options: .usesLineFragmentOrigin.union(.usesFontLeading)).size
+        
+        return retSize.height + 50
+    }
+    
+}
+
+
+class CustomScrollView: NSScrollView {
+    
+    override func scroll(_ point: NSPoint) {
+        
+    }
+    
+    override func scrollWheel(with event: NSEvent) {
+        // Do nothing, effectively disabling scrolling
+    }
+}

+ 83 - 0
KdanAutoTest/KdanAuto/Class/CompareViewController/StringCompareView/StringCompareCellView.xib

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <tableCellView identifier="ImageCompareCellView" id="Ob6-j8-aNh" customClass="StringCompareCellView" customModule="KdanAuto" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="1000" height="800"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZfV-Hf-yE5">
+                    <rect key="frame" x="0.0" y="777" width="678" height="21"/>
+                    <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
+                    <textFieldCell key="cell" lineBreakMode="truncatingMiddle" title="Label" id="yAG-7D-A8X">
+                        <font key="font" metaFont="systemMedium" size="13"/>
+                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                    </textFieldCell>
+                </textField>
+                <customView id="l0O-8O-W8F">
+                    <rect key="frame" x="5" y="5" width="990" height="767"/>
+                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                    <subviews>
+                        <scrollView focusRingType="none" fixedFrame="YES" borderType="none" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" id="Lxj-Lu-JTX" customClass="CustomScrollView">
+                            <rect key="frame" x="0.0" y="0.0" width="990" height="767"/>
+                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                            <clipView key="contentView" drawsBackground="NO" id="C3h-63-7lm">
+                                <rect key="frame" x="0.0" y="0.0" width="990" height="767"/>
+                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                <subviews>
+                                    <textView wantsLayer="YES" editable="NO" selectable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" smartInsertDelete="YES" id="D7Z-t1-Ky4">
+                                        <rect key="frame" x="0.0" y="0.0" width="990" height="767"/>
+                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                        <color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
+                                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                        <size key="minSize" width="990" height="767"/>
+                                        <size key="maxSize" width="990" height="10000000"/>
+                                        <color key="insertionPointColor" name="textColor" catalog="System" colorSpace="catalog"/>
+                                    </textView>
+                                </subviews>
+                            </clipView>
+                            <scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="WHM-8C-3qN">
+                                <rect key="frame" x="-100" y="-100" width="240" height="16"/>
+                                <autoresizingMask key="autoresizingMask"/>
+                            </scroller>
+                            <scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="WkX-Jy-fru">
+                                <rect key="frame" x="-100" y="-100" width="16" height="767"/>
+                                <autoresizingMask key="autoresizingMask"/>
+                            </scroller>
+                        </scrollView>
+                    </subviews>
+                </customView>
+                <customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="eqN-VX-Yfe">
+                    <rect key="frame" x="0.0" y="0.0" width="1000" height="1"/>
+                    <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
+                </customView>
+                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="Ooh-60-kZ8">
+                    <rect key="frame" x="891" y="780" width="106" height="16"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
+                    <textFieldCell key="cell" lineBreakMode="clipping" alignment="center" title="相似度:888.88%" id="7cX-su-WGo">
+                        <font key="font" metaFont="system"/>
+                        <color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
+                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                    </textFieldCell>
+                </textField>
+            </subviews>
+            <connections>
+                <outlet property="_contentView" destination="l0O-8O-W8F" id="xFJ-xl-ppI"/>
+                <outlet property="_degreeInfoLbl" destination="Ooh-60-kZ8" id="tRz-ZD-Ynf"/>
+                <outlet property="_sepLine" destination="eqN-VX-Yfe" id="7xX-yS-Nvt"/>
+                <outlet property="_titleLbl" destination="ZfV-Hf-yE5" id="yoz-vL-tGs"/>
+                <outlet property="m_textScrollView" destination="Lxj-Lu-JTX" id="3I2-eg-KsQ"/>
+                <outlet property="m_textView" destination="D7Z-t1-Ky4" id="c5F-rx-FQZ"/>
+            </connections>
+            <point key="canvasLocation" x="-190" y="78"/>
+        </tableCellView>
+    </objects>
+</document>

+ 296 - 0
KdanAutoTest/KdanAuto/Class/CompareViewController/StringCompareView/StringCompareViewController.swift

@@ -0,0 +1,296 @@
+//
+//  CompareViewController.swift
+//  KdanAuto
+//
+//  Created by 朱东勇 on 2023/2/2.
+//
+
+import Foundation
+import AppKit
+import PDFKit
+
+class StringCompareViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate, NSPopoverDelegate {
+    
+    @IBOutlet var listView : NSTableView!
+    
+    @IBOutlet var filterBtn : NSButton!
+    @IBOutlet var closeBtn : NSButton!
+    
+    @IBOutlet var progressIndicator : NSProgressIndicator!
+    
+    var _files : NSArray!
+    var _showFiles : NSMutableArray!
+    var _popover: NSPopover!
+    
+    static var sharedSCViewController : StringCompareViewController? = nil
+    class func shared() -> StringCompareViewController {
+        if nil == sharedSCViewController {
+            var objects : NSArray!
+            
+            Bundle.main.loadNibNamed("StringCompareViewController", owner: nil, topLevelObjects: &objects)
+            
+            for tView in objects {
+                if let tv = tView as? StringCompareViewController {
+                    sharedSCViewController = tv
+                }
+            }
+        }
+        
+        return sharedSCViewController!
+    }
+    
+    override func viewDidLoad() {
+        self.listView.register(NSNib.init(nibNamed: NSNib.Name.init(NSString(string: "StringCompareCellView")),
+                                          bundle: Bundle.main), forIdentifier: NSUserInterfaceItemIdentifier.init("StringCompareCellView"))
+    }
+    
+    // IBAction
+    @IBAction func filterSimilarItemAction(_ sender:NSButton) {
+        self.setFiles(_files);
+    }
+    
+    @IBAction func exportAction(_ sender:NSButton) {
+        if (_files.count == 0) {
+            let alert = NSAlert.init()
+            alert.messageText = "无测试对比项导出";
+            alert.runModal();
+            
+            return
+        }else if (_showFiles.count == 0) {
+            let alert = NSAlert.init()
+            alert.messageText = "所有对比项均无差异";
+            alert.runModal();
+            
+            return
+        }
+        
+        let savePanel = NSSavePanel.init();
+        let checkBox = NSButton(checkboxWithTitle: "过滤无差异项", target: self, action: nil);
+        checkBox.state = self.filterBtn.state;
+        checkBox.frame = CGRectMake(0, 0, 150, 45);
+        
+        if #available(macOS 11.0, *) {
+            savePanel.allowedContentTypes = [.rtf]
+        } else {
+            savePanel.allowedFileTypes = ["rtf", "rrtf"]
+        }
+        savePanel.accessoryView = checkBox
+        
+        if (savePanel.runModal() == .OK) {
+            var exportFiles = NSMutableArray()
+            
+            if (checkBox.state == .on) {
+                
+                for tfile in NSArray(array: _files) {
+                    let file = tfile as! NSMutableDictionary;
+                    
+                    let degree = file.degree()
+                    if (fabs(degree - 100) > 0) {
+                        exportFiles.add(file);
+                    }
+                }
+                if (exportFiles.count == 0) {
+                    let alert = NSAlert.init()
+                    alert.messageText = "所有对比项均无差异";
+                    alert.runModal();
+                    
+                    return
+                }
+            }else {
+                exportFiles = NSMutableArray(array: _files)
+            }
+            
+            let url = savePanel.url!;
+            NSLog("\(url)")
+            let attString = NSMutableAttributedString(string: "");
+            let needFilter = checkBox.state == .on
+            
+            self.progressIndicator.isHidden = false;
+            self.progressIndicator.doubleValue = 0;
+            processNextImages(attString, index: 0, files:exportFiles, url: url, needFilter: needFilter)
+        }
+    }
+    
+    // Save PDF
+    func processNextImages(_ attString:NSMutableAttributedString, index:Int32, files:NSMutableArray, url:URL, needFilter:Bool) -> Void {
+        let file = files[Int(index)] as! NSMutableDictionary
+        
+        
+        let resultPath = NSString(string: file.resultPath()).appendingPathExtension("rtf")!
+        
+        let checkData = NSData.init(contentsOfFile: resultPath as String)! as Data
+        var documentAttributes:NSDictionary!
+        let tAttString = NSAttributedString.init(rtf: checkData, documentAttributes: &documentAttributes)
+        
+        if (tAttString != nil) {
+            attString.append(NSMutableAttributedString(string: "\n\n"));
+            attString.append(tAttString!)
+        }
+        
+        self.closeBtn.isEnabled = false;
+        
+        DispatchQueue.global().async {
+            
+            if ((index+1) < files.count) {
+                DispatchQueue.main.asyncAfter(deadline: DispatchTime.init(uptimeNanoseconds: 100)) {
+                    
+                    self.progressIndicator.doubleValue = Double(Int(index) * 100/files.count);
+                    self.processNextImages(attString, index: index+1, files: files, url: url, needFilter: needFilter);
+                };
+            }else {
+                DispatchQueue.global().async {
+                    autoreleasepool {
+                        // 写入文件
+                        do {
+                            let rtfData = try? attString.data(from: .init(location: 0, length: attString.length),
+                                                           documentAttributes: [.documentType: NSAttributedString.DocumentType.rtf])
+                            
+                            let path = NSString(string: resultPath).appendingPathExtension("rtf")
+                            try? FileManager.default.removeItem(at: url)
+                            try? rtfData?.write(to: url)
+                        } catch {
+                        }
+                        
+                        DispatchQueue.main.async {
+                            self.progressIndicator.isHidden = true;
+                            self.progressIndicator.doubleValue = 100.0;
+                            
+                            self.closeBtn.isEnabled = true;
+                            
+                            NSWorkspace.shared.activateFileViewerSelecting([url])
+                        }
+                    }
+                }
+            }
+        }
+    }
+    
+    
+    // Show
+    func showIn(_ view:NSView, rect:NSRect) {
+        if _popover == nil {
+            _popover = NSPopover.init()
+            _popover.contentViewController = self;
+            _popover.delegate = self
+        }
+        _popover.contentSize = self.view.frame.size
+        
+        _popover.show(relativeTo: rect, of: view, preferredEdge: NSRectEdge.minY)
+    }
+    
+    
+    // Getter & Setter
+    func setFiles(_ files:NSArray) {
+        _files = files
+        
+        if (self.filterBtn.state == .on) {
+            _showFiles = NSMutableArray()
+            
+            for tfile in NSArray(array: _files) {
+                let file = tfile as! NSMutableDictionary;
+                
+                let degree = file.degree()
+                if (fabs(degree - 100) > 0) {
+                    _showFiles.add(file);
+                }
+            }
+        }else {
+            _showFiles = NSMutableArray (array: _files);
+        }
+        
+        listView.reloadData()
+    }
+    
+    
+    // IBAction
+    @IBAction func closeAction(_ sender: NSButton) {
+        _popover.close()
+    }
+    
+    
+    // TableView Delegate
+    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
+        return autoreleasepool {
+            var cellView = tableView.makeView(withIdentifier: .init("StringCompareCellView"), owner: nil) as! StringCompareCellView?
+            if (nil == cellView) {
+                cellView = StringCompareCellView.shared() ?? nil
+            }
+            
+            if (_showFiles.count > row) {
+                let fileInfo = _showFiles[row] as! NSMutableDictionary
+                
+                cellView?.setFileInfo(fileInfo)
+            }
+            
+            return cellView
+        }
+    }
+    
+    func selectionShouldChange(in tableView: NSTableView) -> Bool {
+        
+        return true
+    }
+    
+    func tableView(_ tableView: NSTableView, shouldSelectRow row: Int) -> Bool {
+        
+        return false
+    }
+    
+    func tableView(_ tableView: NSTableView, shouldSelect tableColumn: NSTableColumn?) -> Bool {
+        
+        return false
+    }
+    
+    func tableView(_ tableView: NSTableView, mouseDownInHeaderOf tableColumn: NSTableColumn) {
+        
+    }
+    
+    func tableView(_ tableView: NSTableView, didClick tableColumn: NSTableColumn) {
+        
+    }
+    
+    func tableView(_ tableView: NSTableView, didDrag tableColumn: NSTableColumn) {
+        
+    }
+    
+    func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
+        if (_showFiles.count > row) {
+            let fileInfo = _showFiles[row] as! NSMutableDictionary
+            
+            return StringCompareCellView.heightFor(fileInfo)
+        }
+        return 0
+    }
+    
+    func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
+        return false
+    }
+    
+    func tableView(_ tableView: NSTableView, sizeToFitWidthOfColumn column: Int) -> CGFloat {
+        return tableView.frame.width
+    }
+    
+    func tableView(_ tableView: NSTableView, rowActionsForRow row: Int, edge: NSTableView.RowActionEdge) -> [NSTableViewRowAction] {
+        return []
+    }
+    
+    func tableViewSelectionDidChange(_ notification: Notification) {
+        
+    }
+    
+    // TableView Data Source
+    func numberOfRows(in tableView: NSTableView) -> Int {
+        if nil == _showFiles {
+            return 0
+        }
+        
+        return _showFiles.count
+    }
+    
+    //
+    func popoverShouldClose(_ popover: NSPopover) -> Bool {
+        return true
+    }
+    
+    
+}

+ 129 - 0
KdanAutoTest/KdanAuto/Class/CompareViewController/StringCompareView/StringCompareViewController.xib

@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <deployment identifier="macosx"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <viewController id="YBj-nQ-WgX" customClass="StringCompareViewController" customModule="KdanAuto" customModuleProvider="target">
+            <connections>
+                <outlet property="closeBtn" destination="u2f-QM-qgA" id="Cb5-Ie-Jkc"/>
+                <outlet property="filterBtn" destination="qCC-xr-5ZS" id="Q7X-Ey-WUr"/>
+                <outlet property="listView" destination="45n-iP-sYg" id="FnW-Nj-Hop"/>
+                <outlet property="progressIndicator" destination="865-rk-Lp5" id="9x5-cL-1Ca"/>
+                <outlet property="view" destination="cCo-Bc-PDG" id="UFV-zt-z4Q"/>
+            </connections>
+        </viewController>
+        <customView id="cCo-Bc-PDG">
+            <rect key="frame" x="0.0" y="0.0" width="1000" height="950"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="u2f-QM-qgA">
+                    <rect key="frame" x="1" y="918" width="38" height="29"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                    <buttonCell key="cell" type="squareTextured" title="X" bezelStyle="texturedSquare" alignment="center" imageScaling="proportionallyDown" inset="2" id="nXq-to-31f">
+                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                        <font key="font" metaFont="system" size="16"/>
+                    </buttonCell>
+                    <connections>
+                        <action selector="closeAction:" target="YBj-nQ-WgX" id="tJq-V5-DdY"/>
+                    </connections>
+                </button>
+                <scrollView fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="24" horizontalPageScroll="10" verticalLineScroll="24" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sc9-iv-6hc">
+                    <rect key="frame" x="5" y="5" width="990" height="915"/>
+                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                    <clipView key="contentView" id="bdH-xL-Fjb">
+                        <rect key="frame" x="1" y="1" width="988" height="913"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" rowSizeStyle="automatic" viewBased="YES" id="45n-iP-sYg">
+                                <rect key="frame" x="0.0" y="0.0" width="988" height="913"/>
+                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                <size key="intercellSpacing" width="17" height="0.0"/>
+                                <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
+                                <tableColumns>
+                                    <tableColumn identifier="AutomaticTableColumnIdentifier.0" width="976" minWidth="40" maxWidth="1000" id="GAy-CY-UvO">
+                                        <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
+                                            <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
+                                            <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
+                                        </tableHeaderCell>
+                                        <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="2L4-rs-fOk">
+                                            <font key="font" metaFont="system"/>
+                                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                                            <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                        </textFieldCell>
+                                        <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
+                                        <prototypeCellViews>
+                                            <tableCellView id="3RK-Lw-S22">
+                                                <rect key="frame" x="8" y="0.0" width="971" height="24"/>
+                                                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                                                <subviews>
+                                                    <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="80Q-Yb-YWu">
+                                                        <rect key="frame" x="0.0" y="4" width="971" height="16"/>
+                                                        <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
+                                                        <textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="JFN-2o-qQp">
+                                                            <font key="font" usesAppearanceFont="YES"/>
+                                                            <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                                                            <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                                                        </textFieldCell>
+                                                    </textField>
+                                                </subviews>
+                                                <connections>
+                                                    <outlet property="textField" destination="80Q-Yb-YWu" id="uvE-IK-2U1"/>
+                                                </connections>
+                                            </tableCellView>
+                                        </prototypeCellViews>
+                                    </tableColumn>
+                                </tableColumns>
+                                <connections>
+                                    <outlet property="dataSource" destination="YBj-nQ-WgX" id="f3O-3A-duS"/>
+                                    <outlet property="delegate" destination="YBj-nQ-WgX" id="6hS-2V-U3r"/>
+                                </connections>
+                            </tableView>
+                        </subviews>
+                    </clipView>
+                    <scroller key="horizontalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="YES" id="tEb-3h-nsO">
+                        <rect key="frame" x="1" y="898" width="988" height="16"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </scroller>
+                    <scroller key="verticalScroller" hidden="YES" wantsLayer="YES" verticalHuggingPriority="750" horizontal="NO" id="Cgv-FT-VuQ">
+                        <rect key="frame" x="224" y="17" width="15" height="102"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                    </scroller>
+                </scrollView>
+                <button verticalHuggingPriority="750" id="dci-WZ-4sM">
+                    <rect key="frame" x="926" y="918" width="74" height="32"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
+                    <buttonCell key="cell" type="push" title="Export" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="xfM-sn-1wh">
+                        <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                        <font key="font" metaFont="system"/>
+                    </buttonCell>
+                    <connections>
+                        <action selector="exportAction:" target="YBj-nQ-WgX" id="wx5-cS-nds"/>
+                    </connections>
+                </button>
+                <button verticalHuggingPriority="750" id="qCC-xr-5ZS">
+                    <rect key="frame" x="819" y="926" width="106" height="18"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
+                    <buttonCell key="cell" type="check" title="过滤无差异项" bezelStyle="regularSquare" imagePosition="left" inset="2" id="7qM-Dj-di2">
+                        <behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
+                        <font key="font" metaFont="system"/>
+                    </buttonCell>
+                    <connections>
+                        <action selector="filterSimilarItemAction:" target="YBj-nQ-WgX" id="RbW-XC-vmp"/>
+                    </connections>
+                </button>
+                <progressIndicator hidden="YES" maxValue="100" doubleValue="50" style="bar" id="865-rk-Lp5">
+                    <rect key="frame" x="709" y="925" width="100" height="20"/>
+                    <autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
+                </progressIndicator>
+            </subviews>
+            <point key="canvasLocation" x="-213" y="678"/>
+        </customView>
+    </objects>
+</document>

+ 11 - 4
KdanAutoTest/KdanAuto/Class/Norrmal/AutoTestAdvanceSettingView.swift

@@ -424,10 +424,17 @@ class AutoTestAdvanceSettingView : NSView, NSTableViewDataSource, NSTableViewDel
         let files = _autoTestObj?.compareFiles(fileName) ?? []
         
         if files.count > 0 {
-            let compareVC = CompareViewController.shared()
-            compareVC.setFiles(files)
-            let point = sender.convert(CGPoint(x: 0, y: 0), to: self)
-            compareVC.showIn(self, rect: NSRect.init(origin: point, size: sender.frame.size))
+            if (_autoTestObj as? StringAutoTest) != nil {
+                var compareVC = StringCompareViewController.shared()
+                compareVC.setFiles(files)
+                let point = sender.convert(CGPoint(x: 0, y: 0), to: self)
+                compareVC.showIn(self, rect: NSRect.init(origin: point, size: sender.frame.size))
+            }else {
+                let compareVC = CompareViewController.shared()
+                compareVC.setFiles(files)
+                let point = sender.convert(CGPoint(x: 0, y: 0), to: self)
+                compareVC.showIn(self, rect: NSRect.init(origin: point, size: sender.frame.size))
+            }
         }
     }
     

+ 17 - 6
KdanAutoTest/KdanAuto/Class/Norrmal/Cell/TestCaseCellView.swift

@@ -252,12 +252,23 @@ class TestCaseCellView : NSTableCellView, NSMenuDelegate {
         let files = _autoTestObj?.compareFiles() ?? []
         
         if nil != files && files.count > 0 {
-            let compareVC = CompareViewController.shared()
-            compareVC.setFiles(files)
-            
-            let point = sender.convert(CGPoint(x: 0, y: 0),
-                                       to: self.window?.contentView ?? self)
-            compareVC.showIn(self.window?.contentView ?? self, rect: NSRect.init(origin: point, size: sender.frame.size))
+            if (_autoTestObj as? StringAutoTest) != nil {
+                var compareVC = StringCompareViewController.shared()
+                
+                compareVC.setFiles(files)
+                
+                let point = sender.convert(CGPoint(x: 0, y: 0),
+                                           to: self.window?.contentView ?? self)
+                compareVC.showIn(self.window?.contentView ?? self, rect: NSRect.init(origin: point, size: sender.frame.size))
+            }else {
+                var compareVC = CompareViewController.shared()
+                
+                compareVC.setFiles(files)
+                
+                let point = sender.convert(CGPoint(x: 0, y: 0),
+                                           to: self.window?.contentView ?? self)
+                compareVC.showIn(self.window?.contentView ?? self, rect: NSRect.init(origin: point, size: sender.frame.size))
+            }
         }
         return
         

+ 1 - 1
KdanAutoTest/KdanAuto/ViewController.swift

@@ -410,7 +410,7 @@ class ViewController : NSViewController, SettingViewControllerDelegate, AutoTest
                 let id = ti["ID"] as! NSString
                 
                 let testObject = AutoTest.autoTestFor(fileType as NSString, id: id)
-                if (testObject?.selectedKeys().count != 0) {
+                if (testObject?.selectedKeys().count != 0 && testObject!.needCompareTest()) {
                     let tFiles = testObject?.compareFiles();
                     if (tFiles != nil && tFiles?.count != 0) {
                         files.addObjects(from: tFiles as! [Any])