Преглед изворни кода

聊天新增黑名单功能

Steven пре 2 месеци
родитељ
комит
d8bb7b9531
34 измењених фајлова са 1000 додато и 104 уклоњено
  1. 37 21
      KulexiuForTeacher/KulexiuForTeacher.xcodeproj/project.pbxproj
  2. 2 2
      KulexiuForTeacher/KulexiuForTeacher.xcodeproj/xcshareddata/xcschemes/KulexiuForTeacher.xcscheme
  3. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Chat/remove_blackList.imageset/Contents.json
  4. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Chat/remove_blackList.imageset/remove_blackList@2x.png
  5. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Chat/remove_blackList.imageset/remove_blackList@3x.png
  6. 2 2
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/AlertView/KSPublicAlertView.xib
  7. 9 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.h
  8. 16 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.m
  9. 8 1
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/ChatAddressViewController.h
  10. 31 28
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/ChatAddressViewController.m
  11. 10 4
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/ChatViewController.m
  12. 94 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/KSChatConversationViewController.m
  13. 19 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSChatTipsAlertView.h
  14. 59 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSChatTipsAlertView.m
  15. 87 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSChatTipsAlertView.xib
  16. 13 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSTXC2CChatViewController.m
  17. 32 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/Controller/GroupSettingViewController.m
  18. 2 1
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupMemberListCell.m
  19. 3 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.h
  20. 18 2
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.m
  21. 41 7
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.xib
  22. 1 1
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Model/GroupMemberModel.h
  23. 8 4
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Model/GroupMemberModel.m
  24. 3 3
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatAddressBodyView.m
  25. 20 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatBlackListBodyView.h
  26. 278 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatBlackListBodyView.m
  27. 2 1
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatNavView.h
  28. 27 4
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatNavView.m
  29. 44 8
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatNavView.xib
  30. 4 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ContractListCell.h
  31. 59 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ContractListCell.m
  32. 30 5
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ContractListCell.xib
  33. 17 10
      KulexiuForTeacher/Pods/TUIChat/TUIChat/UI_Classic/Chat/TUIBaseMessageController.m
  34. 2 0
      KulexiuForTeacher/Pods/TUIChat/TUIChat/UI_Classic/Chat/TUIBaseMessageControllerDelegate.h

+ 37 - 21
KulexiuForTeacher/KulexiuForTeacher.xcodeproj/project.pbxproj

@@ -316,6 +316,7 @@
 		BC106BB42A8F4BC9000759A9 /* LiveModuleService.m in Sources */ = {isa = PBXBuildFile; fileRef = BC106BB32A8F4BC9000759A9 /* LiveModuleService.m */; };
 		BC106C542A9365DE000759A9 /* ClassMemberEmptyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC106C512A9365DC000759A9 /* ClassMemberEmptyView.xib */; };
 		BC106C552A9365DE000759A9 /* ClassMemberEmptyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC106C522A9365DD000759A9 /* ClassMemberEmptyView.m */; };
+		BC108E212DA39DF400977076 /* ChatBlackListBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC108E202DA39DF400977076 /* ChatBlackListBodyView.m */; };
 		BC1191ED280E55CB00A716F7 /* EvaluateDetailModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1191EB280E55CA00A716F7 /* EvaluateDetailModel.m */; };
 		BC1191F0280E8A2800A716F7 /* TableCourseModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1191EF280E8A2800A716F7 /* TableCourseModel.m */; };
 		BC1191F3280EAB9600A716F7 /* AccompanyDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC1191F1280EAB9600A716F7 /* AccompanyDetailViewController.m */; };
@@ -1207,6 +1208,8 @@
 		BCFE54152817918600AD6786 /* MyIncomeListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCFE54132817918600AD6786 /* MyIncomeListCell.xib */; };
 		BCFE54182817BDFD00AD6786 /* IncomeHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFE54172817BDFD00AD6786 /* IncomeHeaderView.m */; };
 		BCFE541A2817BE0800AD6786 /* IncomeHeaderView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCFE54192817BE0800AD6786 /* IncomeHeaderView.xib */; };
+		BCFEBEA42DA3D1A1007F7A3D /* KSChatTipsAlertView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCFEBEA32DA3D1A1007F7A3D /* KSChatTipsAlertView.xib */; };
+		BCFEBEA52DA3D1A1007F7A3D /* KSChatTipsAlertView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCFEBEA22DA3D1A1007F7A3D /* KSChatTipsAlertView.m */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -1783,6 +1786,8 @@
 		BC106C512A9365DC000759A9 /* ClassMemberEmptyView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ClassMemberEmptyView.xib; sourceTree = "<group>"; };
 		BC106C522A9365DD000759A9 /* ClassMemberEmptyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ClassMemberEmptyView.m; sourceTree = "<group>"; };
 		BC106C532A9365DE000759A9 /* ClassMemberEmptyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassMemberEmptyView.h; sourceTree = "<group>"; };
+		BC108E1F2DA39DF400977076 /* ChatBlackListBodyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ChatBlackListBodyView.h; sourceTree = "<group>"; };
+		BC108E202DA39DF400977076 /* ChatBlackListBodyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ChatBlackListBodyView.m; sourceTree = "<group>"; };
 		BC1191EB280E55CA00A716F7 /* EvaluateDetailModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EvaluateDetailModel.m; sourceTree = "<group>"; };
 		BC1191EC280E55CB00A716F7 /* EvaluateDetailModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EvaluateDetailModel.h; sourceTree = "<group>"; };
 		BC1191EE280E8A2700A716F7 /* TableCourseModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableCourseModel.h; sourceTree = "<group>"; };
@@ -3217,6 +3222,9 @@
 		BCFE54162817BDFD00AD6786 /* IncomeHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IncomeHeaderView.h; sourceTree = "<group>"; };
 		BCFE54172817BDFD00AD6786 /* IncomeHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IncomeHeaderView.m; sourceTree = "<group>"; };
 		BCFE54192817BE0800AD6786 /* IncomeHeaderView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IncomeHeaderView.xib; sourceTree = "<group>"; };
+		BCFEBEA12DA3D1A1007F7A3D /* KSChatTipsAlertView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KSChatTipsAlertView.h; sourceTree = "<group>"; };
+		BCFEBEA22DA3D1A1007F7A3D /* KSChatTipsAlertView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KSChatTipsAlertView.m; sourceTree = "<group>"; };
+		BCFEBEA32DA3D1A1007F7A3D /* KSChatTipsAlertView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KSChatTipsAlertView.xib; sourceTree = "<group>"; };
 		CC310B10C17622ABB179BC7C /* libPods-KulexiuForTeacher.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-KulexiuForTeacher.a"; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
@@ -4094,6 +4102,8 @@
 			children = (
 				27F9CAEB27EC17AD003E0FE4 /* ChatAddressBodyView.h */,
 				27F9CAEC27EC17AD003E0FE4 /* ChatAddressBodyView.m */,
+				BC108E1F2DA39DF400977076 /* ChatBlackListBodyView.h */,
+				BC108E202DA39DF400977076 /* ChatBlackListBodyView.m */,
 				275B172727EB26920081FDEF /* ChatAddressHeaderView.h */,
 				275B172827EB26920081FDEF /* ChatAddressHeaderView.m */,
 				275B172A27EB269F0081FDEF /* ChatAddressHeaderView.xib */,
@@ -4598,6 +4608,9 @@
 				BC9EFE952C04804200CFA7B1 /* KSMuteTipsView.h */,
 				BC9EFE932C04804100CFA7B1 /* KSMuteTipsView.m */,
 				BC9EFE942C04804200CFA7B1 /* KSMuteTipsView.xib */,
+				BCFEBEA12DA3D1A1007F7A3D /* KSChatTipsAlertView.h */,
+				BCFEBEA22DA3D1A1007F7A3D /* KSChatTipsAlertView.m */,
+				BCFEBEA32DA3D1A1007F7A3D /* KSChatTipsAlertView.xib */,
 			);
 			path = TXCustom;
 			sourceTree = "<group>";
@@ -8038,7 +8051,7 @@
 			isa = PBXProject;
 			attributes = {
 				BuildIndependentTargetsInParallel = 1;
-				LastUpgradeCheck = 1620;
+				LastUpgradeCheck = 1630;
 				TargetAttributes = {
 					275E8A6327E18F2300DD3F6E = {
 						CreatedOnToolsVersion = 13.2.1;
@@ -8199,6 +8212,7 @@
 				BCB399B327F94B5A00AFF376 /* LTSCalendarBottomView.xib in Resources */,
 				BCC5840728A9FA8100BAB4CF /* cloud_animation_12.png in Resources */,
 				2708565327ED8B8C00EC8E72 /* GroupApplyChooseAllCell.xib in Resources */,
+				BCFEBEA42DA3D1A1007F7A3D /* KSChatTipsAlertView.xib in Resources */,
 				275E3DEE27F467BF0010EC30 /* LiveRoomBottomView.xib in Resources */,
 				BC4766212CE72806002574E5 /* MineEmptyIntroduceView.xib in Resources */,
 				BC14A61E28A0B5CE0086395C /* MineActionView.xib in Resources */,
@@ -8548,9 +8562,13 @@
 			);
 			inputFileListPaths = (
 			);
+			inputPaths = (
+			);
 			name = "[CP] Copy Pods Resources";
 			outputFileListPaths = (
 			);
+			outputPaths = (
+			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-KulexiuForTeacher/Pods-KulexiuForTeacher-resources.sh\"\n";
@@ -8563,9 +8581,13 @@
 			);
 			inputFileListPaths = (
 			);
+			inputPaths = (
+			);
 			name = "[CP] Embed Pods Frameworks";
 			outputFileListPaths = (
 			);
+			outputPaths = (
+			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
 			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-KulexiuForTeacher/Pods-KulexiuForTeacher-frameworks.sh\"\n";
@@ -8819,6 +8841,7 @@
 				BCED5CB4285083AC009A42DE /* ShareMusicViewController.m in Sources */,
 				BCF425E82AB96BDE00BCD942 /* HomeTenantView.m in Sources */,
 				BCDF82042A8A2919005F8B82 /* ClassMemberSettingHeadView.m in Sources */,
+				BC108E212DA39DF400977076 /* ChatBlackListBodyView.m in Sources */,
 				BCB9FA40286DA337005D766B /* GuideViewController.m in Sources */,
 				BC71DF252A8A014F003F165E /* KSImageDisplayView.m in Sources */,
 				BC31BF942B219C5700F7D538 /* ToneTuningBodyView.m in Sources */,
@@ -9256,6 +9279,7 @@
 				BC71DEF52A89F470003F165E /* TxClassroomChatOtherCell.m in Sources */,
 				BC14E4912AB30F8F000C4983 /* TenantCreateGroupViewController.m in Sources */,
 				2779331127E310960010E277 /* NSObject+ReadDocument.m in Sources */,
+				BCFEBEA52DA3D1A1007F7A3D /* KSChatTipsAlertView.m in Sources */,
 				BC8418462AC2D9FB00D8F90E /* PasswordCheckBodyView.m in Sources */,
 				BC3DE082280D88670027DC0E /* EvaluateListModel.m in Sources */,
 				BCDF821A2A8A2BEF005F8B82 /* CREmojiCollectionCell.m in Sources */,
@@ -9423,6 +9447,7 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
 				DEBUG_INFORMATION_FORMAT = dwarf;
+				DEVELOPMENT_TEAM = B2AP53HHTU;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -9484,6 +9509,7 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				DEVELOPMENT_TEAM = B2AP53HHTU;
 				ENABLE_NS_ASSERTIONS = NO;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -9512,8 +9538,7 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = KulexiuForTeacher/KulexiuForTeacher.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1.8.0;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
+				CURRENT_PROJECT_VERSION = 1.8.2;
 				ENABLE_BITCODE = NO;
 				ENABLE_MODULE_VERIFIER = YES;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -9558,7 +9583,7 @@
 					"$(PROJECT_DIR)/KulexiuForTeacher/Common/ThirdPart/UMSocialSDK/share/share_ios_6.10.4/SocialLibraries/QQ",
 					"$(PROJECT_DIR)/KulexiuForTeacher/Common/ThirdPart/UMSocialSDK/share/share_ios_6.10.4/UMSocialSDKPlugin",
 				);
-				MARKETING_VERSION = 1.8.1;
+				MARKETING_VERSION = 1.8.2;
 				MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
 				MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
 				OTHER_LDFLAGS = (
@@ -9688,8 +9713,7 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = KulexiuForTeacher/KulexiuForTeacher.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1.8.0;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
+				CURRENT_PROJECT_VERSION = 1.8.2;
 				ENABLE_BITCODE = NO;
 				ENABLE_MODULE_VERIFIER = YES;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -9734,7 +9758,7 @@
 					"$(PROJECT_DIR)/KulexiuForTeacher/Common/ThirdPart/UMSocialSDK/share/share_ios_6.10.4/SocialLibraries/QQ",
 					"$(PROJECT_DIR)/KulexiuForTeacher/Common/ThirdPart/UMSocialSDK/share/share_ios_6.10.4/UMSocialSDKPlugin",
 				);
-				MARKETING_VERSION = 1.8.1;
+				MARKETING_VERSION = 1.8.2;
 				MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
 				MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
 				OTHER_LDFLAGS = (
@@ -9860,7 +9884,6 @@
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
 				GENERATE_INFOPLIST_FILE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				MARKETING_VERSION = 1.0;
@@ -9878,7 +9901,6 @@
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
 				GENERATE_INFOPLIST_FILE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				MARKETING_VERSION = 1.0;
@@ -9895,7 +9917,6 @@
 			buildSettings = {
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.Colexiu.KulexiuForTeacherUITests;
@@ -9911,7 +9932,6 @@
 			buildSettings = {
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.Colexiu.KulexiuForTeacherUITests;
@@ -9959,6 +9979,7 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
 				DEBUG_INFORMATION_FORMAT = dwarf;
+				DEVELOPMENT_TEAM = B2AP53HHTU;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -9992,8 +10013,7 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = KulexiuForTeacher/KulexiuForTeacher.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1.8.0;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
+				CURRENT_PROJECT_VERSION = 1.8.2;
 				ENABLE_BITCODE = NO;
 				ENABLE_MODULE_VERIFIER = YES;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -10038,7 +10058,7 @@
 					"$(PROJECT_DIR)/KulexiuForTeacher/Common/ThirdPart/UMSocialSDK/share/share_ios_6.10.4/SocialLibraries/QQ",
 					"$(PROJECT_DIR)/KulexiuForTeacher/Common/ThirdPart/UMSocialSDK/share/share_ios_6.10.4/UMSocialSDKPlugin",
 				);
-				MARKETING_VERSION = 1.8.1;
+				MARKETING_VERSION = 1.8.2;
 				MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
 				MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
 				OTHER_LDFLAGS = (
@@ -10165,7 +10185,6 @@
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
 				GENERATE_INFOPLIST_FILE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				MARKETING_VERSION = 1.0;
@@ -10182,7 +10201,6 @@
 			buildSettings = {
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.Colexiu.KulexiuForTeacherUITests;
@@ -10230,6 +10248,7 @@
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
 				COPY_PHASE_STRIP = NO;
 				DEBUG_INFORMATION_FORMAT = dwarf;
+				DEVELOPMENT_TEAM = B2AP53HHTU;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				GCC_C_LANGUAGE_STANDARD = gnu11;
@@ -10263,8 +10282,7 @@
 				CLANG_ENABLE_MODULES = YES;
 				CODE_SIGN_ENTITLEMENTS = KulexiuForTeacher/KulexiuForTeacher.entitlements;
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 1.8.0;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
+				CURRENT_PROJECT_VERSION = 1.8.2;
 				ENABLE_BITCODE = NO;
 				ENABLE_MODULE_VERIFIER = YES;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -10309,7 +10327,7 @@
 					"$(PROJECT_DIR)/KulexiuForTeacher/Common/ThirdPart/UMSocialSDK/share/share_ios_6.10.4/SocialLibraries/QQ",
 					"$(PROJECT_DIR)/KulexiuForTeacher/Common/ThirdPart/UMSocialSDK/share/share_ios_6.10.4/UMSocialSDKPlugin",
 				);
-				MARKETING_VERSION = 1.8.1;
+				MARKETING_VERSION = 1.8.2;
 				MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++";
 				MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++17";
 				OTHER_LDFLAGS = (
@@ -10436,7 +10454,6 @@
 				BUNDLE_LOADER = "$(TEST_HOST)";
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
 				GENERATE_INFOPLIST_FILE = YES;
 				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				MARKETING_VERSION = 1.0;
@@ -10453,7 +10470,6 @@
 			buildSettings = {
 				CODE_SIGN_STYLE = Automatic;
 				CURRENT_PROJECT_VERSION = 1;
-				DEVELOPMENT_TEAM = B2AP53HHTU;
 				GENERATE_INFOPLIST_FILE = YES;
 				MARKETING_VERSION = 1.0;
 				PRODUCT_BUNDLE_IDENTIFIER = com.Colexiu.KulexiuForTeacherUITests;

+ 2 - 2
KulexiuForTeacher/KulexiuForTeacher.xcodeproj/xcshareddata/xcschemes/KulexiuForTeacher.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1620"
+   LastUpgradeVersion = "1630"
    version = "1.7">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -53,7 +53,7 @@
       </Testables>
    </TestAction>
    <LaunchAction
-      buildConfiguration = "TEST"
+      buildConfiguration = "DEV"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       launchStyle = "0"

+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Chat/remove_blackList.imageset/Contents.json

@@ -0,0 +1,22 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "filename" : "remove_blackList@2x.png",
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "remove_blackList@3x.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Chat/remove_blackList.imageset/remove_blackList@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Chat/remove_blackList.imageset/remove_blackList@3x.png


+ 2 - 2
KulexiuForTeacher/KulexiuForTeacher/Common/Base/AlertView/KSPublicAlertView.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
     <device id="retina6_1" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
     <objects>

+ 9 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.h

@@ -523,6 +523,15 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param faliure 失败
 + (void)imGroupMuteAllRequest:(NSString *)post groupId:(NSString *)groupId muteAll:(BOOL)muteAll success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
+// imGroupMember/allowPrivateChat
+/// 是否群成员发送私聊
+/// @param get get
+/// @param groupId 群ID
+/// @param allowPrivateChatFlag 是否允许私聊
+/// @param success 成功
+/// @param faliure 失败
++ (void)imGroupMemberAllowPrivateChatRequest:(NSString *)get groupId:(NSString *)groupId allowPrivateChatFlag:(BOOL)allowPrivateChatFlag success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 // /imGroupMember/groupMute
 
 /// 群成员禁言

+ 16 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.m

@@ -1120,6 +1120,22 @@
     [self request:post andWithUrl:url and:parm success:success faliure:faliure];
 }
 
+// imGroupMember/allowPrivateChat
+/// 是否群成员发送私聊
+/// @param get get
+/// @param groupId 群ID
+/// @param allowPrivateChatFlag 是否允许私聊
+/// @param success 成功
+/// @param faliure 失败
++ (void)imGroupMemberAllowPrivateChatRequest:(NSString *)get groupId:(NSString *)groupId allowPrivateChatFlag:(BOOL)allowPrivateChatFlag success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodJSON];
+    NSString *url = [NSString stringWithFormat:@"%@%@%@", hostURL, @"/api-teacher",@"/imGroupMember/allowPrivateChat"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:groupId forKey:@"groupId"];
+    [parm setValue:@(allowPrivateChatFlag) forKey:@"allowPrivateChatFlag"];
+    [self request:get andWithUrl:url and:parm success:success faliure:faliure];
+}
+
 // /imGroupMember/groupMute
 
 /// 群成员禁言

+ 8 - 1
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/ChatAddressViewController.h

@@ -9,6 +9,12 @@
 #import "JXCategoryView.h"
 #import "JXPagerView.h"
 
+typedef NS_ENUM(NSInteger, CHAT_ADDRESS) {
+    CHAT_ADDRESS_GROUP = 0,
+    CHAT_ADDRESS_PERSON,
+    CHAT_ADDRESS_BLACKLIST,
+};
+
 NS_ASSUME_NONNULL_BEGIN
 
 typedef void(^ScrollPageCallback)(NSInteger scrollIndex);
@@ -19,9 +25,10 @@ typedef void(^ScrollPageCallback)(NSInteger scrollIndex);
 @property (nonatomic, strong, readonly) JXCategoryTitleView *categoryView;
 @property (nonatomic, strong) NSArray <NSString *> *titles;
 
-- (void)scrollToChatList:(BOOL)scrollToChatList;
+- (void)scrollToChatList:(CHAT_ADDRESS)pageList;
 
 - (void)scrollActionCallback:(ScrollPageCallback)callback;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 31 - 28
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/ChatAddressViewController.m

@@ -10,6 +10,7 @@
 #import "JXCategoryView.h"
 #import "JXPagerListRefreshView.h"
 #import "ChatAddressBodyView.h"
+#import "ChatBlackListBodyView.h"
 
 @interface ChatAddressViewController ()<JXPagerViewDelegate, JXPagerMainTableViewGestureDelegate,JXCategoryViewDelegate>
 
@@ -60,26 +61,20 @@
     self.categoryView.listContainer = (id<JXCategoryViewListContainer>)self.pagerView.listContainerView;
 }
 
-
-
-
-- (void)searchRequest:(NSString *)searchKey {
-    if (self.listViewArray.count > self.selectedIndex) {
-        ChatAddressBodyView *listView = self.listViewArray[self.selectedIndex];
-        [listView refreshAndRequestData];
-    }
-}
-
 - (void)viewWillAppear:(BOOL)animated {
     [super viewWillAppear:animated];
     self.navigationController.interactivePopGestureRecognizer.enabled = YES;
     
     if (self.listViewArray.count > self.categoryView.selectedIndex) {
         id value = self.listViewArray[self.categoryView.selectedIndex];
-        if ([value isKindOfClass:[KSJXBodyView class]]) {
+        if ([value isKindOfClass:[ChatAddressBodyView class]]) {
             ChatAddressBodyView *listView = (ChatAddressBodyView *)value;
             [listView refreshAndRequestData];
         }
+        else if ([value isKindOfClass:[ChatBlackListBodyView class]]) {
+            ChatBlackListBodyView *listView = (ChatBlackListBodyView *)value;
+            [listView refreshAndRequestData];
+        }
     }
 }
 
@@ -115,16 +110,21 @@
 }
 
 - (id<JXPagerViewListViewDelegate>)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index {
-    ChatAddressBodyView *listView = [[ChatAddressBodyView alloc] init];
-    listView.naviController = self.navigationController;
-    [self.listViewArray replaceObjectAtIndex:index withObject:listView];
-    if (index == 0) {
-        listView.selectIndex = 0;
-    }else if (index == 1) {
-        listView.selectIndex = 1;
+    if (index == 2) {
+        ChatBlackListBodyView *listView = [[ChatBlackListBodyView alloc] init];
+        listView.naviController = self.navigationController;
+        [self.listViewArray replaceObjectAtIndex:index withObject:listView];
+        [listView beginFirstRefresh];
+        return listView;
+    }
+    else {
+        ChatAddressBodyView *listView = [[ChatAddressBodyView alloc] init];
+        listView.naviController = self.navigationController;
+        [self.listViewArray replaceObjectAtIndex:index withObject:listView];
+        listView.selectIndex = index;
+        [listView beginFirstRefresh];
+        return listView;
     }
-    [listView beginFirstRefresh];
-    return listView;
 }
 
 #pragma mark - JXCategoryViewDelegate
@@ -152,7 +152,7 @@
 
 - (NSMutableArray *)listViewArray {
     if (!_listViewArray) {
-        _listViewArray = [NSMutableArray arrayWithArray:@[@"",@""]];
+        _listViewArray = [NSMutableArray arrayWithArray:@[@"",@"",@""]];
     }
     return _listViewArray;
 }
@@ -174,18 +174,21 @@
 }
 
 
-- (void)scrollToChatList:(BOOL)scrollToChatList {
-    if (scrollToChatList) {
+- (void)scrollToChatList:(CHAT_ADDRESS)pageList {
+    if (pageList == 0) {
+        self.selectedIndex = 0;
+        [self.categoryView selectItemAtIndex:0];
+        [self.categoryView setDefaultSelectedIndex:0];
+    }
+    else if (pageList == 1) {
         self.selectedIndex = 1;
         [self.categoryView selectItemAtIndex:1];
         [self.categoryView setDefaultSelectedIndex:1];
-        // 刷新
     }
     else {
-        self.selectedIndex = 0;
-        [self.categoryView selectItemAtIndex:0];
-        [self.categoryView setDefaultSelectedIndex:0];
-        // 刷新
+        self.selectedIndex = 2;
+        [self.categoryView selectItemAtIndex:2];
+        [self.categoryView setDefaultSelectedIndex:2];
     }
 }
 /*

+ 10 - 4
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/ChatViewController.m

@@ -148,7 +148,7 @@
             [weakSelf contractScrollIndex:scrollIndex];
         }];
         self.contractList = list;
-        list.titles = @[@"群组",@"联系人"];
+        list.titles = @[@"群组",@"联系人",@"黑名单"];
         return list;
     }
 }
@@ -199,16 +199,22 @@
         case CHATNAVACTION_GROUP: // 群组
         {
             [self.categoryView selectItemAtIndex:1];
-            [self.contractList scrollToChatList:NO];
+            [self.contractList scrollToChatList:CHAT_ADDRESS_GROUP];
         }
             break;
         case CHATNAVACTION_CONTACTS:  // 联系人
         {
             [self.categoryView selectItemAtIndex:1];
-            [self.contractList scrollToChatList:YES];
+            [self.contractList scrollToChatList:CHAT_ADDRESS_PERSON];
         }
             break;
-        case CHATNAVACTION_SEND:
+        case CHATNAVACTION_BLACKLIST:
+        {
+            [self.categoryView selectItemAtIndex:1];
+            [self.contractList scrollToChatList:CHAT_ADDRESS_BLACKLIST];
+        }
+            break;
+        case CHATNAVACTION_CREATE:
         {
             if ([UserDefault(TENANT_ID) integerValue] > 0) {
                 TenantCreateGroupViewController *ctrl = [[TenantCreateGroupViewController alloc] init];

+ 94 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/KSChatConversationViewController.m

@@ -7,6 +7,7 @@
 
 #import "KSChatConversationViewController.h"
 #import "KSPublicAlertView.h"
+#import "UIButton+EnlargeEdge.h"
 
 @interface KSChatConversationViewController ()
 
@@ -14,6 +15,12 @@
 
 @property (nonatomic, strong) KSPublicAlertView *alertView;
 
+@property (nonatomic, assign) BOOL isInBlackList;
+
+@property (nonatomic, strong) UIButton *navButton;
+
+@property (nonatomic, strong) NSString *nickName;
+
 @end
 
 @implementation KSChatConversationViewController
@@ -27,6 +34,7 @@
 }
 
 - (void)configUI {
+    [self getBlackList];
     self.vc = [[KSTXC2CChatViewController alloc] init];
     if (![NSString isEmptyString:self.highlightKeyword]) {
         self.vc.highlightKeyword = self.highlightKeyword;
@@ -40,6 +48,7 @@
     MJWeakSelf;
     [[RACObserve(self.vc.conversationData, title) distinctUntilChanged] subscribeNext:^(NSString *title) {
         [weakSelf allocTitle:title];
+        weakSelf.nickName = title;
     }];
 
     [[RACObserve(self.vc.conversationData, otherSideTyping) distinctUntilChanged] subscribeNext:^(id otherSideTyping) {
@@ -54,6 +63,64 @@
     }];
 }
 
+- (void)navBtnClick {
+    
+    if (_isInBlackList) { // 移除
+        NSString *tipsString = @"移除黑名单后,对方可向您发送消息。";
+        if (![NSString isEmptyString:self.nickName]) {
+            tipsString = [NSString stringWithFormat:@"将%@移除黑名单后,对方可向您发送消息。", self.nickName];
+        }
+        MJWeakSelf;
+        self.alertView = [KSPublicAlertView shareInstanceWithTitle:@"移除黑名单" descMessage:tipsString leftTitle:@"取消" rightTitle:@"确认" cancelAction:^{
+
+        } sureAction:^{
+            [weakSelf removeChatPersonFromBlackList];
+        }];
+    }
+    else { // 添加
+        MJWeakSelf;
+        NSString *tipsString = @"加入黑名单后,对方无法向您发送消息。";
+        if (![NSString isEmptyString:self.nickName]) {
+            tipsString = [NSString stringWithFormat:@"将%@加入黑名单后,对方无法向您发送消息。", self.nickName];
+        }
+        self.alertView = [KSPublicAlertView shareInstanceWithTitle:@"添加黑名单" descMessage:tipsString leftTitle:@"取消" rightTitle:@"确认" cancelAction:^{
+
+        } sureAction:^{
+            [weakSelf addChatPersonToBlackList];
+        }];
+    }
+}
+
+- (void)addChatPersonToBlackList {
+    [[V2TIMManager sharedInstance] addToBlackList:@[self.conversation.userID] succ:^(NSArray<V2TIMFriendOperationResult *> *resultList) {
+        self.isInBlackList = YES;
+    } fail:^(int code, NSString *desc) {
+        // 如果错误 不修改
+    }];
+}
+
+- (void)removeChatPersonFromBlackList {
+    [[V2TIMManager sharedInstance] deleteFromBlackList:@[self.conversation.userID] succ:^(NSArray<V2TIMFriendOperationResult *> *resultList) {
+        self.isInBlackList = NO;
+    } fail:^(int code, NSString *desc) {
+        // 如果错误 不修改
+    }];
+}
+
+- (void)getBlackList {
+    [[V2TIMManager sharedInstance] getBlackList:^(NSArray<V2TIMFriendInfo *> *infoList) {
+        for (V2TIMFriendInfo *info in infoList) {
+            if ([info.userID isEqualToString:self.conversation.userID]) {
+                self.isInBlackList = YES;
+                return;
+            }
+        }
+        self.isInBlackList = NO;
+    } fail:^(int code, NSString *desc) {
+        self.isInBlackList = NO;
+    }];
+}
+
 - (void)clearConversation {
     
     NSString *conversationID = [NSString stringWithFormat:@"c2c_%@",self.conversation.userID];
@@ -96,6 +163,33 @@
     }
                                                  fail:nil];
 }
+
+- (void)setIsInBlackList:(BOOL)isInBlackList {
+    _isInBlackList = isInBlackList;
+    if (isInBlackList) {
+        [self.navButton setTitle:@"移除黑名单" forState:UIControlStateNormal];
+    }
+    else {
+        [self.navButton setTitle:@"加入黑名单" forState:UIControlStateNormal];
+    }
+}
+
+- (UIButton *)navButton {
+    if (!_navButton) {
+        UIButton *rightBt = [UIButton buttonWithType:UIButtonTypeCustom];
+        rightBt.frame =CGRectMake(0, 0, 100, 40);
+        rightBt.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, -30);
+        [rightBt setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10];
+        rightBt.titleLabel.font = [UIFont systemFontOfSize:14];
+        [rightBt setTitleColor:HexRGB(0x333333) forState:UIControlStateNormal];
+        [rightBt setTitle:@"" forState:UIControlStateNormal];
+        [rightBt addTarget:self action:@selector(navBtnClick) forControlEvents:UIControlEventTouchUpInside];
+        _navButton = rightBt;
+        UIBarButtonItem *rightItem = [[UIBarButtonItem alloc]initWithCustomView:rightBt];
+        self.navigationItem.rightBarButtonItem = rightItem;
+    }
+    return _navButton;
+}
 /*
 #pragma mark - Navigation
 

+ 19 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSChatTipsAlertView.h

@@ -0,0 +1,19 @@
+//
+//  KSChatTipsAlertView.h
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2025/4/7.
+//
+
+#import "BaseAlertView.h"
+
+typedef void(^ChatTipsAlertCallback)(void);
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSChatTipsAlertView : BaseAlertView
+
++ (instancetype)sharedInstanceWithTitle:(NSString *)descTitle sureTitle:(NSString *)sureTitle sureButtonColor:(UIColor *)bgColor callback:(ChatTipsAlertCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 59 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSChatTipsAlertView.m

@@ -0,0 +1,59 @@
+//
+//  KSChatTipsAlertView.m
+//  KulexiuForStudent
+//
+//  Created by 王智 on 2025/4/7.
+//
+
+#import "KSChatTipsAlertView.h"
+#import <UIView+Animation.h>
+
+@interface KSChatTipsAlertView ()
+
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+@property (weak, nonatomic) IBOutlet UIButton *sureButton;
+
+@property (nonatomic, copy) ChatTipsAlertCallback callback;
+
+@end
+
+@implementation KSChatTipsAlertView
+
++ (instancetype)sharedInstanceWithTitle:(NSString *)descTitle sureTitle:(NSString *)sureTitle sureButtonColor:(UIColor *)bgColor callback:(ChatTipsAlertCallback)callback {
+    KSChatTipsAlertView *alertView = [[[NSBundle mainBundle] loadNibNamed:@"KSChatTipsAlertView" owner:nil options:nil] firstObject];
+    alertView.descLabel.text = [NSString returnNoNullStringWithString:descTitle];
+    [alertView.sureButton setTitle:sureTitle forState:UIControlStateNormal];
+    [alertView.sureButton setBackgroundColor:bgColor];
+    if (callback) {
+        alertView.callback = callback;
+    }
+    [alertView showAlert];
+    return alertView;
+}
+
+- (void)showAlert {
+    [[NSObject getKeyWindow] addSubview:self];
+    [self mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.top.bottom.right.mas_equalTo([NSObject getKeyWindow]);
+    }];
+    [self setPopAnimation];
+}
+
+- (void)hiddenAction {
+    [self removeFromSuperview];
+}
+- (IBAction)sureButtonAction:(id)sender {
+    if (self.callback) {
+        self.callback();
+    }
+    [self hiddenAction];
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 87 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSChatTipsAlertView.xib

@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
+        <capability name="System colors in document resources" minToolsVersion="11.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="KSChatTipsAlertView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ybx-Cd-ag9">
+                    <rect key="frame" x="75" y="366" width="243" height="120"/>
+                    <subviews>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="对方拒收了您的消息" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UWR-XV-KrM">
+                            <rect key="frame" x="8" y="25" width="227" height="24"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="24" id="8OE-s0-BwZ"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                            <color key="textColor" red="0.40000000000000002" green="0.40000000000000002" blue="0.40000000000000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="a8J-Ke-fhV">
+                            <rect key="frame" x="56.666666666666657" y="69" width="130" height="36"/>
+                            <color key="backgroundColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="130" id="1PQ-gJ-xJQ"/>
+                                <constraint firstAttribute="height" constant="36" id="XRV-KR-hOa"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="我知道了"/>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="18"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                            <connections>
+                                <action selector="sureButtonAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="id4-X4-TSw"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="120" id="J7n-1S-Lcu"/>
+                        <constraint firstAttribute="bottom" secondItem="a8J-Ke-fhV" secondAttribute="bottom" constant="15" id="Kyr-8N-rge"/>
+                        <constraint firstItem="UWR-XV-KrM" firstAttribute="leading" secondItem="ybx-Cd-ag9" secondAttribute="leading" constant="8" id="N3g-OZ-ZdW"/>
+                        <constraint firstAttribute="width" constant="243" id="TI0-i0-s8U"/>
+                        <constraint firstItem="a8J-Ke-fhV" firstAttribute="centerX" secondItem="ybx-Cd-ag9" secondAttribute="centerX" id="gbn-xy-9y9"/>
+                        <constraint firstAttribute="trailing" secondItem="UWR-XV-KrM" secondAttribute="trailing" constant="8" id="hV7-Uj-efE"/>
+                        <constraint firstItem="UWR-XV-KrM" firstAttribute="top" secondItem="ybx-Cd-ag9" secondAttribute="top" constant="25" id="sdc-cc-yiK"/>
+                        <constraint firstItem="a8J-Ke-fhV" firstAttribute="top" secondItem="UWR-XV-KrM" secondAttribute="bottom" constant="20" id="yuo-eK-PfI"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="10"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstItem="ybx-Cd-ag9" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="6oR-ur-sWi"/>
+                <constraint firstItem="ybx-Cd-ag9" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="jeY-yE-WeB"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="descLabel" destination="UWR-XV-KrM" id="HPx-5U-im3"/>
+                <outlet property="sureButton" destination="a8J-Ke-fhV" id="oif-CX-CFC"/>
+            </connections>
+            <point key="canvasLocation" x="45" y="20"/>
+        </view>
+    </objects>
+    <resources>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 13 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSTXC2CChatViewController.m

@@ -12,6 +12,7 @@
 #import "TUILinkCellData.h"
 #import "TUIMessageController.h"
 #import "TUIMessageDataProvider.h"
+#import "KSChatTipsAlertView.h"
 
 #define kC2CTypingTime 30.0
 
@@ -22,6 +23,7 @@
 
 @property(nonatomic, assign) BOOL sendTypingBaseCondationInVC;
 
+@property (nonatomic, strong) KSChatTipsAlertView *alertView;
 
 @end
 
@@ -137,4 +139,15 @@
           NSLog(@"Fail");
         }];
 }
+
+#pragma mark - TUIBaseMessageControllerDelegate
+
+- (void)messageController:(TUIBaseMessageController *)controller sendMsgError:(int)code desc:(nonnull NSString *)desc {
+    if (code == 20007) {
+        [self.view endEditing:YES];
+        self.alertView = [KSChatTipsAlertView sharedInstanceWithTitle:@"对方拒收了您的消息" sureTitle:@"我知道了" sureButtonColor:THEMECOLOR callback:^{
+            
+        }];
+    }
+}
 @end

+ 32 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/Controller/GroupSettingViewController.m

@@ -39,6 +39,8 @@
 
 @property (nonatomic, assign) BOOL isMute;
 
+@property (nonatomic, assign) BOOL allowPrivateChatFlag;
+
 @end
 
 @implementation GroupSettingViewController
@@ -122,9 +124,11 @@
                 NSData *jsonData = [jsonString mj_JSONData];
                 NSDictionary *configJson = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
                 self.isMute = [configJson ks_boolValueForKey:@"mute"];
+                self.allowPrivateChatFlag = [subDic ks_boolValueForKey:@"allowPrivateChatFlag"];
             }
             else {
                 self.isMute = NO;
+                self.allowPrivateChatFlag = NO;
             }
             [self refreshUI];
         }
@@ -185,6 +189,7 @@
 
 - (void)refreshUI {
     self.bodyView.isMute = self.isMute;
+    self.bodyView.allowPrivateChatFlag = self.allowPrivateChatFlag;
     MJWeakSelf;
     [self.bodyView configWithSource:self.sourceModel callback:^(GROUPSETTING type) {
         [weakSelf operationWithType:type];
@@ -296,11 +301,38 @@
             [self.navigationController pushViewController:ctrl animated:YES];
         }
             break;
+        case GROUPSETTING_PRIVATECHAT:
+        {
+            if (self.sourceModel) {
+                [self allowPrivateChatAction];
+            }
+            else {
+                [LOADING_MANAGER MBShowAUTOHidingInWindow:@"您已不在当前群聊"];
+            }
+        }
+            break;
         default:
             break;
     }
 }
 
+- (void)allowPrivateChatAction {
+    BOOL allowPrivateChatFlag = !self.allowPrivateChatFlag;
+    [KSNetworkingManager imGroupMemberAllowPrivateChatRequest:KS_GET groupId:self.groupId allowPrivateChatFlag:allowPrivateChatFlag success:^(NSDictionary * _Nonnull dic) {
+        if ([dic ks_integerValueForKey:@"code"] == 200) {
+            [LOADING_MANAGER KSShowMsg:@"设置成功" promptCompletion:^{
+                [self requestData];
+            }];
+        }
+        else {
+            self.bodyView.allowPrivateChatFlag = self.allowPrivateChatFlag;
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        self.bodyView.allowPrivateChatFlag = self.allowPrivateChatFlag;
+    }];
+}
+
 - (void)muteAction {
     BOOL isMute = !self.isMute;
     [KSNetworkingManager imGroupMuteAllRequest:KS_POST groupId:self.groupId muteAll:isMute success:^(NSDictionary * _Nonnull dic) {

+ 2 - 1
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupMemberListCell.m

@@ -52,7 +52,8 @@
             self.memberName.text = model.nickname;
         }
         NSString *imUserId = model.imUserId;
-        if ([imUserId isEqualToString:UserDefault(IM_USERID)]) {
+        
+        if ([imUserId isEqualToString:UserDefault(IM_USERID)] || model.allowPrivateChatFlag == NO) {
             self.chatButton.hidden = YES;
             self.chatButton.userInteractionEnabled = NO;
         }

+ 3 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.h

@@ -20,6 +20,7 @@ typedef NS_ENUM(NSInteger, GROUPSETTING) {
     GROUPSETTING_MUTE,  // 静言
     GROUPSETTING_BANLIST, // 禁言列表
     GROUPSETTING_GROUPINTRODUCE, // 群介绍
+    GROUPSETTING_PRIVATECHAT, // 是否禁止私聊
 };
 
 
@@ -38,6 +39,8 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, assign) BOOL isOn;
 
 @property (nonatomic, assign) BOOL isMute;
+// 是否允许私聊
+@property (nonatomic, assign) BOOL allowPrivateChatFlag;
 
 + (instancetype)shareInstance;
 

+ 18 - 2
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.m

@@ -142,6 +142,8 @@ typedef void(^ChooseMemberCallback)(NSString *targetId);
 
 @property (weak, nonatomic) IBOutlet UILabel *groupDesc;
 
+@property (weak, nonatomic) IBOutlet UIButton *privateChatSwitchButton;
+
 @end
 
 @implementation GroupSettingBodyView
@@ -369,6 +371,14 @@ typedef void(^ChooseMemberCallback)(NSString *targetId);
 }
 
 
+- (IBAction)privateChatAction:(id)sender {
+    self.allowPrivateChatFlag = !self.allowPrivateChatFlag;
+    if (self.callback) {
+        self.callback(GROUPSETTING_PRIVATECHAT);
+    }
+}
+
+
 - (IBAction)displayBanList:(id)sender {
     if (self.callback) {
         self.callback(GROUPSETTING_BANLIST);
@@ -394,6 +404,12 @@ typedef void(^ChooseMemberCallback)(NSString *targetId);
     [self.muteButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
 }
 
+- (void)setAllowPrivateChatFlag:(BOOL)allowPrivateChatFlag {
+    _allowPrivateChatFlag = allowPrivateChatFlag;
+    NSString *imageName = allowPrivateChatFlag ? @"switch_off" : @"switch_on";
+    [self.privateChatSwitchButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
+}
+
 /***
  Owner("群主"),
  Admin("管理员"),
@@ -433,10 +449,10 @@ typedef void(^ChooseMemberCallback)(NSString *targetId);
 - (CGFloat)getViewHeight:(NSString *)roleType {
     CGFloat bottomSpace = IS_iPhoneX ? iPhoneXSafeBottomMargin : 20;
     if ([self.groupRoleType isEqualToString:@"Owner"] || [self.groupRoleType isEqualToString:@"Admin"]) {
-        return 857 + bottomSpace;
+        return 924 + bottomSpace;
     }
     else {
-        return 747 + bottomSpace;
+        return 814 + bottomSpace;
     }
 }
 /*

+ 41 - 7
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
     <device id="retina6_1" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -11,7 +11,7 @@
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
         <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="GroupSettingBodyView">
-            <rect key="frame" x="0.0" y="0.0" width="414" height="989"/>
+            <rect key="frame" x="0.0" y="0.0" width="414" height="1079"/>
             <autoresizingMask key="autoresizingMask"/>
             <subviews>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AOx-4a-71e">
@@ -299,7 +299,7 @@
                     </connections>
                 </view>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="H5y-Vp-Aux">
-                    <rect key="frame" x="0.0" y="723" width="414" height="55"/>
+                    <rect key="frame" x="0.0" y="790" width="414" height="55"/>
                     <subviews>
                         <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mine_next" translatesAutoresizingMaskIntoConstraints="NO" id="dhO-9D-vfB">
                             <rect key="frame" x="395" y="20.5" width="7" height="14"/>
@@ -329,7 +329,7 @@
                     </connections>
                 </view>
                 <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="9Zk-Ss-xf8">
-                    <rect key="frame" x="28" y="808" width="358" height="44"/>
+                    <rect key="frame" x="28" y="875" width="358" height="44"/>
                     <color key="backgroundColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                     <constraints>
                         <constraint firstAttribute="height" constant="44" id="zlf-6G-YkC"/>
@@ -520,6 +520,36 @@
                         <outletCollection property="gestureRecognizers" destination="qcN-so-hbi" appends="YES" id="M2T-Ma-wbb"/>
                     </connections>
                 </view>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="BkA-Cg-LHm">
+                    <rect key="frame" x="0.0" y="723" width="414" height="55"/>
+                    <subviews>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="H1z-Qu-g5t">
+                            <rect key="frame" x="352" y="7.5" width="47" height="40"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="40" id="JlM-j3-i7B"/>
+                                <constraint firstAttribute="width" constant="47" id="wna-Rs-MYX"/>
+                            </constraints>
+                            <state key="normal" image="switch_off"/>
+                            <connections>
+                                <action selector="privateChatAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="8Vc-w1-8MD"/>
+                            </connections>
+                        </button>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" layoutMarginsFollowReadableWidth="YES" text="拒绝接收群成员私聊" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="J7i-Lb-X2M">
+                            <rect key="frame" x="16" y="18" width="143" height="19.5"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                            <color key="textColor" red="0.1019607843" green="0.1019607843" blue="0.1019607843" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <constraints>
+                        <constraint firstItem="J7i-Lb-X2M" firstAttribute="centerY" secondItem="BkA-Cg-LHm" secondAttribute="centerY" id="AN6-qk-wjg"/>
+                        <constraint firstAttribute="height" constant="55" id="IiQ-Nv-caf"/>
+                        <constraint firstAttribute="trailing" secondItem="H1z-Qu-g5t" secondAttribute="trailing" constant="15" id="p3m-3b-mR2"/>
+                        <constraint firstItem="H1z-Qu-g5t" firstAttribute="centerY" secondItem="BkA-Cg-LHm" secondAttribute="centerY" id="tS1-dI-nQd"/>
+                        <constraint firstItem="J7i-Lb-X2M" firstAttribute="leading" secondItem="BkA-Cg-LHm" secondAttribute="leading" constant="16" id="x6J-3V-L0b"/>
+                    </constraints>
+                </view>
             </subviews>
             <color key="backgroundColor" red="0.96470588235294119" green="0.97254901960784312" blue="0.97647058823529409" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
             <constraints>
@@ -530,22 +560,25 @@
                 <constraint firstItem="AOx-4a-71e" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="10" id="6sx-4K-fmr"/>
                 <constraint firstAttribute="trailing" secondItem="0hZ-Dj-wqy" secondAttribute="trailing" id="7J3-AE-4RE"/>
                 <constraint firstItem="aOO-cS-gdV" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="7Ml-qH-PPT"/>
-                <constraint firstItem="H5y-Vp-Aux" firstAttribute="top" secondItem="aOO-cS-gdV" secondAttribute="bottom" constant="12" id="7dy-Ff-zSg"/>
                 <constraint firstItem="0hZ-Dj-wqy" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="AoA-pe-YVq"/>
                 <constraint firstAttribute="trailing" secondItem="H5y-Vp-Aux" secondAttribute="trailing" id="DZc-LC-mJn"/>
                 <constraint firstItem="fRV-DB-sBs" firstAttribute="top" secondItem="AOx-4a-71e" secondAttribute="bottom" constant="12" id="E1k-Ju-fB8"/>
                 <constraint firstItem="tp6-8D-B5D" firstAttribute="top" secondItem="hNX-kx-Qhp" secondAttribute="bottom" id="Fso-tE-6re"/>
                 <constraint firstAttribute="trailing" secondItem="aOO-cS-gdV" secondAttribute="trailing" id="Ggg-Dr-4dw"/>
+                <constraint firstItem="H5y-Vp-Aux" firstAttribute="top" secondItem="BkA-Cg-LHm" secondAttribute="bottom" constant="12" id="J1s-aL-J9m"/>
                 <constraint firstItem="AOx-4a-71e" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="JaT-tL-Lg5"/>
                 <constraint firstItem="fRV-DB-sBs" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="KfE-Ms-nB3"/>
                 <constraint firstItem="hNX-kx-Qhp" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Ki4-NK-uXf"/>
+                <constraint firstItem="BkA-Cg-LHm" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="LSQ-h0-4Jd"/>
                 <constraint firstItem="9Zk-Ss-xf8" firstAttribute="top" secondItem="H5y-Vp-Aux" secondAttribute="bottom" constant="30" id="N1t-gx-92V"/>
+                <constraint firstItem="BkA-Cg-LHm" firstAttribute="top" secondItem="aOO-cS-gdV" secondAttribute="bottom" constant="12" id="OOm-0q-UD2"/>
                 <constraint firstAttribute="trailing" secondItem="tp6-8D-B5D" secondAttribute="trailing" id="OxD-TF-5Rg"/>
                 <constraint firstItem="tp6-8D-B5D" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="QgK-Kv-2Jt"/>
                 <constraint firstAttribute="trailing" secondItem="351-sB-JCZ" secondAttribute="trailing" id="RVK-hp-Anr"/>
                 <constraint firstItem="DCz-5K-rHE" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Utq-mZ-4EV"/>
                 <constraint firstAttribute="trailing" secondItem="AOx-4a-71e" secondAttribute="trailing" id="VHK-38-OtQ"/>
                 <constraint firstItem="fy6-IY-oQY" firstAttribute="top" secondItem="UZO-j7-eJs" secondAttribute="bottom" id="XRi-7P-2HU"/>
+                <constraint firstAttribute="trailing" secondItem="BkA-Cg-LHm" secondAttribute="trailing" id="XeX-Kc-jne"/>
                 <constraint firstAttribute="trailing" secondItem="fRV-DB-sBs" secondAttribute="trailing" id="XuH-sa-ebf"/>
                 <constraint firstItem="9Zk-Ss-xf8" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="28" id="awA-Kz-NgN"/>
                 <constraint firstItem="fy6-IY-oQY" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="bnE-VF-wGj"/>
@@ -579,9 +612,10 @@
                 <outlet property="memberCount" destination="v6l-tz-OXe" id="6cy-BV-LFo"/>
                 <outlet property="memberView" destination="HI1-5o-vEr" id="O4K-9B-P99"/>
                 <outlet property="muteButton" destination="3mj-vH-cZt" id="jaq-9l-IXB"/>
+                <outlet property="privateChatSwitchButton" destination="H1z-Qu-g5t" id="F9i-HF-WMz"/>
                 <outlet property="switchButton" destination="fl2-Rm-1E9" id="xTR-c2-UCT"/>
             </connections>
-            <point key="canvasLocation" x="136.23188405797103" y="11.049107142857142"/>
+            <point key="canvasLocation" x="136.23188405797103" y="41.183035714285715"/>
         </view>
         <tapGestureRecognizer id="hZ3-TO-Qmd">
             <connections>

+ 1 - 1
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Model/GroupMemberModel.h

@@ -25,7 +25,7 @@
 @property (nonatomic, strong) NSString *imUserId;
 
 @property (nonatomic, strong) NSString *groupRoleType;
-
+@property (nonatomic, assign) BOOL allowPrivateChatFlag;
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
 - (instancetype)initWithDictionary:(NSDictionary *)dict;

+ 8 - 4
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Model/GroupMemberModel.m

@@ -19,6 +19,7 @@ NSString *const kGroupMemberModelGroupId = @"groupId";
 NSString *const kGroupMemberModelCreateTime = @"createTime";
 NSString *const kGroupMemberModelImUserId = @"imUserId";
 NSString *const kGroupMemberModelGroupRoleType = @"groupRoleType";
+NSString *const kGroupMemberModelAllowPrivateChatFlag = @"allowPrivateChatFlag";
 
 @interface GroupMemberModel ()
 
@@ -39,6 +40,7 @@ NSString *const kGroupMemberModelGroupRoleType = @"groupRoleType";
 @synthesize createTime = _createTime;
 @synthesize imUserId = _imUserId;
 @synthesize groupRoleType = _groupRoleType;
+@synthesize allowPrivateChatFlag = _allowPrivateChatFlag;
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
 {
@@ -62,7 +64,8 @@ NSString *const kGroupMemberModelGroupRoleType = @"groupRoleType";
             self.groupId = [self objectOrNilForKey:kGroupMemberModelGroupId fromDictionary:dict];
             self.createTime = [self objectOrNilForKey:kGroupMemberModelCreateTime fromDictionary:dict];
             self.imUserId = [self objectOrNilForKey:kGroupMemberModelImUserId fromDictionary:dict];
-        self.groupRoleType = [self objectOrNilForKey:kGroupMemberModelGroupRoleType fromDictionary:dict];
+            self.groupRoleType = [self objectOrNilForKey:kGroupMemberModelGroupRoleType fromDictionary:dict];
+            self.allowPrivateChatFlag = [[self objectOrNilForKey:kGroupMemberModelAllowPrivateChatFlag fromDictionary:dict] boolValue];
 
     }
     
@@ -84,7 +87,7 @@ NSString *const kGroupMemberModelGroupRoleType = @"groupRoleType";
     [mutableDict setValue:self.createTime forKey:kGroupMemberModelCreateTime];
     [mutableDict setValue:self.imUserId forKey:kGroupMemberModelImUserId];
     [mutableDict setValue:self.groupRoleType forKey:kGroupMemberModelGroupRoleType];
-
+    [mutableDict setValue:[NSNumber numberWithBool:self.allowPrivateChatFlag] forKey:kGroupMemberModelAllowPrivateChatFlag];
     return [NSDictionary dictionaryWithDictionary:mutableDict];
 }
 
@@ -122,7 +125,7 @@ NSString *const kGroupMemberModelGroupRoleType = @"groupRoleType";
     self.createTime = [aDecoder decodeObjectForKey:kGroupMemberModelCreateTime];
     self.imUserId = [aDecoder decodeObjectForKey:kGroupMemberModelImUserId];
     self.groupRoleType = [aDecoder decodeObjectForKey:kGroupMemberModelGroupRoleType];
-
+    self.allowPrivateChatFlag = [aDecoder decodeBoolForKey:kGroupMemberModelAllowPrivateChatFlag];
     return self;
 }
 
@@ -140,7 +143,7 @@ NSString *const kGroupMemberModelGroupRoleType = @"groupRoleType";
     [aCoder encodeObject:_createTime forKey:kGroupMemberModelCreateTime];
     [aCoder encodeObject:_imUserId forKey:kGroupMemberModelImUserId];
     [aCoder encodeObject:_groupRoleType forKey:kGroupMemberModelGroupRoleType];
-
+    [aCoder encodeBool:_allowPrivateChatFlag forKey:kGroupMemberModelAllowPrivateChatFlag];
 }
 
 - (id)copyWithZone:(NSZone *)zone
@@ -160,6 +163,7 @@ NSString *const kGroupMemberModelGroupRoleType = @"groupRoleType";
         copy.createTime = [self.createTime copyWithZone:zone];
         copy.imUserId = [self.imUserId copyWithZone:zone];
         copy.groupRoleType = [self.groupRoleType copyWithZone:zone];
+        copy.allowPrivateChatFlag = self.allowPrivateChatFlag;
     }
     
     return copy;

+ 3 - 3
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatAddressBodyView.m

@@ -67,9 +67,9 @@
         [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
             make.left.right.top.bottom.mas_equalTo(self);
         }];
-        UIView *headView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 10)];
-        headView.backgroundColor = HexRGB(0xf8f9fc);
-        self.tableView.tableHeaderView = headView;
+//        UIView *headView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 10)];
+//        headView.backgroundColor = HexRGB(0xf8f9fc);
+//        self.tableView.tableHeaderView = headView;
         
         UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 10)];
         bottomView.backgroundColor = HexRGB(0xf8f9fc);

+ 20 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatBlackListBodyView.h

@@ -0,0 +1,20 @@
+//
+//  ChatBlackListBodyView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2025/4/7.
+//
+
+#import "KSJXBodyView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface ChatBlackListBodyView : KSJXBodyView
+
+@property (nonatomic, strong) NSString *searchKey;
+
+- (void)refreshAndRequestData;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 278 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatBlackListBodyView.m

@@ -0,0 +1,278 @@
+//
+//  ChatBlackListBodyView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2025/4/7.
+//
+
+#import "ChatBlackListBodyView.h"
+#import "StateView.h"
+#import "Reachability.h"
+#import "ContractListCell.h"
+#import "FriendListModel.h"
+#import "KSChatListSearchView.h"
+#import <ImSDK_Plus/ImSDK_Plus.h>
+#import "KSPublicAlertView.h"
+
+@interface ChatBlackListBodyView ()<UITableViewDelegate,UITableViewDataSource>
+
+@property (nonatomic, strong) StateView *promptView;
+@property (nonatomic, strong) UIView *promptPlaceView;
+
+@property (nonatomic, assign) BOOL networkAvaiable; // 网络是否可用
+
+@property (nonatomic, strong) NSMutableArray *blackListArray;
+
+@property (nonatomic, strong) KSChatListSearchView *searchView;
+
+@property (nonatomic, strong) KSPublicAlertView *alertView;
+
+@end
+
+@implementation ChatBlackListBodyView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        self.backgroundColor = HexRGB(0xf8f9fc);
+        self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
+        self.tableView.backgroundColor = HexRGB(0xf8f9fc);
+        self.tableView.showsVerticalScrollIndicator = NO;
+
+        self.tableView.dataSource = self;
+        self.tableView.delegate = self;
+        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+        self.tableView.rowHeight = 70;
+        [self addSubview:self.tableView];
+        
+        [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.right.top.bottom.mas_equalTo(self);
+        }];
+        
+        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 10)];
+        bottomView.backgroundColor = HexRGB(0xf8f9fc);
+        self.tableView.tableFooterView = bottomView;
+        
+        [self.tableView registerNib:[UINib nibWithNibName:@"ContractListCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"ContractListCell"];
+        MJWeakSelf;
+        self.tableView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
+            [weakSelf resetParamenter];
+            [weakSelf requestData];
+        }];
+    }
+    return self;
+}
+
+- (void)endRefresh {
+    [self.tableView.mj_header endRefreshing];
+}
+
+- (void)refreshAndRequestData {
+    [self resetParamenter];
+    [self requestData];
+}
+
+- (void)resetParamenter {
+    [self setPromptString:@"暂无黑名单" imageName:@"wd_img_zwsj" inView:self.tableView];
+    [self.blackListArray removeAllObjects];
+    [self.tableView reloadData];
+}
+
+- (void)beginRefreshImmediately {
+    [self.tableView.mj_header beginRefreshing];
+}
+
+- (void)selectCellAtIndexPath:(NSIndexPath *)indexPath {
+    
+    if (self.lastSelectedIndexPath == indexPath) {
+        return;
+    }
+    if (self.lastSelectedIndexPath != nil) {
+        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.lastSelectedIndexPath];
+        [cell setSelected:NO animated:NO];
+    }
+    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
+    [cell setSelected:YES animated:NO];
+    self.lastSelectedIndexPath = indexPath;
+}
+
+- (void)layoutSubviews {
+    [super layoutSubviews];
+    CGFloat height = [self.searchView getViewHeight];
+    if (![self.subviews containsObject:self.searchView]) {
+        [self addSubview:self.searchView];
+        self.searchView.frame = CGRectMake(0, 0, self.bounds.size.width, height);
+    }
+
+    [self.searchView configText:@"请输入用户名称"];
+    [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
+        make.top.mas_equalTo(self).mas_offset(height);
+    }];
+}
+
+- (void)beginFirstRefresh {
+    if (!self.isHeaderRefreshed) {
+        [self beginRefreshImmediately];
+    }
+}
+
+
+- (void)requestData {
+    [[V2TIMManager sharedInstance] getBlackList:^(NSArray<V2TIMFriendInfo *> *infoList) {
+        [self endRefresh];
+        for (V2TIMFriendInfo *info in infoList) {
+            FriendListModel *model = [[FriendListModel alloc] init];
+            model.friendAvatar = info.userFullInfo.faceURL;
+            model.friendNickname = info.userFullInfo.nickName;
+            model.imFriendId = info.userID;
+            if ([info.userID hasSuffix:@"TEACHER"]) {
+                model.roleType = @"TEACHER";
+            }
+            else {
+                model.roleType = @"STUDENT";
+            }
+            [self.blackListArray addObject:model];
+        }
+        [self changePromptLabelStateWithArray:self.blackListArray];
+        [self.tableView reloadData];
+        
+    } fail:^(int code, NSString *desc) {
+        [self endRefresh];
+        if (self.networkAvaiable == NO) {
+            [self setPromptString:@"暂无网络" imageName:@"no_networking" inView:self.tableView];
+        }
+        [self.blackListArray removeAllObjects];
+        [self.tableView reloadData];
+        [self changePromptLabelStateWithArray:self.blackListArray];
+    }];
+}
+
+
+#pragma mark - UITableViewDataSource, UITableViewDelegate
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    return self.blackListArray.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    ContractListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ContractListCell"];
+    FriendListModel *model = self.blackListArray[indexPath.row];
+    MJWeakSelf;
+    [cell configBlackListWithSource:model callback:^(NSString * _Nonnull imUserId, NSString * _Nullable nickName) {
+        [weakSelf removeBlackList:imUserId nickName:nickName];
+    }];
+
+    return cell;
+}
+
+- (void)removeBlackList:(NSString *)imUserId nickName:(NSString *)nickName {
+    MJWeakSelf;
+    NSString *tipsString = [NSString stringWithFormat:@"将%@移除黑名单后,对方可向您发送消息。", nickName];
+    self.alertView = [KSPublicAlertView shareInstanceWithTitle:@"移除黑名单" descMessage:tipsString leftTitle:@"取消" rightTitle:@"确认" cancelAction:^{
+
+    } sureAction:^{
+        [weakSelf removeChatPersonFromBlackList:imUserId];
+    }];
+}
+
+- (void)removeChatPersonFromBlackList:(NSString *)imUserId {
+    [[V2TIMManager sharedInstance] deleteFromBlackList:@[imUserId] succ:^(NSArray<V2TIMFriendOperationResult *> *resultList) {
+        [self refreshAndRequestData];
+    } fail:^(int code, NSString *desc) {
+        // 如果错误 不修改
+    }];
+}
+
+/**
+ 设置没有数据时的显示
+ 
+ @param promptString 提示语
+ @param imgName 图片名称
+ @param view 显示在什么地方
+ */
+- (void)setPromptString:(NSString *)promptString imageName:(NSString *)imgName inView:(UIView *)view {
+    if (self.promptView != nil) {
+        [self.promptView removeFromSuperview];
+    }
+    else {
+        self.promptView = [[StateView alloc]init];
+        self.promptView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight - 300);
+    }
+    _promptPlaceView = view;
+    //当请求不到数据时 ,自定义提示view 将会出现;
+    self.promptView.imageName = imgName;
+    self.promptView.alpha = 0.0f;
+    [self.promptView setText:promptString];
+    [view addSubview:self.promptView];
+}
+
+// 结束刷新后调用方法
+- (void)changePromptLabelStateWithArray:(NSMutableArray *)array {
+    NSInteger count;
+    if (array.count) {
+        count = array.count;
+    } else {
+        count = 0;
+    }
+    
+    [UIView animateWithDuration:0.1 animations:^{
+        [[self promptView] setAlpha:count ? 0.0f :1.0f ] ;
+        
+    }] ;
+    
+}
+
+- (BOOL)networkAvaiable {
+    return [self checkNetworkAvaiable];
+}
+
+- (BOOL)checkNetworkAvaiable {
+    BOOL isExistenceNetwork = YES;
+    Reachability *reach = [Reachability reachabilityWithHostName:@"www.apple.com"];
+    switch ([reach currentReachabilityStatus]) {
+        case NotReachable:
+            isExistenceNetwork = NO;
+            //NSLog(@"notReachable");
+            break;
+        case ReachableViaWiFi:
+            isExistenceNetwork = YES;
+            //NSLog(@"WIFI");
+            break;
+        case ReachableViaWWAN:
+            isExistenceNetwork = YES;
+            //NSLog(@"3G");
+            break;
+    }
+    return isExistenceNetwork;
+}
+#pragma mark --- lazying
+- (NSMutableArray *)blackListArray {
+    if (!_blackListArray) {
+        _blackListArray = [NSMutableArray array];
+    }
+    return _blackListArray;
+}
+
+- (KSChatListSearchView *)searchView {
+    if (!_searchView) {
+        _searchView = [KSChatListSearchView shareInstance];
+        MJWeakSelf;
+        [_searchView topSearchCallback:^{
+            [weakSelf searchAction];
+        }];
+    }
+    return _searchView;
+}
+
+- (void)searchAction {
+    self.searchKey = self.searchView.searchField.text;
+    [self refreshAndRequestData];
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 2 - 1
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatNavView.h

@@ -11,7 +11,8 @@ typedef NS_ENUM(NSInteger, CHATNAVACTION) {
     CHATNAVACTION_LIST = 0,     // 聊天列表
     CHATNAVACTION_GROUP,    // 创建群组
     CHATNAVACTION_CONTACTS, // 联系人
-    CHATNAVACTION_SEND,     // 群发记录
+    CHATNAVACTION_BLACKLIST, // 黑名单
+    CHATNAVACTION_CREATE,     // 创建群聊
 };
 
 typedef void(^ChatNavCallback)(CHATNAVACTION action);

+ 27 - 4
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatNavView.m

@@ -8,15 +8,22 @@
 #import "ChatNavView.h"
 
 @interface ChatNavView ()
+@property (weak, nonatomic) IBOutlet UIView *lineView;
 
 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *dotLeft;
 
+@property (weak, nonatomic) IBOutlet UIView *chatView;
 @property (weak, nonatomic) IBOutlet UILabel *chatLabel;
 
+@property (weak, nonatomic) IBOutlet UIView *groupView;
 @property (weak, nonatomic) IBOutlet UILabel *groupLabel;
 
+@property (weak, nonatomic) IBOutlet UIView *presonView;
 @property (weak, nonatomic) IBOutlet UILabel *personLabel;
 
+@property (weak, nonatomic) IBOutlet UIView *blackView;
+@property (weak, nonatomic) IBOutlet UILabel *blackLabel;
+
 @property (nonatomic, copy) ChatNavCallback callback;
 
 @property (nonatomic, assign) NSInteger chooseIndex;
@@ -48,10 +55,10 @@
     self.chooseIndex = chatIndex;
 }
 
-// 群发记录
+// 创建群聊
 - (IBAction)GroupSendingAction:(id)sender {
     if (self.callback) {
-        self.callback(CHATNAVACTION_SEND);
+        self.callback(CHATNAVACTION_CREATE);
     }
 }
 
@@ -76,6 +83,8 @@
         [self.groupLabel setFont:[UIFont systemFontOfSize:16.0f]];
         [self.personLabel setTextColor:HexRGB(0x777777)];
         [self.personLabel setFont:[UIFont systemFontOfSize:16.0f]];
+        [self.blackLabel setTextColor:HexRGB(0x777777)];
+        [self.blackLabel setFont:[UIFont systemFontOfSize:16.0f]];
         left = 26.0f;
     }
     else if (chooseIndex == 1) {
@@ -85,22 +94,36 @@
         [self.groupLabel setFont:[UIFont systemFontOfSize:18.0f weight:UIFontWeightMedium]];
         [self.personLabel setTextColor:HexRGB(0x777777)];
         [self.personLabel setFont:[UIFont systemFontOfSize:16.0f]];
+        [self.blackLabel setTextColor:HexRGB(0x777777)];
+        [self.blackLabel setFont:[UIFont systemFontOfSize:16.0f]];
         left = 94.0f;
     }
-    else {
+    else if (chooseIndex == 2) {
         [self.chatLabel setTextColor:HexRGB(0x777777)];
         [self.chatLabel setFont:[UIFont systemFontOfSize:16.0f]];
         [self.groupLabel setTextColor:HexRGB(0x777777)];
         [self.groupLabel setFont:[UIFont systemFontOfSize:16.0f]];
         [self.personLabel setTextColor:HexRGB(0x333333)];
         [self.personLabel setFont:[UIFont systemFontOfSize:18.0f weight:UIFontWeightMedium]];
+        [self.blackLabel setTextColor:HexRGB(0x777777)];
+        [self.blackLabel setFont:[UIFont systemFontOfSize:16.0f]];
         left = 170.0f;
     }
+    else {
+        [self.chatLabel setTextColor:HexRGB(0x777777)];
+        [self.chatLabel setFont:[UIFont systemFontOfSize:16.0f]];
+        [self.groupLabel setTextColor:HexRGB(0x777777)];
+        [self.groupLabel setFont:[UIFont systemFontOfSize:16.0f]];
+        [self.personLabel setTextColor:HexRGB(0x777777)];
+        [self.personLabel setFont:[UIFont systemFontOfSize:16.0f]];
+        [self.blackLabel setTextColor:HexRGB(0x333333)];
+        [self.blackLabel setFont:[UIFont systemFontOfSize:18.0f weight:UIFontWeightMedium]];
+        left = 250.0f;
+    }
 
     [UIView animateWithDuration:0.3f animations:^{
         self.dotLeft.constant = left;
     }];
-    
 }
 /*
 // Only override drawRect: if you perform custom drawing.

+ 44 - 8
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ChatNavView.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
     <device id="retina6_0" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
         <capability name="System colors in document resources" minToolsVersion="11.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -30,7 +30,7 @@
                             </connections>
                         </button>
                         <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yrU-9H-Hbl">
-                            <rect key="frame" x="0.0" y="0.0" width="215" height="44"/>
+                            <rect key="frame" x="0.0" y="0.0" width="291.33333333333331" height="44"/>
                             <subviews>
                                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="adv-7f-atF">
                                     <rect key="frame" x="24" y="36" width="16" height="4"/>
@@ -127,10 +127,10 @@
                                     </connections>
                                 </view>
                                 <view tag="1003" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dTE-57-dju">
-                                    <rect key="frame" x="136" y="0.0" width="79" height="44"/>
+                                    <rect key="frame" x="136" y="0.0" width="77.666666666666686" height="44"/>
                                     <subviews>
                                         <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="联系人" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4Dn-gZ-oVZ">
-                                            <rect key="frame" x="15" y="11.999999999999998" width="49" height="20.333333333333329"/>
+                                            <rect key="frame" x="14.999999999999996" y="11.999999999999998" width="47.666666666666657" height="20.333333333333329"/>
                                             <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                             <color key="textColor" red="0.46666666670000001" green="0.46666666670000001" blue="0.46666666670000001" alpha="1" colorSpace="calibratedRGB"/>
                                             <nil key="highlightedColor"/>
@@ -148,21 +148,46 @@
                                         <outletCollection property="gestureRecognizers" destination="wjg-RA-bzc" appends="YES" id="eOZ-Zc-dRW"/>
                                     </connections>
                                 </view>
+                                <view tag="1004" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Ry9-Oc-X2m">
+                                    <rect key="frame" x="213.66666666666666" y="0.0" width="77.666666666666657" height="44"/>
+                                    <subviews>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="黑名单" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FUd-Qz-nzE">
+                                            <rect key="frame" x="14.999999999999996" y="11.999999999999998" width="47.666666666666657" height="20.333333333333329"/>
+                                            <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                                            <color key="textColor" red="0.46666666670000001" green="0.46666666670000001" blue="0.46666666670000001" alpha="1" colorSpace="calibratedRGB"/>
+                                            <nil key="highlightedColor"/>
+                                        </label>
+                                    </subviews>
+                                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                    <gestureRecognizers/>
+                                    <constraints>
+                                        <constraint firstItem="FUd-Qz-nzE" firstAttribute="leading" secondItem="Ry9-Oc-X2m" secondAttribute="leading" constant="15" id="RpT-Gm-eHn"/>
+                                        <constraint firstItem="FUd-Qz-nzE" firstAttribute="centerY" secondItem="Ry9-Oc-X2m" secondAttribute="centerY" id="kUV-3g-fcn"/>
+                                        <constraint firstAttribute="trailing" secondItem="FUd-Qz-nzE" secondAttribute="trailing" constant="15" id="w4q-uD-RLr"/>
+                                        <constraint firstItem="FUd-Qz-nzE" firstAttribute="centerX" secondItem="Ry9-Oc-X2m" secondAttribute="centerX" id="yQA-vg-mwz"/>
+                                    </constraints>
+                                    <connections>
+                                        <outletCollection property="gestureRecognizers" destination="brw-qj-vlN" appends="YES" id="Ga6-O9-Xwc"/>
+                                    </connections>
+                                </view>
                             </subviews>
                             <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                             <constraints>
+                                <constraint firstItem="Ry9-Oc-X2m" firstAttribute="leading" secondItem="dTE-57-dju" secondAttribute="trailing" id="2Pw-vr-j7P"/>
                                 <constraint firstAttribute="bottom" secondItem="U5I-bi-mi0" secondAttribute="bottom" id="Am3-vG-ffd"/>
                                 <constraint firstAttribute="bottom" secondItem="2R7-iV-Sqq" secondAttribute="bottom" id="BE7-Aa-kg0"/>
+                                <constraint firstAttribute="trailing" secondItem="Ry9-Oc-X2m" secondAttribute="trailing" id="HVw-Bw-XbX"/>
                                 <constraint firstItem="adv-7f-atF" firstAttribute="leading" secondItem="yrU-9H-Hbl" secondAttribute="leading" constant="24" id="MiK-89-Q1b"/>
                                 <constraint firstItem="dTE-57-dju" firstAttribute="top" secondItem="yrU-9H-Hbl" secondAttribute="top" id="RuC-h2-F09"/>
                                 <constraint firstItem="2R7-iV-Sqq" firstAttribute="top" secondItem="yrU-9H-Hbl" secondAttribute="top" id="T8E-uI-NHV"/>
-                                <constraint firstAttribute="trailing" secondItem="dTE-57-dju" secondAttribute="trailing" id="TMt-GV-8gG"/>
                                 <constraint firstItem="2R7-iV-Sqq" firstAttribute="leading" secondItem="U5I-bi-mi0" secondAttribute="trailing" id="Uwt-hf-Laf"/>
                                 <constraint firstItem="U5I-bi-mi0" firstAttribute="top" secondItem="yrU-9H-Hbl" secondAttribute="top" id="YmA-Nd-oxg"/>
                                 <constraint firstItem="U5I-bi-mi0" firstAttribute="leading" secondItem="yrU-9H-Hbl" secondAttribute="leading" id="c0Z-gs-gkg"/>
+                                <constraint firstItem="Ry9-Oc-X2m" firstAttribute="top" secondItem="yrU-9H-Hbl" secondAttribute="top" id="isg-nU-BpC"/>
                                 <constraint firstItem="dTE-57-dju" firstAttribute="leading" secondItem="2R7-iV-Sqq" secondAttribute="trailing" id="knb-rM-g4k"/>
                                 <constraint firstAttribute="bottom" secondItem="adv-7f-atF" secondAttribute="bottom" constant="4" id="o7a-y5-dIc"/>
                                 <constraint firstAttribute="bottom" secondItem="dTE-57-dju" secondAttribute="bottom" id="r1K-50-17j"/>
+                                <constraint firstAttribute="bottom" secondItem="Ry9-Oc-X2m" secondAttribute="bottom" id="xXy-Em-lll"/>
                             </constraints>
                         </view>
                     </subviews>
@@ -188,11 +213,17 @@
             <nil key="simulatedBottomBarMetrics"/>
             <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
             <connections>
+                <outlet property="blackLabel" destination="FUd-Qz-nzE" id="q1z-4V-ViW"/>
+                <outlet property="blackView" destination="Ry9-Oc-X2m" id="rgj-cj-ljF"/>
                 <outlet property="chatLabel" destination="9iF-re-XDo" id="PtD-hw-7Bw"/>
-                <outlet property="dotLeft" destination="MiK-89-Q1b" id="9kU-rP-gNd"/>
+                <outlet property="chatView" destination="U5I-bi-mi0" id="MWd-S0-Pk3"/>
+                <outlet property="dotLeft" destination="MiK-89-Q1b" id="EQd-4P-sIg"/>
                 <outlet property="dotView" destination="e7v-cD-P17" id="shw-Fo-mes"/>
                 <outlet property="groupLabel" destination="tXa-sZ-KZH" id="flO-9b-rdc"/>
+                <outlet property="groupView" destination="2R7-iV-Sqq" id="PoY-Da-mdH"/>
+                <outlet property="lineView" destination="adv-7f-atF" id="lXK-9M-WsG"/>
                 <outlet property="personLabel" destination="4Dn-gZ-oVZ" id="Os5-jH-6AD"/>
+                <outlet property="presonView" destination="dTE-57-dju" id="R0j-D2-Wgh"/>
             </connections>
             <point key="canvasLocation" x="113.84615384615384" y="-108.05687203791469"/>
         </view>
@@ -211,11 +242,16 @@
                 <action selector="tapAction:" destination="iN0-l3-epB" id="6U7-Fi-av7"/>
             </connections>
         </tapGestureRecognizer>
+        <tapGestureRecognizer id="brw-qj-vlN">
+            <connections>
+                <action selector="tapAction:" destination="iN0-l3-epB" id="I6y-Ei-ZXb"/>
+            </connections>
+        </tapGestureRecognizer>
     </objects>
     <resources>
         <image name="group_create" width="22" height="22"/>
         <systemColor name="systemRedColor">
-            <color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <color red="1" green="0.23137254900000001" blue="0.18823529410000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </systemColor>
     </resources>
 </document>

+ 4 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ContractListCell.h

@@ -9,12 +9,16 @@
 
 typedef void(^ContractUserDetailCallback)(NSString * _Nullable imUserId);
 
+typedef void(^RemoveBlackListCallback)(NSString * _Nonnull imUserId, NSString * _Nullable nickName);
+
 NS_ASSUME_NONNULL_BEGIN
 
 @interface ContractListCell : UITableViewCell
 
 - (void)configWithSource:(id)sourceModel callback:(ContractUserDetailCallback)callback;
 
+- (void)configBlackListWithSource:(id)source callback:(RemoveBlackListCallback)callback;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 59 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ContractListCell.m

@@ -20,7 +20,18 @@
 
 @property (nonatomic, strong) NSString *imUserId;
 
+@property (nonatomic, assign) BOOL showActionButton;
+
 @property (nonatomic, copy) ContractUserDetailCallback callback;
+
+@property (nonatomic, copy) RemoveBlackListCallback actionCallback;
+
+@property (weak, nonatomic) IBOutlet UIImageView *blackListRemoveImg;
+
+@property (weak, nonatomic) IBOutlet UIButton *blackListActionButton;
+
+@property (nonatomic, strong) NSString *nickName;
+
 @end
 
 @implementation ContractListCell
@@ -35,6 +46,7 @@
     if (callback) {
         self.callback = callback;
     }
+    self.showActionButton = NO;
     if ([sourceModel isKindOfClass:[FriendListModel class]]) {
         FriendListModel *model = sourceModel;
         [self.friendAvatar sd_setImageWithURL:[NSURL URLWithString:[model.friendAvatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:CHAT_USER_DEFAULT_LOGO]];
@@ -56,12 +68,59 @@
     }
 }
 
+- (void)configBlackListWithSource:(id)source callback:(RemoveBlackListCallback)callback {
+    if (callback) {
+        self.actionCallback = callback;
+    }
+    self.showActionButton = YES;
+    if ([source isKindOfClass:[FriendListModel class]]) {
+        FriendListModel *model = source;
+        [self.friendAvatar sd_setImageWithURL:[NSURL URLWithString:[model.friendAvatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:CHAT_USER_DEFAULT_LOGO]];
+        if ([NSString isEmptyString:model.friendNickname]) {
+            self.friendName.text = [NSString stringWithFormat:@"游客%@",model.imFriendId];
+        }
+        else {
+            self.friendName.text = model.friendNickname;
+        }
+        self.nickName = [NSString returnNoNullStringWithString:model.friendNickname];
+        self.friendName.text = [NSString returnNoNullStringWithString:model.friendNickname];
+        
+        if ([model.roleType isEqualToString:@"TEACHER"]) {
+            self.roleTypeView.hidden = NO;
+        }
+        else {
+            self.roleTypeView.hidden = YES;
+        }
+        self.imUserId = model.imFriendId;
+    }
+}
+
 - (IBAction)detailAction:(id)sender {
     if (self.callback) {
         self.callback(self.imUserId);
     }
 }
 
+- (IBAction)removeBlackList:(id)sender {
+    if (self.actionCallback) {
+        self.actionCallback(self.imUserId, self.nickName);
+    }
+}
+
+- (void)setShowActionButton:(BOOL)showActionButton {
+    _showActionButton = showActionButton;
+    if (showActionButton) {
+        self.blackListRemoveImg.hidden = NO;
+        self.blackListActionButton.hidden = NO;
+        self.blackListActionButton.userInteractionEnabled = YES;
+    }
+    else {
+        self.blackListRemoveImg.hidden = YES;
+        self.blackListActionButton.hidden = YES;
+        self.blackListActionButton.userInteractionEnabled = NO;
+    }
+}
+
 - (void)setSelected:(BOOL)selected animated:(BOOL)animated {
     [super setSelected:selected animated:animated];
 

+ 30 - 5
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/View/ContractListCell.xib

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23727" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
     <device id="retina6_1" orientation="portrait" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23721"/>
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -30,7 +30,7 @@
                         </userDefinedRuntimeAttributes>
                     </imageView>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="张老师" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="8fl-pa-IHx">
-                        <rect key="frame" x="69" y="31.5" width="49" height="22"/>
+                        <rect key="frame" x="69" y="31.5" width="48" height="22"/>
                         <constraints>
                             <constraint firstAttribute="height" constant="22" id="XK0-bc-cnh"/>
                         </constraints>
@@ -46,7 +46,7 @@
                         </constraints>
                     </view>
                     <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="group_role_teacher" translatesAutoresizingMaskIntoConstraints="NO" id="gE4-tY-dGd">
-                        <rect key="frame" x="121" y="32.5" width="41" height="20"/>
+                        <rect key="frame" x="120" y="32.5" width="41" height="20"/>
                         <constraints>
                             <constraint firstAttribute="height" constant="20" id="1XY-Ml-PVI"/>
                             <constraint firstAttribute="width" constant="41" id="ZOO-Kl-p8S"/>
@@ -59,27 +59,51 @@
                             <action selector="detailAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="Fvq-zV-UzN"/>
                         </connections>
                     </button>
+                    <imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" image="remove_blackList" translatesAutoresizingMaskIntoConstraints="NO" id="6Hc-H7-yzC">
+                        <rect key="frame" x="354" y="33.5" width="18" height="18"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="18" id="ky7-JZ-mvE"/>
+                            <constraint firstAttribute="width" constant="18" id="vDf-6i-eQI"/>
+                        </constraints>
+                    </imageView>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="MZq-hC-fXF">
+                        <rect key="frame" x="344" y="22.5" width="40" height="40"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="40" id="2h6-xh-PS5"/>
+                            <constraint firstAttribute="height" constant="40" id="RLI-gl-qwS"/>
+                        </constraints>
+                        <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                        <connections>
+                            <action selector="removeBlackList:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="4id-i3-Rpm"/>
+                        </connections>
+                    </button>
                 </subviews>
                 <constraints>
                     <constraint firstItem="8fl-pa-IHx" firstAttribute="centerY" secondItem="vI1-v5-uMm" secondAttribute="centerY" id="9PL-c3-9J3"/>
                     <constraint firstItem="ZD7-0R-OoK" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="72" id="DPF-fF-mtx"/>
                     <constraint firstItem="MXb-8G-ALr" firstAttribute="trailing" secondItem="vI1-v5-uMm" secondAttribute="trailing" id="EoE-Zg-osE"/>
+                    <constraint firstItem="6Hc-H7-yzC" firstAttribute="centerY" secondItem="gE4-tY-dGd" secondAttribute="centerY" id="G2D-h6-1JT"/>
                     <constraint firstItem="MXb-8G-ALr" firstAttribute="bottom" secondItem="vI1-v5-uMm" secondAttribute="bottom" id="Gg2-u4-CJM"/>
-                    <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="gE4-tY-dGd" secondAttribute="trailing" constant="20" id="H6V-ug-KuF"/>
                     <constraint firstItem="gE4-tY-dGd" firstAttribute="centerY" secondItem="8fl-pa-IHx" secondAttribute="centerY" id="L3q-sA-1sR"/>
                     <constraint firstItem="MXb-8G-ALr" firstAttribute="leading" secondItem="vI1-v5-uMm" secondAttribute="leading" id="Pmj-tI-btJ"/>
                     <constraint firstAttribute="bottom" secondItem="ZD7-0R-OoK" secondAttribute="bottom" id="Qy0-N6-dQU"/>
+                    <constraint firstItem="6Hc-H7-yzC" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="gE4-tY-dGd" secondAttribute="trailing" constant="10" id="b8h-dm-XBm"/>
+                    <constraint firstAttribute="trailing" secondItem="6Hc-H7-yzC" secondAttribute="trailing" constant="12" id="cF6-6c-ln9"/>
                     <constraint firstItem="8fl-pa-IHx" firstAttribute="leading" secondItem="vI1-v5-uMm" secondAttribute="trailing" constant="11" id="fdz-o1-pUv"/>
+                    <constraint firstAttribute="trailing" secondItem="MZq-hC-fXF" secondAttribute="trailing" id="ffW-o5-seO"/>
                     <constraint firstItem="MXb-8G-ALr" firstAttribute="top" secondItem="vI1-v5-uMm" secondAttribute="top" id="htL-zq-vdY"/>
                     <constraint firstAttribute="trailing" secondItem="ZD7-0R-OoK" secondAttribute="trailing" id="qkd-cr-TeW"/>
                     <constraint firstItem="gE4-tY-dGd" firstAttribute="leading" secondItem="8fl-pa-IHx" secondAttribute="trailing" constant="3" id="v9q-dL-wZX"/>
                     <constraint firstItem="vI1-v5-uMm" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="vgm-ZS-Nds"/>
                     <constraint firstItem="vI1-v5-uMm" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="14" id="yHs-ea-3Xd"/>
+                    <constraint firstItem="MZq-hC-fXF" firstAttribute="centerY" secondItem="gE4-tY-dGd" secondAttribute="centerY" id="zro-YP-ylE"/>
                 </constraints>
             </tableViewCellContentView>
             <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
             <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
             <connections>
+                <outlet property="blackListActionButton" destination="MZq-hC-fXF" id="1YN-k2-hkl"/>
+                <outlet property="blackListRemoveImg" destination="6Hc-H7-yzC" id="pDj-OD-ymb"/>
                 <outlet property="detailButton" destination="MXb-8G-ALr" id="AH6-wh-uKi"/>
                 <outlet property="friendAvatar" destination="vI1-v5-uMm" id="Nob-dw-1A8"/>
                 <outlet property="friendName" destination="8fl-pa-IHx" id="o2J-m8-ozl"/>
@@ -91,5 +115,6 @@
     <resources>
         <image name="chat_personLogo" width="44" height="44"/>
         <image name="group_role_teacher" width="41" height="20"/>
+        <image name="remove_blackList" width="18" height="18"/>
     </resources>
 </document>

+ 17 - 10
KulexiuForTeacher/Pods/TUIChat/TUIChat/UI_Classic/Chat/TUIBaseMessageController.m

@@ -357,17 +357,24 @@
         return;
     }
     
-    NSString *errorMsg = @"";
-    if (self.isMsgNeedReadReceipt && code == ERR_SDK_INTERFACE_NOT_SUPPORT) {
-        errorMsg = [NSString stringWithFormat:@"%@%@", TUIKitLocalizableString(TUIKitErrorUnsupportIntefaceMessageRead),
-                                         TUIKitLocalizableString(TUIKitErrorUnsupporInterfaceSuffix)];
-    } else {
-        errorMsg = [TUITool convertIMError:code msg:desc];
+    // 处理 20007 回调
+    if (self.delegate && [self.delegate respondsToSelector:@selector(messageController:sendMsgError:desc:)]) {
+        [self.delegate messageController:self sendMsgError:code desc:desc];
+    }
+    
+    if (code != 20007) {
+        NSString *errorMsg = @"";
+        if (self.isMsgNeedReadReceipt && code == ERR_SDK_INTERFACE_NOT_SUPPORT) {
+            errorMsg = [NSString stringWithFormat:@"%@%@", TUIKitLocalizableString(TUIKitErrorUnsupportIntefaceMessageRead),
+                                             TUIKitLocalizableString(TUIKitErrorUnsupporInterfaceSuffix)];
+        } else {
+            errorMsg = [TUITool convertIMError:code msg:desc];
+        }
+        errorMsg = @"消息发送失败";
+        UIAlertController *ac = [UIAlertController alertControllerWithTitle:errorMsg message:nil preferredStyle:UIAlertControllerStyleAlert];
+        [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Confirm) style:UIAlertActionStyleDefault handler:nil]];
+        [self presentViewController:ac animated:YES completion:nil];
     }
-    errorMsg = @"消息发送失败";
-    UIAlertController *ac = [UIAlertController alertControllerWithTitle:errorMsg message:nil preferredStyle:UIAlertControllerStyleAlert];
-    [ac tuitheme_addAction:[UIAlertAction actionWithTitle:TIMCommonLocalizableString(Confirm) style:UIAlertActionStyleDefault handler:nil]];
-    [self presentViewController:ac animated:YES completion:nil];
 }
 
 - (void)sendMessage:(V2TIMMessage *)message {

+ 2 - 0
KulexiuForTeacher/Pods/TUIChat/TUIChat/UI_Classic/Chat/TUIBaseMessageControllerDelegate.h

@@ -177,6 +177,8 @@ NS_ASSUME_NONNULL_BEGIN
  */
 - (CGFloat)getTopMarginByCustomView;
 
+// 自定义错误消息发送回调
+- (void)messageController:(TUIBaseMessageController *)controller sendMsgError:(int)code desc:(NSString *)desc;
 @end
 
 NS_ASSUME_NONNULL_END