Browse Source

群禁言

Steven 9 months ago
parent
commit
597f2f910e
39 changed files with 3145 additions and 20 deletions
  1. 104 0
      KulexiuForTeacher/KulexiuForTeacher.xcodeproj/project.pbxproj
  2. 1 1
      KulexiuForTeacher/KulexiuForTeacher.xcodeproj/xcshareddata/xcschemes/KulexiuForTeacher.xcscheme
  3. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Converstaion/mute_tips.imageset/Contents.json
  4. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Converstaion/mute_tips.imageset/mute_tips@2x.png
  5. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Converstaion/mute_tips.imageset/mute_tips@3x.png
  6. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/cancel_dark.imageset/Contents.json
  7. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/cancel_dark.imageset/cancel_dark@2x.png
  8. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/cancel_dark.imageset/cancel_dark@3x.png
  9. 34 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.h
  10. 58 1
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.m
  11. 24 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/Controller/GroupBanListViewController.h
  12. 210 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/Controller/GroupBanListViewController.m
  13. 19 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/BanStudentListCell.h
  14. 48 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/BanStudentListCell.m
  15. 99 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/BanStudentListCell.xib
  16. 18 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBodyView.h
  17. 540 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBodyView.m
  18. 45 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBottomView.h
  19. 140 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBottomView.m
  20. 122 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBottomView.xib
  21. 33 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanNavView.h
  22. 96 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanNavView.m
  23. 162 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanNavView.xib
  24. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentChooseDisplayCell.h
  25. 51 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentChooseDisplayCell.m
  26. 93 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentChooseDisplayCell.xib
  27. 24 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentPreviewView.h
  28. 146 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentPreviewView.m
  29. 110 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentPreviewView.xib
  30. 18 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSMuteTipsView.h
  31. 24 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSMuteTipsView.m
  32. 53 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSMuteTipsView.xib
  33. 530 1
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSTXGroupChatViewController.m
  34. 70 4
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/Controller/GroupSettingViewController.m
  35. 8 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.h
  36. 78 4
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.m
  37. 107 9
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.xib
  38. 3 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Model/GroupMemberModel.h
  39. 11 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Model/GroupMemberModel.m

+ 104 - 0
KulexiuForTeacher/KulexiuForTeacher.xcodeproj/project.pbxproj

@@ -793,6 +793,20 @@
 		BC9AA0D02ABC3D3A00CD954D /* KSComplainImageDisplayView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC9AA0CF2ABC3D3A00CD954D /* KSComplainImageDisplayView.xib */; };
 		BC9AA0D42ABC430B00CD954D /* KSCustomLoadingView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC9AA0D12ABC430A00CD954D /* KSCustomLoadingView.xib */; };
 		BC9AA0D52ABC430B00CD954D /* KSCustomLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9AA0D22ABC430A00CD954D /* KSCustomLoadingView.m */; };
+		BC9EFE962C04804200CFA7B1 /* KSMuteTipsView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9EFE932C04804100CFA7B1 /* KSMuteTipsView.m */; };
+		BC9EFE972C04804200CFA7B1 /* KSMuteTipsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC9EFE942C04804200CFA7B1 /* KSMuteTipsView.xib */; };
+		BC9EFEAF2C0480A500CFA7B1 /* GroupBanListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9EFE992C0480A500CFA7B1 /* GroupBanListViewController.m */; };
+		BC9EFEB02C0480A500CFA7B1 /* BanStudentListCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9EFE9D2C0480A500CFA7B1 /* BanStudentListCell.m */; };
+		BC9EFEB12C0480A500CFA7B1 /* BanStudentListCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC9EFE9E2C0480A500CFA7B1 /* BanStudentListCell.xib */; };
+		BC9EFEB22C0480A500CFA7B1 /* GroupBanBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9EFEA02C0480A500CFA7B1 /* GroupBanBodyView.m */; };
+		BC9EFEB32C0480A500CFA7B1 /* GroupBanBottomView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9EFEA22C0480A500CFA7B1 /* GroupBanBottomView.m */; };
+		BC9EFEB42C0480A500CFA7B1 /* GroupBanBottomView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC9EFEA32C0480A500CFA7B1 /* GroupBanBottomView.xib */; };
+		BC9EFEB52C0480A500CFA7B1 /* GroupBanNavView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9EFEA52C0480A500CFA7B1 /* GroupBanNavView.m */; };
+		BC9EFEB62C0480A500CFA7B1 /* GroupBanNavView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC9EFEA62C0480A500CFA7B1 /* GroupBanNavView.xib */; };
+		BC9EFEB72C0480A500CFA7B1 /* StudentChooseDisplayCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9EFEA82C0480A500CFA7B1 /* StudentChooseDisplayCell.m */; };
+		BC9EFEB82C0480A500CFA7B1 /* StudentChooseDisplayCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC9EFEA92C0480A500CFA7B1 /* StudentChooseDisplayCell.xib */; };
+		BC9EFEB92C0480A500CFA7B1 /* StudentPreviewView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC9EFEAB2C0480A500CFA7B1 /* StudentPreviewView.m */; };
+		BC9EFEBA2C0480A500CFA7B1 /* StudentPreviewView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC9EFEAC2C0480A500CFA7B1 /* StudentPreviewView.xib */; };
 		BCA1134828A22A66007FAFB9 /* HomeHotMusicCollectionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA1134628A22A66007FAFB9 /* HomeHotMusicCollectionCell.m */; };
 		BCA1134928A22A66007FAFB9 /* HomeHotMusicCollectionCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA1134728A22A66007FAFB9 /* HomeHotMusicCollectionCell.xib */; };
 		BCA1134C28A23221007FAFB9 /* HomeHotMusicCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA1134B28A23221007FAFB9 /* HomeHotMusicCellView.m */; };
@@ -2402,6 +2416,28 @@
 		BC9AA0D12ABC430A00CD954D /* KSCustomLoadingView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSCustomLoadingView.xib; sourceTree = "<group>"; };
 		BC9AA0D22ABC430A00CD954D /* KSCustomLoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSCustomLoadingView.m; sourceTree = "<group>"; };
 		BC9AA0D32ABC430B00CD954D /* KSCustomLoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSCustomLoadingView.h; sourceTree = "<group>"; };
+		BC9EFE932C04804100CFA7B1 /* KSMuteTipsView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSMuteTipsView.m; sourceTree = "<group>"; };
+		BC9EFE942C04804200CFA7B1 /* KSMuteTipsView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSMuteTipsView.xib; sourceTree = "<group>"; };
+		BC9EFE952C04804200CFA7B1 /* KSMuteTipsView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSMuteTipsView.h; sourceTree = "<group>"; };
+		BC9EFE982C0480A500CFA7B1 /* GroupBanListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupBanListViewController.h; sourceTree = "<group>"; };
+		BC9EFE992C0480A500CFA7B1 /* GroupBanListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupBanListViewController.m; sourceTree = "<group>"; };
+		BC9EFE9C2C0480A500CFA7B1 /* BanStudentListCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BanStudentListCell.h; sourceTree = "<group>"; };
+		BC9EFE9D2C0480A500CFA7B1 /* BanStudentListCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BanStudentListCell.m; sourceTree = "<group>"; };
+		BC9EFE9E2C0480A500CFA7B1 /* BanStudentListCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BanStudentListCell.xib; sourceTree = "<group>"; };
+		BC9EFE9F2C0480A500CFA7B1 /* GroupBanBodyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupBanBodyView.h; sourceTree = "<group>"; };
+		BC9EFEA02C0480A500CFA7B1 /* GroupBanBodyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupBanBodyView.m; sourceTree = "<group>"; };
+		BC9EFEA12C0480A500CFA7B1 /* GroupBanBottomView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupBanBottomView.h; sourceTree = "<group>"; };
+		BC9EFEA22C0480A500CFA7B1 /* GroupBanBottomView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupBanBottomView.m; sourceTree = "<group>"; };
+		BC9EFEA32C0480A500CFA7B1 /* GroupBanBottomView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GroupBanBottomView.xib; sourceTree = "<group>"; };
+		BC9EFEA42C0480A500CFA7B1 /* GroupBanNavView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupBanNavView.h; sourceTree = "<group>"; };
+		BC9EFEA52C0480A500CFA7B1 /* GroupBanNavView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupBanNavView.m; sourceTree = "<group>"; };
+		BC9EFEA62C0480A500CFA7B1 /* GroupBanNavView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GroupBanNavView.xib; sourceTree = "<group>"; };
+		BC9EFEA72C0480A500CFA7B1 /* StudentChooseDisplayCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StudentChooseDisplayCell.h; sourceTree = "<group>"; };
+		BC9EFEA82C0480A500CFA7B1 /* StudentChooseDisplayCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StudentChooseDisplayCell.m; sourceTree = "<group>"; };
+		BC9EFEA92C0480A500CFA7B1 /* StudentChooseDisplayCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StudentChooseDisplayCell.xib; sourceTree = "<group>"; };
+		BC9EFEAA2C0480A500CFA7B1 /* StudentPreviewView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StudentPreviewView.h; sourceTree = "<group>"; };
+		BC9EFEAB2C0480A500CFA7B1 /* StudentPreviewView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StudentPreviewView.m; sourceTree = "<group>"; };
+		BC9EFEAC2C0480A500CFA7B1 /* StudentPreviewView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StudentPreviewView.xib; sourceTree = "<group>"; };
 		BCA1134528A22A66007FAFB9 /* HomeHotMusicCollectionCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeHotMusicCollectionCell.h; sourceTree = "<group>"; };
 		BCA1134628A22A66007FAFB9 /* HomeHotMusicCollectionCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeHotMusicCollectionCell.m; sourceTree = "<group>"; };
 		BCA1134728A22A66007FAFB9 /* HomeHotMusicCollectionCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeHotMusicCollectionCell.xib; sourceTree = "<group>"; };
@@ -3687,6 +3723,7 @@
 		2779360227E32BBF0010E277 /* Chat */ = {
 			isa = PBXGroup;
 			children = (
+				BC9EFEAE2C0480A500CFA7B1 /* BanList */,
 				BCED5CB5285087A9009A42DE /* ShareMusic */,
 				27F9CB0527EC5479003E0FE4 /* Group */,
 				2755C07827EC9593007D9070 /* GroupNotice */,
@@ -4246,6 +4283,9 @@
 				BC000D9D2A84E68B006C5A89 /* KSTXGroupChatViewController.m */,
 				BC000D9F2A84E6D5006C5A89 /* KSTXC2CChatViewController.h */,
 				BC000DA02A84E6D5006C5A89 /* KSTXC2CChatViewController.m */,
+				BC9EFE952C04804200CFA7B1 /* KSMuteTipsView.h */,
+				BC9EFE932C04804100CFA7B1 /* KSMuteTipsView.m */,
+				BC9EFE942C04804200CFA7B1 /* KSMuteTipsView.xib */,
 			);
 			path = TXCustom;
 			sourceTree = "<group>";
@@ -6336,6 +6376,56 @@
 			path = KulexiuForTeacher/Common/LoadingManager;
 			sourceTree = SOURCE_ROOT;
 		};
+		BC9EFE9A2C0480A500CFA7B1 /* Controller */ = {
+			isa = PBXGroup;
+			children = (
+				BC9EFE982C0480A500CFA7B1 /* GroupBanListViewController.h */,
+				BC9EFE992C0480A500CFA7B1 /* GroupBanListViewController.m */,
+			);
+			path = Controller;
+			sourceTree = "<group>";
+		};
+		BC9EFE9B2C0480A500CFA7B1 /* Model */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			path = Model;
+			sourceTree = "<group>";
+		};
+		BC9EFEAD2C0480A500CFA7B1 /* View */ = {
+			isa = PBXGroup;
+			children = (
+				BC9EFE9C2C0480A500CFA7B1 /* BanStudentListCell.h */,
+				BC9EFE9D2C0480A500CFA7B1 /* BanStudentListCell.m */,
+				BC9EFE9E2C0480A500CFA7B1 /* BanStudentListCell.xib */,
+				BC9EFE9F2C0480A500CFA7B1 /* GroupBanBodyView.h */,
+				BC9EFEA02C0480A500CFA7B1 /* GroupBanBodyView.m */,
+				BC9EFEA12C0480A500CFA7B1 /* GroupBanBottomView.h */,
+				BC9EFEA22C0480A500CFA7B1 /* GroupBanBottomView.m */,
+				BC9EFEA32C0480A500CFA7B1 /* GroupBanBottomView.xib */,
+				BC9EFEA42C0480A500CFA7B1 /* GroupBanNavView.h */,
+				BC9EFEA52C0480A500CFA7B1 /* GroupBanNavView.m */,
+				BC9EFEA62C0480A500CFA7B1 /* GroupBanNavView.xib */,
+				BC9EFEA72C0480A500CFA7B1 /* StudentChooseDisplayCell.h */,
+				BC9EFEA82C0480A500CFA7B1 /* StudentChooseDisplayCell.m */,
+				BC9EFEA92C0480A500CFA7B1 /* StudentChooseDisplayCell.xib */,
+				BC9EFEAA2C0480A500CFA7B1 /* StudentPreviewView.h */,
+				BC9EFEAB2C0480A500CFA7B1 /* StudentPreviewView.m */,
+				BC9EFEAC2C0480A500CFA7B1 /* StudentPreviewView.xib */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
+		BC9EFEAE2C0480A500CFA7B1 /* BanList */ = {
+			isa = PBXGroup;
+			children = (
+				BC9EFE9A2C0480A500CFA7B1 /* Controller */,
+				BC9EFE9B2C0480A500CFA7B1 /* Model */,
+				BC9EFEAD2C0480A500CFA7B1 /* View */,
+			);
+			path = BanList;
+			sourceTree = "<group>";
+		};
 		BCA1136928A4D6E6007FAFB9 /* AnimationSource */ = {
 			isa = PBXGroup;
 			children = (
@@ -7185,11 +7275,13 @@
 				BCC583F528A9FA8100BAB4CF /* cloud_animation_8.png in Resources */,
 				BCDF820C2A8A2955005F8B82 /* ClassMemberSettingView.xib in Resources */,
 				BCA1134E28A23229007FAFB9 /* HomeHotMusicCellView.xib in Resources */,
+				BC9EFEB82C0480A500CFA7B1 /* StudentChooseDisplayCell.xib in Resources */,
 				275B173127EB27960081FDEF /* GroupCreateView.xib in Resources */,
 				BCB908F82850C6EF00F5FF69 /* MusicChooseCell.xib in Resources */,
 				BC8831052873D67C00C702A0 /* LiveVideoCollectionViewCell.xib in Resources */,
 				2755C08E27ED5DB2007D9070 /* GroupApplyChooseCell.xib in Resources */,
 				BCF61BE9280425DA0000ACFE /* InstrumentChooseCell.xib in Resources */,
+				BC9EFEBA2C0480A500CFA7B1 /* StudentPreviewView.xib in Resources */,
 				BC76146F280D57220080FD1F /* HomeworkVideoView.xib in Resources */,
 				BC71D1FD2887FDD40010F14B /* img_31.png in Resources */,
 				277931CE27E30FC20010E277 /* KSPremissionAlert.xib in Resources */,
@@ -7228,6 +7320,7 @@
 				BC1553532AB3279500C1C347 /* TenentGroupAddMemberCell.xib in Resources */,
 				BCC0F7062A8CF13D00C4EFA4 /* TXDanBottomView.xib in Resources */,
 				BCC408E92AFCE11900C60249 /* MusicPublistAlert.xib in Resources */,
+				BC9EFEB42C0480A500CFA7B1 /* GroupBanBottomView.xib in Resources */,
 				2780C92927E490CA00A95A4F /* VefiBodyView.xib in Resources */,
 				BCC5840828A9FA8100BAB4CF /* cloud_animation_10.png in Resources */,
 				BCA9CE4427FD947C00D558C6 /* AccompanyArrangeCell.xib in Resources */,
@@ -7339,6 +7432,7 @@
 				BC15535C2AB33B0300C1C347 /* TenantCreateStuView.xib in Resources */,
 				BC8B6E562856ED0600866917 /* iOS集成升级必读.pdf in Resources */,
 				BC8B6E6A28575DEE00866917 /* MusicDisplayView.xib in Resources */,
+				BC9EFEB12C0480A500CFA7B1 /* BanStudentListCell.xib in Resources */,
 				BCB9FA21286D53A1005D766B /* ScanNavView.xib in Resources */,
 				BC7B0F5229271B650044CF61 /* CourseWarePreviewView.xib in Resources */,
 				BC71D1EB2887FDD40010F14B /* img_1.png in Resources */,
@@ -7372,6 +7466,7 @@
 				BC14E48E2AB2FBCD000C4983 /* TenantUnbindDetailBodyView.xib in Resources */,
 				BC513E7E28A4D874003F58C4 /* live_animation.json in Resources */,
 				BC106BA32A8F45AA000759A9 /* TXLiveRoomHeadView.xib in Resources */,
+				BC9EFEB62C0480A500CFA7B1 /* GroupBanNavView.xib in Resources */,
 				BCC408DA2AFCE0D700C60249 /* VideoCropImageViewCell.xib in Resources */,
 				27D83F5927F4225D00062476 /* LivePreviewBodyView.xib in Resources */,
 				BC41104A2806706800800BD9 /* HomeworkListCell.xib in Resources */,
@@ -7440,6 +7535,7 @@
 				BCE70D3828C6DA9300DE7A69 /* MyStyleEditHeadView.xib in Resources */,
 				BC71D2092887FDD40010F14B /* img_21.png in Resources */,
 				BC60E3C2287D448600B05441 /* DeleteAccountBodyView.xib in Resources */,
+				BC9EFE972C04804200CFA7B1 /* KSMuteTipsView.xib in Resources */,
 				BC31BFA02B219C5700F7D538 /* WidgetDotView.xib in Resources */,
 				BCC5841028A9FA8100BAB4CF /* cloud_animation_3.png in Resources */,
 				BC32E10E286AB326001434DD /* KSPublicAlertView.xib in Resources */,
@@ -7648,6 +7744,8 @@
 				BC106BAB2A8F45AA000759A9 /* TXSeatContainerView.m in Sources */,
 				277931CD27E30FC20010E277 /* KSPremissionAlert.m in Sources */,
 				BC106B872A8F4586000759A9 /* TXConstMessage.m in Sources */,
+				BC9EFEB72C0480A500CFA7B1 /* StudentChooseDisplayCell.m in Sources */,
+				BC9EFEB92C0480A500CFA7B1 /* StudentPreviewView.m in Sources */,
 				2779326A27E30FD80010E277 /* FSCalendarWeekdayView.m in Sources */,
 				BC106B302A8F4541000759A9 /* TXLiveRoomTimeManager.m in Sources */,
 				BC4BCE702823A02F00522C8B /* AddressBottomView.m in Sources */,
@@ -7856,6 +7954,7 @@
 				27D83F5727F4224F00062476 /* LivePreviewBodyView.m in Sources */,
 				BC1191F6280EBC7D00A716F7 /* AccompanyDetailBottomView.m in Sources */,
 				BCB909042851E25D00F5FF69 /* KSShareChooseViewController.m in Sources */,
+				BC9EFEB02C0480A500CFA7B1 /* BanStudentListCell.m in Sources */,
 				2773204D27EDB72B008FAECA /* LFPopupMenu.m in Sources */,
 				BCC03F8F2805484200461B7C /* StyleVideoModel.m in Sources */,
 				BC71DE912A89C937003F165E /* TXClassroomMsgCenter.m in Sources */,
@@ -7910,8 +8009,10 @@
 				BC106BB42A8F4BC9000759A9 /* LiveModuleService.m in Sources */,
 				BCDF822F2A8A3176005F8B82 /* KSValuePopView.m in Sources */,
 				BCEA75262819103300886A86 /* UnbindBodyView.m in Sources */,
+				BC9EFE962C04804200CFA7B1 /* KSMuteTipsView.m in Sources */,
 				BC542E4328407AD200633781 /* UserSettingViewController.m in Sources */,
 				BCB14113288A49710022C13A /* HomeButtonView.m in Sources */,
+				BC9EFEB52C0480A500CFA7B1 /* GroupBanNavView.m in Sources */,
 				2779360C27E32BE50010E277 /* LoginViewController.m in Sources */,
 				BC84183A2AC2D83700D8F90E /* NewPwdModifyViewController.m in Sources */,
 				27F9CB0E27EC5DF5003E0FE4 /* KSRCloudMediaManager.m in Sources */,
@@ -8032,6 +8133,7 @@
 				275E3DE727F4677F0010EC30 /* LiveRoomHeadView.m in Sources */,
 				BC106B882A8F4586000759A9 /* TXLiveMessageBlockUser.m in Sources */,
 				BC106B7E2A8F4586000759A9 /* TXLiveMessageDownSeatAll.m in Sources */,
+				BC9EFEB32C0480A500CFA7B1 /* GroupBanBottomView.m in Sources */,
 				2779320427E30FC30010E277 /* KSHoldButton.m in Sources */,
 				2779320627E30FC30010E277 /* UIView+ValueAdd.m in Sources */,
 				BCA9CE1527FD339400D558C6 /* AuthDisplayView.m in Sources */,
@@ -8177,6 +8279,7 @@
 				BC221FB428C82F0500F99802 /* MinePageSortView.m in Sources */,
 				BC84183B2AC2D83700D8F90E /* PasswordCheckViewController.m in Sources */,
 				BC71DF2B2A8A0432003F165E /* KSWhiteboardRefreshView.m in Sources */,
+				BC9EFEB22C0480A500CFA7B1 /* GroupBanBodyView.m in Sources */,
 				BCD457B2286564DB0010B493 /* LiveRoomAlertView.m in Sources */,
 				BCB399AC27F946A200AFF376 /* CourseNavView.m in Sources */,
 				BCE06F2B2818146700234817 /* KSConfirmAlertView.m in Sources */,
@@ -8198,6 +8301,7 @@
 				BC29AD2C2BFAFAFA00D44848 /* KSLogManager.m in Sources */,
 				BC0A22A4284751F80065C1AB /* AccompanySongCell.m in Sources */,
 				BC3A4EB728DAFCF7001C4428 /* MusicTagView.m in Sources */,
+				BC9EFEAF2C0480A500CFA7B1 /* GroupBanListViewController.m in Sources */,
 				BCD6D16F28196756009A773E /* FeeRecordModel.m in Sources */,
 				BC71DEF52A89F470003F165E /* TxClassroomChatOtherCell.m in Sources */,
 				BC14E4912AB30F8F000C4983 /* TenantCreateGroupViewController.m in Sources */,

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

@@ -52,7 +52,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/Converstaion/mute_tips.imageset/Contents.json

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Converstaion/mute_tips.imageset/mute_tips@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Converstaion/mute_tips.imageset/mute_tips@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/cancel_dark.imageset/cancel_dark@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/cancel_dark.imageset/cancel_dark@3x.png


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

@@ -420,6 +420,18 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param faliure 失败
 + (void)imGroupMemberAllRequest:(NSString *)post groupId:(NSString *)groupId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
+// 查询群成员列表(是否禁言)
+// /imGroupMember/page
+
+/// 查询群成员列表
+/// @param post post
+/// @param groupId 群id
+/// @param groupMute 是否禁言
+/// @param keyword 搜索
+/// @param success 成功
+/// @param faliure 失败
++ (void)imGroupMemberMuteRequest:(NSString *)post groupId:(NSString *)groupId groupMute:(BOOL)groupMute keyword:(NSString *_Nullable)keyword success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 // 查询群成员
 // /api-teacher/imGroupMember/getUserDetail
 /// 查询群成员信息
@@ -490,6 +502,28 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param success 成功
 /// @param faliure 失败
 + (void)sysImComplaintRequest:(NSString *)post type:(NSString *)type fileUrl:(NSString *)fileUrl memo:(NSString *)memo targetId:(NSString *)targetId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
+// /imGroup/muteAll
+
+/// 群主禁言操作
+/// @param post post
+/// @param groupId 群ID
+/// @param muteAll 是否禁言
+/// @param success 成功
+/// @param faliure 失败
++ (void)imGroupMuteAllRequest:(NSString *)post groupId:(NSString *)groupId muteAll:(BOOL)muteAll success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
+// /imGroupMember/groupMute
+
+/// 群成员禁言
+/// @param post post
+/// @param groupId 群组ID
+/// @param userIds 用户id
+/// @param groupMute 是否禁言
+/// @param success 成功
+/// @param faliure 失败
++ (void)groupMuteRequest:(NSString *)post groupId:(NSString *)groupId userIdArray:(NSMutableArray *)userIds groupMute:(BOOL)groupMute success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 #pragma mark ---- 群公告
 // /api-teacher/imGroupNotice/queryPage
 

+ 58 - 1
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.m

@@ -934,6 +934,28 @@
     [parm setValue:groupId forKey:@"groupId"];
     [self request:post andWithUrl:url and:parm success:success faliure:faliure];
 }
+
+// 查询群成员列表(是否禁言)
+// /api-teacher/imGroupMember/queryAll
+
+/// 查询群成员列表
+/// @param post post
+/// @param groupId 群id
+/// @param groupMute 是否禁言
+/// @param keyword 搜索
+/// @param success 成功
+/// @param faliure 失败
++ (void)imGroupMemberMuteRequest:(NSString *)post groupId:(NSString *)groupId groupMute:(BOOL)groupMute keyword:(NSString *_Nullable)keyword success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodJSON];
+    NSString *url = [NSString stringWithFormat:@"%@%@",hostURL, @"/api-teacher/imGroupMember/queryAll"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:groupId forKey:@"groupId"];
+    [parm setValue:keyword forKey:@"keyword"];
+    [parm setValue:@(groupMute) forKey:@"groupMute"];
+    [parm setValue:@[@"Member"] forKey:@"groupRoleTypes"];
+    [self request:post andWithUrl:url and:parm success:success faliure:faliure];
+}
+
 // 查询群成员
 // /api-teacher/imGroupMember/getUserDetail
 /// 查询群成员信息
@@ -1046,7 +1068,6 @@
 + (void)sysImComplaintRequest:(NSString *)post type:(NSString *)type fileUrl:(NSString *)fileUrl memo:(NSString *)memo targetId:(NSString *)targetId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     [self configRequestMethodJSON];
     NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-teacher/sysImComplaint/add"];
-//    targetId = [self returnNoContainGroupId:targetId];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
     [parm setValue:type forKey:@"type"];
     [parm setValue:fileUrl forKey:@"url"];
@@ -1055,6 +1076,42 @@
     [self request:post andWithUrl:url and:parm success:success faliure:faliure];
 }
 
+// /imGroup/muteAll
+
+/// 群主禁言操作
+/// @param post post
+/// @param groupId 群ID
+/// @param muteAll 是否禁言
+/// @param success 成功
+/// @param faliure 失败
++ (void)imGroupMuteAllRequest:(NSString *)post groupId:(NSString *)groupId muteAll:(BOOL)muteAll success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodJSON];
+    NSString *url = [NSString stringWithFormat:@"%@%@%@", hostURL, @"/api-teacher",@"/imGroup/muteAll"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:groupId forKey:@"groupId"];
+    [parm setValue:@(muteAll) forKey:@"muteAll"];
+    [self request:post andWithUrl:url and:parm success:success faliure:faliure];
+}
+
+// /imGroupMember/groupMute
+
+/// 群成员禁言
+/// @param post post
+/// @param groupId 群组ID
+/// @param userIds 用户id
+/// @param groupMute 是否禁言
+/// @param success 成功
+/// @param faliure 失败
++ (void)groupMuteRequest:(NSString *)post groupId:(NSString *)groupId userIdArray:(NSMutableArray *)userIds groupMute:(BOOL)groupMute success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    [self configRequestMethodJSON];
+    NSString *url = [NSString stringWithFormat:@"%@%@%@", hostURL, @"/api-teacher",@"/imGroupMember/groupMute"];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [parm setValue:groupId forKey:@"groupId"];
+    [parm setValue:@(groupMute) forKey:@"groupMute"];
+    [parm setValue:userIds forKey:@"userIds"];
+    [parm setValue:@(-1) forKey:@"muteTime"];
+    [self request:post andWithUrl:url and:parm success:success faliure:faliure];
+}
 
 #pragma mark ---- 群公告
 // /api-teacher/imGroupNotice/queryPage

+ 24 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/Controller/GroupBanListViewController.h

@@ -0,0 +1,24 @@
+//
+//  GroupBanListViewController.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import "KSBaseViewController.h"
+#import "JXCategoryView.h"
+#import "JXPagerView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupBanListViewController : KSBaseViewController
+
+@property (nonatomic, strong) JXPagerView *pagerView;
+@property (nonatomic, strong, readonly) JXCategoryTitleView *categoryView;
+@property (nonatomic, strong) NSArray <NSString *> *titles;
+
+@property (nonatomic, strong) NSString *groupId;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 210 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/Controller/GroupBanListViewController.m

@@ -0,0 +1,210 @@
+//
+//  GroupBanListViewController.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import "GroupBanListViewController.h"
+#import "GroupMemberModel.h"
+#import "GroupBanBodyView.h"
+#import "JXCategoryView.h"
+#import "JXPagerListRefreshView.h"
+#import "GroupBanNavView.h"
+
+
+@interface GroupBanListViewController ()<JXPagerViewDelegate, JXPagerMainTableViewGestureDelegate,JXCategoryViewDelegate>
+
+@property (nonatomic, strong) GroupBanNavView *navView;
+
+@property (nonatomic, assign) NSInteger selectedIndex;
+
+@property (nonatomic, strong) NSMutableArray *listViewArray;
+
+@end
+
+@implementation GroupBanListViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    [self configUI];
+}
+
+- (void)configUI {
+    [self.scrollView removeFromSuperview];
+    self.view.backgroundColor = HexRGB(0xF8F8F8);
+    self.ks_prefersNavigationBarHidden = YES;
+    [self.view addSubview:self.navView];
+    CGFloat navHeight = [GroupBanNavView getViewHeight];
+    [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.mas_equalTo(self.view);
+        make.height.mas_equalTo(navHeight);
+    }];
+    _titles = @[@"未禁言",@"已禁言"];
+
+    
+    _categoryView = [[JXCategoryTitleView alloc] initWithFrame:CGRectMake(0, navHeight, KPortraitWidth, 1)];
+    _categoryView.backgroundColor = [UIColor clearColor];
+    self.categoryView.titles = self.titles;
+    self.categoryView.delegate = self;
+    self.categoryView.titleFont = [UIFont systemFontOfSize:16.0f];
+    self.categoryView.titleSelectedFont = [UIFont systemFontOfSize:16.0f weight:UIFontWeightMedium];
+    self.categoryView.titleSelectedColor = THEMECOLOR;
+    self.categoryView.titleColor = HexRGB(0x777777);
+    self.categoryView.titleColorGradientEnabled = YES;
+    self.categoryView.hidden = YES;
+    
+    _pagerView = [self preferredPagingView];
+    self.pagerView.frame = CGRectMake(0, navHeight, KPortraitWidth, KPortraitHeight - navHeight);
+    self.pagerView.mainTableView.gestureDelegate = self;
+    self.pagerView.backgroundColor = [UIColor clearColor];
+    self.pagerView.mainTableView.backgroundColor = [UIColor clearColor];
+    [self.view addSubview:self.pagerView];
+    self.categoryView.listContainer = (id<JXCategoryViewListContainer>)self.pagerView.listContainerView;
+    if (self.selectedIndex != 0) {
+        [self.categoryView setDefaultSelectedIndex:self.selectedIndex];
+    }
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
+    self.navigationController.interactivePopGestureRecognizer.enabled = (self.categoryView.selectedIndex == 0);
+    if (self.listViewArray.count > self.categoryView.selectedIndex) {
+        id value = self.listViewArray[self.categoryView.selectedIndex];
+        if ([value isKindOfClass:[KSJXBodyView class]]) {
+            KSJXBodyView *listView = (KSJXBodyView *)value;
+            [listView beginFirstRefresh];
+        }
+    }
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+    [super viewDidAppear:animated];
+}
+
+- (JXPagerView *)preferredPagingView {
+    return [[JXPagerListRefreshView alloc] initWithDelegate:self];
+}
+
+#pragma mark - JXPagerViewDelegate
+
+- (UIView *)tableHeaderViewInPagerView:(JXPagerView *)pagerView {
+    return [UIView new];
+}
+
+- (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView {
+    return CGFLOAT_MIN;
+}
+
+- (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
+    return 1;
+}
+
+- (UIView *)viewForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
+    return self.categoryView;
+}
+
+- (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView {
+    //和categoryView的item数量一致
+    return self.titles.count;
+}
+
+- (id<JXPagerViewListViewDelegate>)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index {
+    GroupBanBodyView *listView = [[GroupBanBodyView alloc] init];
+    listView.groupId = self.groupId;
+    listView.naviController = self.navigationController;
+    [self.listViewArray replaceObjectAtIndex:index withObject:listView];
+    if (index == 0) {
+        listView.selectIndex = 0;
+    }else if (index == 1) {
+        listView.selectIndex = 1;
+    }
+    [listView beginFirstRefresh];
+    return listView;
+}
+
+#pragma mark - JXCategoryViewDelegate
+- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index {
+    self.selectedIndex = index;
+    [self.navView scrollTableIndex:index];
+    [self refreshAndRequest:index];
+}
+
+#pragma mark - JXPagerMainTableViewGestureDelegate
+
+- (BOOL)mainTableViewGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
+    //禁止categoryView左右滑动的时候,上下和左右都可以滚动
+    if (otherGestureRecognizer == self.categoryView.collectionView.panGestureRecognizer) {
+        return NO;
+    }
+    return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];
+}
+
+
+- (NSMutableArray *)listViewArray {
+    if (!_listViewArray) {
+        _listViewArray = [NSMutableArray arrayWithArray:@[@"",@""]];
+    }
+    return _listViewArray;
+}
+
+- (GroupBanNavView *)navView {
+    if (!_navView) {
+        _navView = [GroupBanNavView shareInstance];
+        MJWeakSelf;
+        [_navView banNavAction:^(BANNAVACTION action) {
+            [weakSelf navAction:action];
+        }];
+
+    }
+    return _navView;
+}
+
+#pragma mark ----- nav action
+- (void)navAction:(BANNAVACTION)action {
+    switch (action) {
+        case BANNAVACTION_BACK: // 返回
+        {
+            [self backAction];
+        }
+            break;
+        case BANNAVACTION_UNBAN:
+        {
+            [self.categoryView selectItemAtIndex:0];
+            [self refreshAndRequest:0];
+        }
+            break;
+        case BANNAVACTION_BAN:
+        {
+            [self.categoryView selectItemAtIndex:1];
+            [self refreshAndRequest:1];
+        }
+            break;
+        default:
+            break;
+    }
+}
+
+- (void)refreshAndRequest:(NSInteger)selectedIndex {
+    if (self.listViewArray.count > selectedIndex) {
+        id value = self.listViewArray[selectedIndex];
+        if ([value isKindOfClass:[GroupBanBodyView class]]) {
+            GroupBanBodyView *listView = value;
+            [listView beginFirstRefresh];
+        }
+    }
+}
+
+/*
+#pragma mark - Navigation
+
+// In a storyboard-based application, you will often want to do a little preparation before navigation
+- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
+    // Get the new view controller using [segue destinationViewController].
+    // Pass the selected object to the new view controller.
+}
+*/
+
+
+@end

+ 19 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/BanStudentListCell.h

@@ -0,0 +1,19 @@
+//
+//  BanStudentListCell.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import <UIKit/UIKit.h>
+#import "GroupMemberModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface BanStudentListCell : UITableViewCell
+
+- (void)configWithSource:(GroupMemberModel *)model isChoose:(BOOL)isChoose;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 48 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/BanStudentListCell.m

@@ -0,0 +1,48 @@
+//
+//  BanStudentListCell.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import "BanStudentListCell.h"
+
+@interface BanStudentListCell ()
+
+@property (weak, nonatomic) IBOutlet UIImageView *statusImage;
+
+@property (weak, nonatomic) IBOutlet UIImageView *studentAvatar;
+
+@property (weak, nonatomic) IBOutlet UILabel *studentName;
+
+@end
+
+@implementation BanStudentListCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+}
+
+
+- (void)configWithSource:(GroupMemberModel *)model isChoose:(BOOL)isChoose {
+    if ([NSString isEmptyString:model.nickname]) {
+        self.studentName.text = [NSString stringWithFormat:@"用户:%@",model.userId];
+    }
+    else {
+        self.studentName.text = model.nickname;
+    }
+    [self.studentAvatar sd_setImageWithURL:[NSURL URLWithString:[model.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:USERDEFAULT_LOGO]];
+    
+    NSString *statusImage = isChoose ? @"choose_status" : @"unChoose_status";
+    [self.statusImage setImage:[UIImage imageNamed:statusImage]];
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+@end

+ 99 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/BanStudentListCell.xib

@@ -0,0 +1,99 @@
+<?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">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <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"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="149" id="KGk-i7-Jjw" customClass="BanStudentListCell">
+            <rect key="frame" x="0.0" y="0.0" width="320" height="70"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
+                <rect key="frame" x="0.0" y="0.0" width="320" height="70"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="OMW-an-wEJ">
+                        <rect key="frame" x="0.0" y="0.0" width="320" height="70"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="user_default_avatal" translatesAutoresizingMaskIntoConstraints="NO" id="fAV-uj-cGe">
+                                <rect key="frame" x="43" y="11" width="48" height="48"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="48" id="OAz-2Q-EQo"/>
+                                    <constraint firstAttribute="height" constant="48" id="w9W-B3-o2g"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="24"/>
+                                    </userDefinedRuntimeAttribute>
+                                </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="P69-hs-iWn">
+                                <rect key="frame" x="101" y="24" width="189" height="22"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="22" id="8TG-oB-XVX"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
+                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7uC-Z6-wvI">
+                                <rect key="frame" x="101" y="69" width="219" height="1"/>
+                                <color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="1" id="niK-2L-KJP"/>
+                                </constraints>
+                            </view>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="unChoose_status" translatesAutoresizingMaskIntoConstraints="NO" id="REu-8s-tOA">
+                                <rect key="frame" x="13" y="26" width="18" height="18"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="18" id="Ejb-G4-mlI"/>
+                                    <constraint firstAttribute="height" constant="18" id="Qx5-oA-wlp"/>
+                                </constraints>
+                            </imageView>
+                        </subviews>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <constraint firstAttribute="trailing" secondItem="P69-hs-iWn" secondAttribute="trailing" constant="30" id="ADv-Sc-r87"/>
+                            <constraint firstItem="P69-hs-iWn" firstAttribute="leading" secondItem="fAV-uj-cGe" secondAttribute="trailing" constant="10" id="DDa-cx-5H8"/>
+                            <constraint firstItem="REu-8s-tOA" firstAttribute="centerY" secondItem="OMW-an-wEJ" secondAttribute="centerY" id="GAj-kQ-sFd"/>
+                            <constraint firstItem="P69-hs-iWn" firstAttribute="leading" secondItem="7uC-Z6-wvI" secondAttribute="leading" id="NFy-2I-77r"/>
+                            <constraint firstItem="fAV-uj-cGe" firstAttribute="centerY" secondItem="OMW-an-wEJ" secondAttribute="centerY" id="QLH-ki-lmj"/>
+                            <constraint firstAttribute="bottom" secondItem="7uC-Z6-wvI" secondAttribute="bottom" id="XVe-Q1-eXB"/>
+                            <constraint firstAttribute="trailing" secondItem="7uC-Z6-wvI" secondAttribute="trailing" id="aFd-NV-8xV"/>
+                            <constraint firstItem="fAV-uj-cGe" firstAttribute="leading" secondItem="REu-8s-tOA" secondAttribute="trailing" constant="12" id="cVA-lC-g0l"/>
+                            <constraint firstItem="P69-hs-iWn" firstAttribute="centerY" secondItem="fAV-uj-cGe" secondAttribute="centerY" id="qCn-2b-vX8"/>
+                            <constraint firstItem="REu-8s-tOA" firstAttribute="leading" secondItem="OMW-an-wEJ" secondAttribute="leading" constant="13" id="te1-WU-Wrv"/>
+                        </constraints>
+                    </view>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="OMW-an-wEJ" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="GqX-b4-WFv"/>
+                    <constraint firstAttribute="bottom" secondItem="OMW-an-wEJ" secondAttribute="bottom" id="HY0-7Q-F5K"/>
+                    <constraint firstItem="OMW-an-wEJ" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="gYS-tE-TCR"/>
+                    <constraint firstAttribute="trailing" secondItem="OMW-an-wEJ" secondAttribute="trailing" id="rxS-jW-Sft"/>
+                </constraints>
+            </tableViewCellContentView>
+            <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <connections>
+                <outlet property="statusImage" destination="REu-8s-tOA" id="NoK-52-wfx"/>
+                <outlet property="studentAvatar" destination="fAV-uj-cGe" id="KUX-Zs-KZf"/>
+                <outlet property="studentName" destination="P69-hs-iWn" id="oVl-LF-dUi"/>
+            </connections>
+            <point key="canvasLocation" x="33.587786259541986" y="83.450704225352112"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="unChoose_status" width="18" height="18"/>
+        <image name="user_default_avatal" width="52" height="52"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 18 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBodyView.h

@@ -0,0 +1,18 @@
+//
+//  GroupBanBodyView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import <KSToolLibrary/KSJXBodyView.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupBanBodyView : KSJXBodyView
+
+@property (nonatomic, strong) NSString *groupId;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 540 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBodyView.m

@@ -0,0 +1,540 @@
+//
+//  GroupBanBodyView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import "GroupBanBodyView.h"
+#import "KSChatListSearchView.h"
+#import "KSEmptyStatusView.h"
+#import "Reachability.h"
+#import "BanStudentListCell.h"
+#import <KSToolLibrary/SCIndexView.h>
+#import <KSToolLibrary/UITableView+SCIndexView.h>
+#import "GroupMemberModel.h"
+#import "GroupBanBottomView.h"
+#import "StudentPreviewView.h"
+
+@interface GroupBanBodyView ()<UITableViewDelegate,UITableViewDataSource>
+
+@property (nonatomic, strong) KSEmptyStatusView *promptView;
+@property (nonatomic, strong) UIView *promptPlaceView;
+
+@property (nonatomic, assign) BOOL networkAvaiable; // 网络是否可用
+
+@property (nonatomic, strong) NSString *searchKey;
+
+@property (nonatomic, strong) KSChatListSearchView *searchView;
+
+@property (nonatomic, strong) NSMutableArray *sourceArray;
+
+@property (nonatomic, strong) NSMutableArray *studentArray; // 学员数据
+
+@property (nonatomic, strong) NSMutableArray *sourceIndexArray;
+
+@property (nonatomic, strong) GroupBanBottomView *bottomView;
+
+@property (nonatomic, strong) StudentPreviewView *displayView;
+
+@property (nonatomic, strong) NSMutableArray *currentChooseArray;
+
+
+@end
+
+@implementation GroupBanBodyView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        self.backgroundColor = HexRGB(0xF8F8F8);
+        self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
+        self.tableView.backgroundColor = HexRGB(0xF8F8F8);
+        self.tableView.showsVerticalScrollIndicator = NO;
+        self.tableView.rowHeight = UITableViewAutomaticDimension;
+        self.tableView.rowHeight = 70.0f;
+        self.tableView.dataSource = self;
+        self.tableView.delegate = self;
+        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+        if (@available(iOS 15.0, *)) {
+            self.tableView.sectionHeaderTopPadding = 0;
+        }
+        self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
+        self.tableView.estimatedSectionFooterHeight = 0;
+        self.tableView.estimatedSectionHeaderHeight = 0;
+        [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(0xF8F8F8);
+        self.tableView.tableFooterView = bottomView;
+        
+        [self.tableView registerNib:[UINib nibWithNibName:@"BanStudentListCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"BanStudentListCell"];
+        MJWeakSelf;
+        self.tableView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
+            [weakSelf resetParamenter];
+            [weakSelf requestData];
+        }];
+    }
+    return self;
+}
+
+- (void)endRefresh {
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        [self.tableView.mj_header endRefreshing];
+    });
+}
+
+- (void)refreshAndRequestData {
+    [self resetParamenter];
+    [self requestData];
+}
+
+- (void)requestData {
+    BOOL isMute = self.selectIndex == 0 ? NO : YES;
+    [self.sourceArray removeAllObjects];
+    [KSNetworkingManager imGroupMemberMuteRequest:KS_POST groupId:self.groupId groupMute:isMute keyword:self.searchKey success:^(NSDictionary * _Nonnull dic) {
+        [self endRefresh];
+        if ([dic ks_integerValueForKey:@"code"] == 200) {
+            NSArray *sourceArray = [dic ks_arrayValueForKey:@"data"];
+            for (NSDictionary *parm in sourceArray) {
+                if ([parm isKindOfClass:[NSNull class]]) {
+                    continue;
+                }
+                GroupMemberModel *model = [[GroupMemberModel alloc] initWithDictionary:parm];
+                [self.sourceArray addObject:model];
+            }
+            [self evaluateMessge];
+        }
+        else {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        [self endRefresh];
+    }];
+}
+
+- (void)evaluateMessge {
+    // 异步线程处理数据
+    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+        NSMutableArray *sortArr = [NSMutableArray array];
+        for (GroupMemberModel *model in self.sourceArray) {
+            NSString *firstLetter = [NSString getFirstLetterFromString:model.nickname];
+            model.firstLetter = firstLetter;
+            if (![sortArr containsObject:firstLetter]) {
+                [sortArr addObject:firstLetter];
+            }
+        }
+        // 排序
+        [sortArr sortUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
+            return [obj1 compare:obj2 options:NSCaseInsensitiveSearch];
+        }];
+        // 将#移动到最后
+        for (NSString *letterStr in sortArr) {
+            if ([letterStr isEqualToString:@"#"]) {
+                [sortArr removeObject:letterStr];
+                [sortArr addObject:@"#"];
+                break;
+            }
+        }
+        for (NSString *sortStr in sortArr) {
+            NSMutableArray *filterArray = [NSMutableArray array];
+            for (GroupMemberModel *subModel in self.sourceArray) {
+                if ([sortStr isEqualToString:subModel.firstLetter]) {
+                    [filterArray addObject:subModel];
+                }
+            }
+            [self.studentArray addObject:filterArray];
+        }
+        self.sourceIndexArray = sortArr;
+        // 主线程刷新
+        dispatch_async(dispatch_get_main_queue(), ^{
+            self.tableView.sc_indexViewDataSource = self.sourceIndexArray;
+            [self refreshChooseStatus];
+            [self changePromptLabelStateWithArray:self.studentArray];            
+        });
+    });
+}
+
+- (void)resetParamenter {
+    NSString *tipsString = @"暂无群成员";
+    [self setPromptString:tipsString imageName:@"wd_img_zwsj" inView:self.tableView];
+    [self.studentArray removeAllObjects];
+    [self.sourceArray removeAllObjects];
+    self.sourceIndexArray = [NSMutableArray array];
+    SCIndexViewConfiguration *indexConfiguration = [SCIndexViewConfiguration configuration];
+    indexConfiguration.indexItemSelectedBackgroundColor = HexRGB(0x1CACF1);
+    indexConfiguration.indicatorBackgroundColor = HexRGB(0x1CACF1);
+    indexConfiguration.indexItemTextColor = HexRGB(0xAAAAAA);
+    self.tableView.sc_indexViewConfiguration = indexConfiguration;
+    self.tableView.sc_indexViewDataSource = self.sourceIndexArray;
+    [self.tableView reloadData];
+}
+
+- (void)beginRefreshImmediately {
+    [self resetParamenter];
+    [self requestData];
+}
+
+- (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:@"请输入群成员名称"];
+    // 添加底部按钮
+    CGFloat bottomHeight = [GroupBanBottomView getViewHeight];
+    if (![self.subviews containsObject:self.bottomView]) {
+        [self addSubview:self.bottomView];
+        self.bottomView.frame = CGRectMake(0, self.bounds.size.height - bottomHeight, self.bounds.size.width, bottomHeight);
+    }
+    NSString *displayMsg = @"禁言";
+    if (self.selectIndex == 1) {
+        displayMsg = @"解除禁言";
+    }
+    
+    [self.bottomView displayBottomButton:displayMsg];
+    [self.tableView mas_updateConstraints:^(MASConstraintMaker *make) {
+        make.top.mas_equalTo(self.mas_top).mas_offset(height);
+        make.bottom.mas_equalTo(self.mas_bottom).offset(-bottomHeight);
+    }];
+}
+
+- (void)beginFirstRefresh {
+    if (!self.isHeaderRefreshed) {
+        [self beginRefreshImmediately];
+    }
+}
+
+#pragma mark -- table data source
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    if (self.studentArray.count > section) {
+        NSArray *filterArray = self.studentArray[section];
+        return filterArray.count;
+    }
+    return 0;
+}
+
+- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
+    return self.sourceIndexArray.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    BanStudentListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"BanStudentListCell"];
+    NSArray *filterArray = self.studentArray[indexPath.section];
+    GroupMemberModel *model = filterArray[indexPath.row];
+    BOOL isChoose = [self judgeContainUser:model.imUserId];
+    [cell configWithSource:model isChoose:isChoose];
+    return cell;
+}
+
+
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+    // 设置选中状态
+    NSArray *filterArray = self.studentArray[indexPath.section];
+    GroupMemberModel *model = filterArray[indexPath.row];
+    if (![self judgeContainUser:model.imUserId]) {
+        [self.currentChooseArray addObject:model];
+    }
+    else {
+        [self removeUser:model.imUserId];
+    }
+    [self refreshChooseStatus];
+}
+
+- (void)removeUser:(NSString *)imUserId {
+    for (GroupMemberModel *model in self.currentChooseArray) {
+        if ([model.imUserId isEqualToString:imUserId]) {
+            [self.currentChooseArray removeObject:model];
+            return;
+        }
+    }
+}
+
+- (BOOL)judgeContainUser:(NSString *)imUserId {
+    BOOL isContain = NO;
+    for (GroupMemberModel *model in self.currentChooseArray) {
+        if ([model.imUserId isEqualToString:imUserId]) {
+            isContain = YES;
+        }
+    }
+    return isContain;
+}
+
+- (void)refreshChooseStatus {
+    NSInteger chooseCount = 0;
+    
+    BOOL hasNoChooseStu = NO;
+    if (self.sourceArray.count == 0) { // 如果是空
+        hasNoChooseStu = YES;
+    }
+    else {
+        for (GroupMemberModel *model in self.sourceArray) {
+            BOOL isChoose = NO;
+            for (GroupMemberModel *chooseModel in self.currentChooseArray) {
+                if ([chooseModel.imUserId isEqualToString:model.imUserId]) {
+                    chooseCount++;
+                    isChoose = YES;
+                }
+                
+            }
+            if (isChoose == NO) {
+                hasNoChooseStu = YES;
+            }
+        }
+    }
+    
+    
+    CHOOSESTATUS status = CHOOSESTATUS_EMPTY;
+   if (hasNoChooseStu == NO) {
+        status = CHOOSESTATUS_FULL;
+    }
+    else {
+        status = CHOOSESTATUS_EMPTY;
+    }
+    [self.bottomView refreshChooseStatus:status];
+    [self.bottomView refreshChooseStudentStatus:self.currentChooseArray];
+    [self.tableView reloadData];
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
+    return 42.0f;
+}
+
+- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
+    
+    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, 42.0f)];
+    view.backgroundColor = HexRGB(0xF8F8F8);
+    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(24, 11, kScreenWidth - 48, 20)];
+    label.textColor = HexRGB(0x999999);
+    label.font = [UIFont systemFontOfSize:16.0f weight:UIFontWeightMedium];
+    [view addSubview:label];
+    label.textAlignment = NSTextAlignmentLeft;
+    NSString *titleStr = self.sourceIndexArray[section];
+    label.text = titleStr;
+    return view;
+}
+
+- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
+    return CGFLOAT_MIN;
+}
+/**
+ 设置没有数据时的显示
+ 
+ @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 = [KSEmptyStatusView shareInstance];
+    }
+    _promptPlaceView = view;
+    //当请求不到数据时 ,自定义提示view 将会出现;
+    self.promptView.alpha = 0.0f;
+    [self.promptView configImageName:imgName desc:promptString topHeight:40];
+    [view addSubview:self.promptView];
+    [self.promptView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.edges.mas_equalTo(view);
+        make.width.mas_equalTo(view);
+        make.height.mas_equalTo(view);
+    }];
+}
+
+// 结束刷新后调用方法
+- (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;
+}
+
+- (KSChatListSearchView *)searchView {
+    if (!_searchView) {
+        _searchView = [KSChatListSearchView shareInstance];
+        MJWeakSelf;
+        [_searchView topSearchCallback:^{
+            [weakSelf searchAction];
+        }];
+    }
+    return _searchView;
+}
+
+- (GroupBanBottomView *)bottomView {
+    if (!_bottomView) {
+        _bottomView = [GroupBanBottomView shareInstance];
+        MJWeakSelf;
+        [_bottomView modifyChooseStatus:^(BOTTOM_ACTION action) {
+            [weakSelf bottomAction:action];
+        }];
+    }
+    return _bottomView;
+}
+
+- (void)bottomAction:(BOTTOM_ACTION)action {
+    switch (action) {
+        case BOTTOM_ACTION_CHOOSE:
+        {
+            if (self.bottomView.status == CHOOSESTATUS_EMPTY) {
+                self.currentChooseArray = [NSMutableArray array];
+                
+            }
+            else {
+                self.currentChooseArray = [NSMutableArray arrayWithArray:self.sourceArray];
+            }
+            [self refreshChooseStatus];
+        }
+            break;
+        case BOTTOM_ACTION_DISPLAY:
+        {
+            [self displayChooseView];
+        }
+            break;
+        case BOTTOM_ACTION_SURE:
+        {
+            if (self.currentChooseArray.count == 0) {
+                [LOADING_MANAGER MBShowAUTOHidingInWindow:@"请选择群成员"];
+                return;
+            }
+            NSMutableArray *userIdList = [NSMutableArray array];
+            for (GroupMemberModel *model in self.currentChooseArray) {
+                [userIdList addObject:model.userId];
+            }
+            BOOL isMute = self.selectIndex == 1 ? NO : YES;
+            [LOADING_MANAGER showCustomLoading:@"加载中..."];
+            [KSNetworkingManager groupMuteRequest:KS_POST groupId:self.groupId userIdArray:userIdList groupMute:isMute success:^(NSDictionary * _Nonnull dic) {
+                [LOADING_MANAGER removeCustomLoading];
+                if ([dic ks_integerValueForKey:@"code"] == 200) {
+                    self.currentChooseArray = [NSMutableArray array];
+                    [self refreshAndRequestData];
+                }
+                else {
+                    [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+                }
+            } faliure:^(NSError * _Nonnull error) {
+                [LOADING_MANAGER removeCustomLoading];
+            }];
+            
+        }
+            break;
+        default:
+            break;
+    }
+}
+
+- (void)displayChooseView {
+    
+    MJWeakSelf;
+    [self.displayView configWithSource:self.currentChooseArray callback:^(NSMutableArray * _Nonnull studentArray) {
+        [weakSelf refreshChooseStudent:studentArray];
+    }];
+    [self.displayView showView];
+}
+
+- (void)refreshChooseStudent:(NSMutableArray *)studentArray {
+    
+    self.currentChooseArray = [NSMutableArray arrayWithArray:studentArray];
+    [self refreshChooseStatus];
+    [self.tableView reloadData];
+}
+
+- (void)searchAction {
+    self.searchKey = self.searchView.searchField.text;
+    [self refreshAndRequestData];
+}
+
+- (NSMutableArray *)studentArray {
+    if (!_studentArray) {
+        _studentArray = [NSMutableArray array];
+    }
+    return _studentArray;
+}
+- (NSMutableArray *)sourceIndexArray {
+    if (!_sourceIndexArray) {
+        _sourceIndexArray = [NSMutableArray array];
+    }
+    return _sourceIndexArray;
+}
+
+- (NSMutableArray *)sourceArray {
+    if (!_sourceArray) {
+        _sourceArray = [NSMutableArray array];
+    }
+    return _sourceArray;
+}
+
+- (StudentPreviewView *)displayView {
+    if (!_displayView) {
+        _displayView = [StudentPreviewView shareInstance];
+    }
+    return _displayView;
+}
+- (NSMutableArray *)currentChooseArray {
+    if (!_currentChooseArray) {
+        _currentChooseArray = [NSMutableArray array];
+    }
+    return _currentChooseArray;
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 45 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBottomView.h

@@ -0,0 +1,45 @@
+//
+//  GroupBanBottomView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSInteger, CHOOSESTATUS) {
+    CHOOSESTATUS_EMPTY,  // 未选择
+    CHOOSESTATUS_FULL,   // 全选
+};
+
+typedef NS_ENUM(NSInteger, BOTTOM_ACTION) {
+    BOTTOM_ACTION_CHOOSE,   // 选择
+    BOTTOM_ACTION_DISPLAY,  // 显示
+    BOTTOM_ACTION_SURE,     // 确认
+};
+
+typedef void(^ChooseButtonClickCallback)(BOTTOM_ACTION action);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupBanBottomView : UIView
+
+@property (nonatomic, assign) CHOOSESTATUS status;
+
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+
++ (instancetype)shareInstance;
+
+- (void)refreshChooseStudentStatus:(NSMutableArray *)studentArray;
+
+- (void)refreshChooseStatus:(CHOOSESTATUS)status;
+
+- (void)modifyChooseStatus:(ChooseButtonClickCallback)callback;
+
+- (void)displayBottomButton:(NSString *)displayMsg;
+
++ (CGFloat)getViewHeight;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 140 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBottomView.m

@@ -0,0 +1,140 @@
+//
+//  GroupBanBottomView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import "GroupBanBottomView.h"
+#import <KSToolLibrary/UIView+KSLayer.h>
+#import "GroupMemberModel.h"
+
+@interface GroupBanBottomView ()
+@property (weak, nonatomic) IBOutlet UIView *colorView;
+
+@property (weak, nonatomic) IBOutlet UIImageView *statusImage;
+
+@property (weak, nonatomic) IBOutlet UIView *imageContainer;
+
+@property (nonatomic, strong) UIScrollView *imageScrollView;
+
+@property (weak, nonatomic) IBOutlet UIButton *sureButton;
+
+@property (nonatomic, copy) ChooseButtonClickCallback callback;
+
+@end
+
+@implementation GroupBanBottomView
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    [self.imageContainer addSubview:self.imageScrollView];
+    [self.imageScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.bottom.mas_equalTo(self.imageContainer);
+    }];
+}
+
++ (instancetype)shareInstance {
+    GroupBanBottomView *view = [[[NSBundle mainBundle] loadNibNamed:@"GroupBanBottomView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)refreshChooseStatus:(CHOOSESTATUS)status {
+    self.status = status;
+}
+
+- (void)modifyChooseStatus:(ChooseButtonClickCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (void)refreshChooseStudentStatus:(NSMutableArray *)studentArray {
+    [self.imageScrollView removeAllSubViews];
+    self.descLabel.text = [NSString stringWithFormat:@"全选(已选择%zd):",studentArray.count];
+    for (NSInteger index = 0; index < studentArray.count; index++) {
+        GroupMemberModel *model = studentArray[index];
+        NSString *imgUrl = model.avatar;
+        UIImageView *imageView = [[UIImageView alloc] init];
+        imageView.layer.cornerRadius = 14.0f;
+        imageView.contentMode = UIViewContentModeScaleAspectFill;
+        imageView.layer.masksToBounds = YES;
+        imageView.userInteractionEnabled = YES;
+        UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(displayImage:)];
+        [imageView addGestureRecognizer:gesture];
+        [self.imageScrollView addSubview:imageView];
+        
+        [imageView sd_setImageWithURL:[NSURL URLWithString:[imgUrl getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:USERDEFAULT_LOGO]];
+        CGFloat width = 28;
+        CGFloat leftSpace = index * (6 + width);
+        [imageView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.top.bottom.mas_equalTo(self.imageContainer);
+            make.width.mas_equalTo(width);
+            make.left.mas_equalTo(self.imageScrollView.mas_left).offset(leftSpace);
+            if (index == studentArray.count - 1) {
+                make.right.mas_equalTo(self.imageScrollView.mas_right);
+            }
+        }];
+    }
+}
+
+- (IBAction)chooseAction:(id)sender {
+    if (self.status == CHOOSESTATUS_FULL) {
+        self.status = CHOOSESTATUS_EMPTY;
+    }
+    else {
+        self.status = CHOOSESTATUS_FULL;
+    }
+    if (self.callback) {
+        self.callback(BOTTOM_ACTION_CHOOSE);
+    }
+}
+
+// 显示学生列表
+- (void)displayImage:(id)sender {
+    if (self.callback) {
+        self.callback(BOTTOM_ACTION_DISPLAY);
+    }
+}
+
+- (IBAction)sureAction:(id)sender {
+    if (self.callback) {
+        self.callback(BOTTOM_ACTION_SURE);
+    }
+}
+
+- (void)setStatus:(CHOOSESTATUS)status {
+    _status = status;
+    NSString *imgName = nil;
+    if (status == CHOOSESTATUS_EMPTY) {
+        imgName = @"unChoose_status";
+    }
+    else {
+        imgName = @"choose_status";
+    }
+    [self.statusImage setImage:[UIImage imageNamed:imgName]];
+}
+
++ (CGFloat)getViewHeight {
+    return 60 + iPhoneXSafeBottomMargin;
+}
+
+- (void)displayBottomButton:(NSString *)displayMsg {
+    [self.sureButton setTitle:displayMsg forState:UIControlStateNormal];
+}
+
+- (UIScrollView *)imageScrollView {
+    if (!_imageScrollView) {
+        _imageScrollView = [[UIScrollView alloc] init];
+    }
+    return _imageScrollView;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 122 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanBottomView.xib

@@ -0,0 +1,122 @@
+<?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" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <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="GroupBanBottomView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="60"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="unChoose_status" translatesAutoresizingMaskIntoConstraints="NO" id="4vH-45-Chd">
+                    <rect key="frame" x="13" y="21" width="18" height="18"/>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="18" id="0Jq-Mk-dUW"/>
+                        <constraint firstAttribute="height" constant="18" id="4RZ-JM-nI6"/>
+                    </constraints>
+                </imageView>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="全选(已选择):" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9V8-cK-iyl">
+                    <rect key="frame" x="33" y="20" width="91" height="20"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="20" id="eEE-iu-xcm"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                    <color key="textColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="rc8-DX-0iI">
+                    <rect key="frame" x="131" y="16" width="155" height="28"/>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="28" id="jMN-aT-eIZ"/>
+                    </constraints>
+                </view>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fVB-PC-63v">
+                    <rect key="frame" x="301" y="15" width="80" height="30"/>
+                    <color key="backgroundColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="calibratedRGB"/>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="15"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NCc-jc-GUf">
+                    <rect key="frame" x="301" y="15" width="80" height="30"/>
+                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstAttribute="width" constant="80" id="C7o-d3-eVX"/>
+                        <constraint firstAttribute="height" constant="30" id="jMC-U1-pFH"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <state key="normal" title="禁言"/>
+                    <connections>
+                        <action selector="sureAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="zSP-hU-JVV"/>
+                    </connections>
+                </button>
+                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xYH-lk-TmS">
+                    <rect key="frame" x="13" y="13" width="111" height="34"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="34" id="zcr-7B-BA3"/>
+                    </constraints>
+                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                    <connections>
+                        <action selector="chooseAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="EbF-Yu-9aF"/>
+                    </connections>
+                </button>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="26D-B3-H5O">
+                    <rect key="frame" x="0.0" y="0.0" width="393" height="1"/>
+                    <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="calibratedRGB"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="1" id="mIP-pT-awD"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+            <constraints>
+                <constraint firstItem="9V8-cK-iyl" firstAttribute="centerY" secondItem="4vH-45-Chd" secondAttribute="centerY" id="9Df-Eb-NvL"/>
+                <constraint firstAttribute="trailing" secondItem="NCc-jc-GUf" secondAttribute="trailing" constant="12" id="BqS-pj-KJE"/>
+                <constraint firstItem="NCc-jc-GUf" firstAttribute="top" secondItem="fVB-PC-63v" secondAttribute="top" id="CUQ-11-lBW"/>
+                <constraint firstItem="NCc-jc-GUf" firstAttribute="leading" secondItem="rc8-DX-0iI" secondAttribute="trailing" constant="15" id="Mvm-xF-mBt"/>
+                <constraint firstItem="4vH-45-Chd" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="21" id="O2v-Gs-O4d"/>
+                <constraint firstItem="rc8-DX-0iI" firstAttribute="leading" secondItem="9V8-cK-iyl" secondAttribute="trailing" constant="7" id="OoB-ni-QdQ"/>
+                <constraint firstItem="4vH-45-Chd" firstAttribute="leading" secondItem="xYH-lk-TmS" secondAttribute="leading" id="V73-cN-aTk"/>
+                <constraint firstItem="9V8-cK-iyl" firstAttribute="centerY" secondItem="xYH-lk-TmS" secondAttribute="centerY" id="Wpf-5C-7b7"/>
+                <constraint firstItem="9V8-cK-iyl" firstAttribute="leading" secondItem="4vH-45-Chd" secondAttribute="trailing" constant="2" id="YGC-kR-Y0A"/>
+                <constraint firstItem="9V8-cK-iyl" firstAttribute="trailing" secondItem="xYH-lk-TmS" secondAttribute="trailing" id="bxq-LR-3dd"/>
+                <constraint firstItem="4vH-45-Chd" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="fpw-OL-CnH"/>
+                <constraint firstItem="rc8-DX-0iI" firstAttribute="centerY" secondItem="9V8-cK-iyl" secondAttribute="centerY" id="hjs-An-lhR"/>
+                <constraint firstItem="NCc-jc-GUf" firstAttribute="trailing" secondItem="fVB-PC-63v" secondAttribute="trailing" id="kBG-MY-f2w"/>
+                <constraint firstItem="NCc-jc-GUf" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="15" id="m9J-e5-2NN"/>
+                <constraint firstItem="NCc-jc-GUf" firstAttribute="leading" secondItem="fVB-PC-63v" secondAttribute="leading" id="oXb-oe-TDL"/>
+                <constraint firstAttribute="trailing" secondItem="26D-B3-H5O" secondAttribute="trailing" id="pPk-LH-Rgf"/>
+                <constraint firstItem="NCc-jc-GUf" firstAttribute="bottom" secondItem="fVB-PC-63v" secondAttribute="bottom" id="pX6-Oq-ogS"/>
+                <constraint firstItem="26D-B3-H5O" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="r3M-30-MoX"/>
+                <constraint firstItem="26D-B3-H5O" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="tNr-fR-lzI"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="colorView" destination="fVB-PC-63v" id="RfO-qi-mpt"/>
+                <outlet property="descLabel" destination="9V8-cK-iyl" id="USd-4i-tB2"/>
+                <outlet property="imageContainer" destination="rc8-DX-0iI" id="5wL-9N-z9I"/>
+                <outlet property="statusImage" destination="4vH-45-Chd" id="6f7-dz-b0M"/>
+                <outlet property="sureButton" destination="NCc-jc-GUf" id="lgY-Q6-38k"/>
+            </connections>
+            <point key="canvasLocation" x="151.90839694656489" y="166.19718309859155"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="unChoose_status" width="18" height="18"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 33 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanNavView.h

@@ -0,0 +1,33 @@
+//
+//  GroupBanNavView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import <UIKit/UIKit.h>
+typedef NS_ENUM(NSInteger, BANNAVACTION) {
+    BANNAVACTION_BACK = 0,     // 返回
+    BANNAVACTION_UNBAN,        // 未禁言
+    BANNAVACTION_BAN,          // 已禁言
+};
+
+
+typedef void(^BanNavCallback)(BANNAVACTION action);
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupBanNavView : UIView
+
++ (instancetype)shareInstance;
+
++ (CGFloat)getViewHeight;
+
+- (void)banNavAction:(BanNavCallback)callback;
+
+- (void)scrollTableIndex:(NSInteger)navIndex;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 96 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanNavView.m

@@ -0,0 +1,96 @@
+//
+//  GroupBanNavView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import "GroupBanNavView.h"
+
+@interface GroupBanNavView ()
+
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *lineLeft;
+
+@property (weak, nonatomic) IBOutlet UILabel *unBanLabel;
+
+@property (weak, nonatomic) IBOutlet UILabel *banLabel;
+
+@property (nonatomic, assign) NSInteger chooseIndex;
+
+@property (nonatomic, copy) BanNavCallback callback;
+
+@end
+
+@implementation GroupBanNavView
+
++ (instancetype)shareInstance {
+    GroupBanNavView *view = [[[NSBundle mainBundle] loadNibNamed:@"GroupBanNavView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)banNavAction:(BanNavCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (void)scrollTableIndex:(NSInteger)navIndex {
+    if (navIndex == self.chooseIndex) {
+        return;
+    }
+    self.chooseIndex = navIndex;
+}
+
+- (void)setChooseIndex:(NSInteger)chooseIndex {
+    _chooseIndex = chooseIndex;
+    CGFloat left = 0.0f;
+    if (chooseIndex == 0) {
+        left = 37;
+        [self.unBanLabel setTextColor:HexRGB(0x333333)];
+        [self.unBanLabel setFont:[UIFont systemFontOfSize:18.0f weight:UIFontWeightMedium]];
+        [self.banLabel setTextColor:HexRGB(0x777777)];
+        [self.banLabel setFont:[UIFont systemFontOfSize:18.0f]];
+    }
+    else {
+        left = 127;
+        [self.unBanLabel setTextColor:HexRGB(0x777777)];
+        [self.unBanLabel setFont:[UIFont systemFontOfSize:18.0f]];
+        [self.banLabel setTextColor:HexRGB(0x333333)];
+        [self.banLabel setFont:[UIFont systemFontOfSize:18.0f weight:UIFontWeightMedium]];
+    }
+    [UIView animateWithDuration:0.3f animations:^{
+        self.lineLeft.constant = left;
+    }];
+}
+
+- (IBAction)tapAction:(UITapGestureRecognizer *)sender {
+    NSInteger index = sender.view.tag - 1001;
+    if (index == self.chooseIndex) {
+        return;
+    }
+    self.chooseIndex = index;
+    BANNAVACTION action = index == 0 ? BANNAVACTION_UNBAN : BANNAVACTION_BAN;
+    if (self.callback) {
+        self.callback(action);
+    }
+}
+
+- (IBAction)backAction:(id)sender {
+    if (self.callback) {
+        self.callback(BANNAVACTION_BACK);
+    }
+}
+
+
++ (CGFloat)getViewHeight {
+    return kNaviBarHeight;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 162 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/GroupBanNavView.xib

@@ -0,0 +1,162 @@
+<?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" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <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="GroupBanNavView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="80"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="9T1-wm-kp3">
+                    <rect key="frame" x="0.0" y="36" width="393" height="44"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="back_black" translatesAutoresizingMaskIntoConstraints="NO" id="itK-XD-eqE">
+                            <rect key="frame" x="14" y="12" width="12" height="20"/>
+                        </imageView>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="O47-8h-Tf7">
+                            <rect key="frame" x="0.0" y="0.0" width="44" height="44"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="44" id="9AG-EI-0hL"/>
+                            </constraints>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="backAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="JX3-TX-8V7"/>
+                            </connections>
+                        </button>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="2SM-v4-OFF">
+                            <rect key="frame" x="106.66666666666669" y="0.0" width="180" height="44"/>
+                            <subviews>
+                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vb0-cf-bXr">
+                                    <rect key="frame" x="36.999999999999986" y="37" width="16" height="4"/>
+                                    <color key="backgroundColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="calibratedRGB"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="16" id="VsD-hY-syn"/>
+                                        <constraint firstAttribute="height" constant="4" id="tfk-oQ-ngH"/>
+                                    </constraints>
+                                    <userDefinedRuntimeAttributes>
+                                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                            <real key="value" value="2"/>
+                                        </userDefinedRuntimeAttribute>
+                                    </userDefinedRuntimeAttributes>
+                                </view>
+                                <view tag="1001" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fTb-kj-Zar">
+                                    <rect key="frame" x="0.0" y="0.0" width="90" height="44"/>
+                                    <subviews>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="未禁言" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0Wi-pt-Vlp">
+                                            <rect key="frame" x="15" y="9.6666666666666643" width="60" height="25"/>
+                                            <constraints>
+                                                <constraint firstAttribute="height" constant="25" id="Oz0-ml-9Ra"/>
+                                                <constraint firstAttribute="width" constant="60" id="pBj-ML-pP5"/>
+                                            </constraints>
+                                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="18"/>
+                                            <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" 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 firstAttribute="trailing" secondItem="0Wi-pt-Vlp" secondAttribute="trailing" constant="15" id="7mI-ki-BW9"/>
+                                        <constraint firstItem="0Wi-pt-Vlp" firstAttribute="leading" secondItem="fTb-kj-Zar" secondAttribute="leading" constant="15" id="bPH-gV-IOp"/>
+                                        <constraint firstItem="0Wi-pt-Vlp" firstAttribute="centerX" secondItem="fTb-kj-Zar" secondAttribute="centerX" id="l1w-MR-0Az"/>
+                                        <constraint firstItem="0Wi-pt-Vlp" firstAttribute="centerY" secondItem="fTb-kj-Zar" secondAttribute="centerY" id="puG-qG-J0o"/>
+                                    </constraints>
+                                    <connections>
+                                        <outletCollection property="gestureRecognizers" destination="pV8-A0-deX" appends="YES" id="OI2-bF-Ln5"/>
+                                    </connections>
+                                </view>
+                                <view tag="1002" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MIP-W5-35v">
+                                    <rect key="frame" x="90" y="0.0" width="90" height="44"/>
+                                    <subviews>
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="已禁言" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jRo-FE-XrA">
+                                            <rect key="frame" x="15" y="4.6666666666666643" width="60" height="35"/>
+                                            <gestureRecognizers/>
+                                            <constraints>
+                                                <constraint firstAttribute="width" constant="60" id="97G-AB-nrw"/>
+                                                <constraint firstAttribute="height" constant="35" id="Vem-MI-0qc"/>
+                                            </constraints>
+                                            <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="jRo-FE-XrA" firstAttribute="leading" secondItem="MIP-W5-35v" secondAttribute="leading" constant="15" id="LER-Qh-Ihd"/>
+                                        <constraint firstAttribute="trailing" secondItem="jRo-FE-XrA" secondAttribute="trailing" constant="15" id="lJr-jp-9Ug"/>
+                                        <constraint firstItem="jRo-FE-XrA" firstAttribute="centerX" secondItem="MIP-W5-35v" secondAttribute="centerX" id="qH0-Hi-3N6"/>
+                                        <constraint firstItem="jRo-FE-XrA" firstAttribute="centerY" secondItem="MIP-W5-35v" secondAttribute="centerY" id="wrK-kj-oxL"/>
+                                    </constraints>
+                                    <connections>
+                                        <outletCollection property="gestureRecognizers" destination="yNJ-ZU-MzF" appends="YES" id="ei7-mF-bG7"/>
+                                    </connections>
+                                </view>
+                            </subviews>
+                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            <constraints>
+                                <constraint firstItem="fTb-kj-Zar" firstAttribute="top" secondItem="2SM-v4-OFF" secondAttribute="top" id="Gbk-9a-5Cc"/>
+                                <constraint firstAttribute="bottom" secondItem="vb0-cf-bXr" secondAttribute="bottom" constant="3" id="MQu-cz-lrK"/>
+                                <constraint firstAttribute="trailing" secondItem="MIP-W5-35v" secondAttribute="trailing" id="ObR-sn-WVD"/>
+                                <constraint firstItem="fTb-kj-Zar" firstAttribute="leading" secondItem="2SM-v4-OFF" secondAttribute="leading" id="QL0-PV-4ag"/>
+                                <constraint firstItem="MIP-W5-35v" firstAttribute="top" secondItem="2SM-v4-OFF" secondAttribute="top" id="QX6-on-gmi"/>
+                                <constraint firstItem="MIP-W5-35v" firstAttribute="width" secondItem="fTb-kj-Zar" secondAttribute="width" id="Uf3-PH-Vb5"/>
+                                <constraint firstItem="MIP-W5-35v" firstAttribute="leading" secondItem="fTb-kj-Zar" secondAttribute="trailing" id="dak-gt-OJD"/>
+                                <constraint firstAttribute="bottom" secondItem="fTb-kj-Zar" secondAttribute="bottom" id="eAM-yQ-afY"/>
+                                <constraint firstAttribute="bottom" secondItem="MIP-W5-35v" secondAttribute="bottom" id="j8i-qG-q0m"/>
+                                <constraint firstItem="vb0-cf-bXr" firstAttribute="leading" secondItem="2SM-v4-OFF" secondAttribute="leading" constant="37" id="rxM-Tx-pbd"/>
+                            </constraints>
+                        </view>
+                    </subviews>
+                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="2SM-v4-OFF" firstAttribute="centerY" secondItem="9T1-wm-kp3" secondAttribute="centerY" id="2aW-oG-Hbo"/>
+                        <constraint firstItem="itK-XD-eqE" firstAttribute="leading" secondItem="9T1-wm-kp3" secondAttribute="leading" constant="14" id="3Mu-Od-3jW"/>
+                        <constraint firstItem="2SM-v4-OFF" firstAttribute="centerX" secondItem="9T1-wm-kp3" secondAttribute="centerX" id="6oi-gH-rUB"/>
+                        <constraint firstAttribute="bottom" secondItem="2SM-v4-OFF" secondAttribute="bottom" id="DSZ-Jy-cJn"/>
+                        <constraint firstItem="O47-8h-Tf7" firstAttribute="top" secondItem="9T1-wm-kp3" secondAttribute="top" id="Pnf-2J-bMU"/>
+                        <constraint firstItem="O47-8h-Tf7" firstAttribute="leading" secondItem="9T1-wm-kp3" secondAttribute="leading" id="Y5m-zz-EBP"/>
+                        <constraint firstItem="2SM-v4-OFF" firstAttribute="top" secondItem="9T1-wm-kp3" secondAttribute="top" id="b7v-w2-61f"/>
+                        <constraint firstItem="itK-XD-eqE" firstAttribute="centerY" secondItem="9T1-wm-kp3" secondAttribute="centerY" id="jUP-B9-Es4"/>
+                        <constraint firstAttribute="height" constant="44" id="ooa-1N-bgd"/>
+                        <constraint firstAttribute="bottom" secondItem="O47-8h-Tf7" secondAttribute="bottom" id="yNZ-j2-dLs"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="9T1-wm-kp3" secondAttribute="trailing" id="06D-d8-6iw"/>
+                <constraint firstAttribute="bottom" secondItem="9T1-wm-kp3" secondAttribute="bottom" id="U0V-1S-HgK"/>
+                <constraint firstItem="9T1-wm-kp3" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="wUJ-cU-BRh"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="banLabel" destination="jRo-FE-XrA" id="uW1-NC-Wsr"/>
+                <outlet property="lineLeft" destination="rxM-Tx-pbd" id="nFe-6g-i5f"/>
+                <outlet property="unBanLabel" destination="0Wi-pt-Vlp" id="wdg-Xt-Hwi"/>
+            </connections>
+            <point key="canvasLocation" x="275.57251908396944" y="-140.84507042253523"/>
+        </view>
+        <tapGestureRecognizer id="pV8-A0-deX">
+            <connections>
+                <action selector="tapAction:" destination="iN0-l3-epB" id="UtU-I0-6bH"/>
+            </connections>
+        </tapGestureRecognizer>
+        <tapGestureRecognizer id="yNJ-ZU-MzF">
+            <connections>
+                <action selector="tapAction:" destination="iN0-l3-epB" id="MN5-hy-gvj"/>
+            </connections>
+        </tapGestureRecognizer>
+    </objects>
+    <resources>
+        <image name="back_black" width="12" height="20"/>
+    </resources>
+</document>

+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentChooseDisplayCell.h

@@ -0,0 +1,22 @@
+//
+//  StudentChooseDisplayCell.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import <UIKit/UIKit.h>
+#import "GroupMemberModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^DeleteStuCallback)(NSString *studentId);
+
+
+@interface StudentChooseDisplayCell : UITableViewCell
+
+- (void)configSource:(GroupMemberModel *)model callback:(DeleteStuCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 51 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentChooseDisplayCell.m

@@ -0,0 +1,51 @@
+//
+//  StudentChooseDisplayCell.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/20.
+//
+
+#import "StudentChooseDisplayCell.h"
+
+@interface StudentChooseDisplayCell ()
+
+@property (weak, nonatomic) IBOutlet UIImageView *studentAvatar;
+
+@property (weak, nonatomic) IBOutlet UILabel *studentName;
+
+@property (nonatomic, copy) DeleteStuCallback callback;
+
+@property (nonatomic, strong) GroupMemberModel *source;
+
+@end
+
+@implementation StudentChooseDisplayCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+}
+
+- (void)configSource:(GroupMemberModel *)model callback:(DeleteStuCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    self.source = model;
+    [self.studentAvatar sd_setImageWithURL:[NSURL URLWithString:[model.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:USERDEFAULT_LOGO]];
+    self.studentName.text = [NSString returnNoNullStringWithString:model.nickname];
+}
+
+- (IBAction)deleteAction:(id)sender {
+    if (self.callback) {
+        self.callback([NSString stringWithFormat:@"%.0f",self.source.internalBaseClassIdentifier]);
+    }
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+@end

+ 93 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentChooseDisplayCell.xib

@@ -0,0 +1,93 @@
+<?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">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <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"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="51" id="KGk-i7-Jjw" customClass="StudentChooseDisplayCell">
+            <rect key="frame" x="0.0" y="0.0" width="320" height="51"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
+                <rect key="frame" x="0.0" y="0.0" width="320" height="51"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Xqt-GI-iob">
+                        <rect key="frame" x="0.0" y="5.6666666666666679" width="320" height="40"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="user_default_avatal" translatesAutoresizingMaskIntoConstraints="NO" id="61W-tA-OJT">
+                                <rect key="frame" x="12" y="0.0" width="40" height="40"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="40" id="Sx9-pW-icG"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="20"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </imageView>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="m3d-Hv-dDu">
+                                <rect key="frame" x="264" y="0.0" width="40" height="40"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="40" id="FGA-ge-SUj"/>
+                                    <constraint firstAttribute="height" constant="40" id="KV3-ut-czz"/>
+                                </constraints>
+                                <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                                <state key="normal" image="modify_cancel"/>
+                                <connections>
+                                    <action selector="deleteAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="fVe-ek-fGb"/>
+                                </connections>
+                            </button>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3pe-ib-wZa">
+                                <rect key="frame" x="64" y="10" width="188" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="Pq8-yo-rxW"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                        </subviews>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <constraint firstItem="61W-tA-OJT" firstAttribute="top" secondItem="Xqt-GI-iob" secondAttribute="top" id="AqS-6l-sxQ"/>
+                            <constraint firstAttribute="trailing" secondItem="m3d-Hv-dDu" secondAttribute="trailing" constant="16" id="Cat-dQ-ZaX"/>
+                            <constraint firstItem="61W-tA-OJT" firstAttribute="leading" secondItem="Xqt-GI-iob" secondAttribute="leading" constant="12" id="PpR-gB-CFP"/>
+                            <constraint firstItem="3pe-ib-wZa" firstAttribute="leading" secondItem="61W-tA-OJT" secondAttribute="trailing" constant="12" id="imK-xE-nyw"/>
+                            <constraint firstAttribute="bottom" secondItem="m3d-Hv-dDu" secondAttribute="bottom" id="lNR-hz-H0K"/>
+                            <constraint firstItem="m3d-Hv-dDu" firstAttribute="top" secondItem="Xqt-GI-iob" secondAttribute="top" id="lek-WO-YWP"/>
+                            <constraint firstAttribute="height" constant="40" id="nEg-u8-u1B"/>
+                            <constraint firstAttribute="bottom" secondItem="61W-tA-OJT" secondAttribute="bottom" id="u7e-wr-oBN"/>
+                            <constraint firstItem="3pe-ib-wZa" firstAttribute="centerY" secondItem="Xqt-GI-iob" secondAttribute="centerY" id="z90-Ua-O1z"/>
+                            <constraint firstItem="m3d-Hv-dDu" firstAttribute="leading" secondItem="3pe-ib-wZa" secondAttribute="trailing" constant="12" id="zOt-nm-E7q"/>
+                        </constraints>
+                    </view>
+                </subviews>
+                <constraints>
+                    <constraint firstAttribute="trailing" secondItem="Xqt-GI-iob" secondAttribute="trailing" id="57u-xC-1dH"/>
+                    <constraint firstItem="Xqt-GI-iob" firstAttribute="centerY" secondItem="H2p-sc-9uM" secondAttribute="centerY" id="Me7-K2-s9W"/>
+                    <constraint firstItem="Xqt-GI-iob" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="Neg-te-RNP"/>
+                </constraints>
+            </tableViewCellContentView>
+            <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
+            <connections>
+                <outlet property="studentAvatar" destination="61W-tA-OJT" id="Dnf-TX-RY9"/>
+                <outlet property="studentName" destination="3pe-ib-wZa" id="hYy-su-RfP"/>
+            </connections>
+            <point key="canvasLocation" x="-3.0534351145038165" y="22.183098591549296"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="modify_cancel" width="15" height="15"/>
+        <image name="user_default_avatal" width="52" height="52"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 24 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentPreviewView.h

@@ -0,0 +1,24 @@
+//
+//  StudentPreviewView.h
+//  GuanYueTeamManager
+//
+//  Created by 王智 on 2024/2/20.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^ModifyCallback)(NSMutableArray * _Nonnull studentArray);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface StudentPreviewView : UIView
+
++ (instancetype)shareInstance;
+
+- (void)configWithSource:(NSMutableArray *)studentArray callback:(ModifyCallback)callback;
+
+- (void)showView;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 146 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentPreviewView.m

@@ -0,0 +1,146 @@
+//
+//  StudentPreviewView.m
+//  GuanYueTeamManager
+//
+//  Created by 王智 on 2024/2/20.
+//
+
+#import "StudentPreviewView.h"
+#import "StudentChooseDisplayCell.h"
+#import "GroupMemberModel.h"
+
+@interface StudentPreviewView ()<UITableViewDelegate, UITableViewDataSource,UIGestureRecognizerDelegate>
+
+@property (weak, nonatomic) IBOutlet UIView *bgView;
+
+@property (weak, nonatomic) IBOutlet UIView *tableContainer;
+
+@property (weak, nonatomic) IBOutlet UILabel *countLabel;
+
+@property (nonatomic, strong) UITableView *tableView;
+
+@property (nonatomic, strong) NSMutableArray *sourceArray;
+
+@property (nonatomic, copy) ModifyCallback callback;
+
+@end
+
+@implementation StudentPreviewView
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    self.bgView.layer.cornerRadius = 10.0f;
+    self.bgView.layer.maskedCorners = kCALayerMinXMinYCorner | kCALayerMaxXMinYCorner;
+    [self.tableContainer addSubview:self.tableView];
+    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.bottom.mas_equalTo(self.tableContainer);
+    }];
+    
+    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideView)];
+    tap.delegate = self;
+    [self addGestureRecognizer:tap];
+}
+
++ (instancetype)shareInstance {
+    StudentPreviewView *view = [[[NSBundle mainBundle] loadNibNamed:@"StudentPreviewView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)configWithSource:(NSMutableArray *)studentArray callback:(ModifyCallback)callback {
+    self.sourceArray = [NSMutableArray arrayWithArray:studentArray];
+    if (callback) {
+        self.callback = callback;
+    }
+    [self configCountLabel];
+    [self.tableView reloadData];
+}
+
+- (void)configCountLabel {
+    self.countLabel.text = [NSString stringWithFormat:@"已选择 (%zd)",self.sourceArray.count];
+}
+
+- (void)showView {
+    UIView *displayView = [NSObject getKeyWindow];
+    [displayView addSubview:self];
+    [self mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.bottom.mas_equalTo(displayView);
+    }];
+}
+
+- (IBAction)sureAction:(id)sender {
+    [self hideView];
+}
+
+- (IBAction)cancelAction:(id)sender {
+    [self hideView];
+}
+
+
+- (void)hideView {
+    if (self.callback) {
+        self.callback(self.sourceArray);
+    }
+    [self removeFromSuperview];
+}
+
+#pragma mark ---- table data source
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    return self.sourceArray.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    GroupMemberModel *model = self.sourceArray[indexPath.row];
+    StudentChooseDisplayCell *cell = [tableView dequeueReusableCellWithIdentifier:@"StudentChooseDisplayCell"];
+    MJWeakSelf;
+    [cell configSource:model callback:^(NSString * _Nonnull studentId) {
+        [weakSelf removeUser:studentId];
+    }];
+    return cell;
+}
+
+- (void)removeUser:(NSString *)userId {
+    for (GroupMemberModel *model in self.sourceArray) {
+        if ([[NSString stringWithFormat:@"%.0f",model.internalBaseClassIdentifier] isEqualToString:userId]) {
+            [self.sourceArray removeObject:model];
+            break;
+        }
+    }
+    [self configCountLabel];
+    [self.tableView reloadData];
+}
+
+- (UITableView *)tableView {
+    if (!_tableView) {
+        _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
+        _tableView.backgroundColor = [UIColor clearColor];
+        _tableView.delegate = self;
+        _tableView.dataSource = self;
+        _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+        _tableView.showsVerticalScrollIndicator = NO;
+        [_tableView registerNib:[UINib nibWithNibName:@"StudentChooseDisplayCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"StudentChooseDisplayCell"];
+        _tableView.rowHeight = 60.0f;
+        UIView *headView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, 10)];
+        headView.backgroundColor = [UIColor whiteColor];
+        _tableView.tableHeaderView = headView;
+        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, 15)];
+        bottomView.backgroundColor = [UIColor clearColor];
+        _tableView.tableFooterView = bottomView;
+    }
+    return _tableView;
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
+    if ([touch.view isDescendantOfView:self.bgView]) {
+        return NO;
+    }
+    return YES;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 110 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/BanList/View/StudentPreviewView.xib

@@ -0,0 +1,110 @@
+<?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" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <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="StudentPreviewView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="X19-GQ-sdf">
+                    <rect key="frame" x="0.0" y="159" width="393" height="693"/>
+                    <subviews>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="已选择 " textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kvU-gX-aZP">
+                            <rect key="frame" x="170" y="16" width="53" height="22"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="22" id="Dro-Ab-UJm"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
+                            <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="uNl-th-DGF">
+                            <rect key="frame" x="321" y="14" width="52" height="26"/>
+                            <color key="backgroundColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="52" id="1hj-A1-Tmw"/>
+                                <constraint firstAttribute="height" constant="26" id="f9b-5y-2XR"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" title="确定">
+                                <color key="titleColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            </state>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="6"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                            <connections>
+                                <action selector="sureAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="u2j-9C-W5C"/>
+                            </connections>
+                        </button>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="cpw-OS-rws">
+                            <rect key="frame" x="0.0" y="50" width="393" height="643"/>
+                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        </view>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="cancel_dark" translatesAutoresizingMaskIntoConstraints="NO" id="nQa-CD-U3J">
+                            <rect key="frame" x="20" y="16" width="19" height="19"/>
+                        </imageView>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="XUw-im-x2a">
+                            <rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="50" id="aJ4-rv-Xj5"/>
+                            </constraints>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="cancelAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="yi8-wC-MFN"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <constraints>
+                        <constraint firstAttribute="trailing" secondItem="uNl-th-DGF" secondAttribute="trailing" constant="20" id="0EP-9d-Hqp"/>
+                        <constraint firstItem="nQa-CD-U3J" firstAttribute="leading" secondItem="X19-GQ-sdf" secondAttribute="leading" constant="20" id="27U-N7-aJW"/>
+                        <constraint firstItem="uNl-th-DGF" firstAttribute="top" secondItem="X19-GQ-sdf" secondAttribute="top" constant="14" id="437-fl-vZa"/>
+                        <constraint firstAttribute="trailing" secondItem="cpw-OS-rws" secondAttribute="trailing" id="45d-QR-uxQ"/>
+                        <constraint firstItem="cpw-OS-rws" firstAttribute="leading" secondItem="X19-GQ-sdf" secondAttribute="leading" id="8TL-yb-rh1"/>
+                        <constraint firstItem="nQa-CD-U3J" firstAttribute="top" secondItem="X19-GQ-sdf" secondAttribute="top" constant="16" id="Gpf-JJ-ndL"/>
+                        <constraint firstItem="cpw-OS-rws" firstAttribute="top" secondItem="XUw-im-x2a" secondAttribute="bottom" id="N6W-nx-98n"/>
+                        <constraint firstAttribute="bottom" secondItem="cpw-OS-rws" secondAttribute="bottom" id="QAo-DJ-LvS"/>
+                        <constraint firstItem="kvU-gX-aZP" firstAttribute="centerX" secondItem="X19-GQ-sdf" secondAttribute="centerX" id="ZBa-yW-crY"/>
+                        <constraint firstItem="XUw-im-x2a" firstAttribute="leading" secondItem="X19-GQ-sdf" secondAttribute="leading" id="ZtZ-jk-g6P"/>
+                        <constraint firstItem="XUw-im-x2a" firstAttribute="top" secondItem="X19-GQ-sdf" secondAttribute="top" id="gl7-Ct-b2e"/>
+                        <constraint firstItem="kvU-gX-aZP" firstAttribute="top" secondItem="X19-GQ-sdf" secondAttribute="top" constant="16" id="qHE-P5-hSz"/>
+                        <constraint firstItem="cpw-OS-rws" firstAttribute="top" secondItem="uNl-th-DGF" secondAttribute="bottom" constant="10" id="uIc-h3-bkk"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="X19-GQ-sdf" secondAttribute="trailing" id="7pe-aF-HJd"/>
+                <constraint firstItem="X19-GQ-sdf" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="159" id="Vgq-kL-grI"/>
+                <constraint firstItem="X19-GQ-sdf" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="iCx-Zm-Z0S"/>
+                <constraint firstAttribute="bottom" secondItem="X19-GQ-sdf" secondAttribute="bottom" id="jjF-Qa-iUk"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="bgView" destination="X19-GQ-sdf" id="bne-9F-mCY"/>
+                <outlet property="countLabel" destination="kvU-gX-aZP" id="umn-m2-eTb"/>
+                <outlet property="tableContainer" destination="cpw-OS-rws" id="Pkq-gb-ynl"/>
+            </connections>
+            <point key="canvasLocation" x="-16.030534351145036" y="19.718309859154932"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="cancel_dark" width="19" height="19"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 18 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSMuteTipsView.h

@@ -0,0 +1,18 @@
+//
+//  KSMuteTipsView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/21.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSMuteTipsView : UIView
+
++ (instancetype)shareInstance;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 24 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSMuteTipsView.m

@@ -0,0 +1,24 @@
+//
+//  KSMuteTipsView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/5/21.
+//
+
+#import "KSMuteTipsView.h"
+
+@implementation KSMuteTipsView
+
++ (instancetype)shareInstance {
+    KSMuteTipsView *view = [[[NSBundle mainBundle] loadNibNamed:@"KSMuteTipsView" owner:nil options:nil] firstObject];
+    return view;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 53 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSMuteTipsView.xib

@@ -0,0 +1,53 @@
+<?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">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.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">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="45"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mute_tips" translatesAutoresizingMaskIntoConstraints="NO" id="pe5-GS-WtP">
+                    <rect key="frame" x="160" y="12.666666666666664" width="22" height="20"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="20" id="OAX-rX-PYH"/>
+                        <constraint firstAttribute="width" constant="22" id="sYH-E8-dkX"/>
+                    </constraints>
+                </imageView>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="禁言中" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sfe-Tx-y9r">
+                    <rect key="frame" x="187" y="13.666666666666664" width="46" height="18"/>
+                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="15"/>
+                    <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
+            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstItem="sfe-Tx-y9r" firstAttribute="leading" secondItem="pe5-GS-WtP" secondAttribute="trailing" constant="5" id="7vO-yp-H0i"/>
+                <constraint firstItem="sfe-Tx-y9r" firstAttribute="centerY" secondItem="pe5-GS-WtP" secondAttribute="centerY" id="90M-2j-OtE"/>
+                <constraint firstItem="sfe-Tx-y9r" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="DDP-QK-6ob"/>
+                <constraint firstItem="sfe-Tx-y9r" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" constant="13.5" id="I8M-DX-7gI"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <userDefinedRuntimeAttributes>
+                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                    <real key="value" value="6"/>
+                </userDefinedRuntimeAttribute>
+            </userDefinedRuntimeAttributes>
+            <point key="canvasLocation" x="35.877862595419849" y="-124.29577464788733"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="mute_tips" width="22" height="20"/>
+    </resources>
+</document>

+ 530 - 1
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Controller/TXCustom/KSTXGroupChatViewController.m

@@ -6,16 +6,545 @@
 //
 
 #import "KSTXGroupChatViewController.h"
+#import <TIMCommon/NSString+TUIEmoji.h>
+#import <TIMCommon/TIMCommonModel.h>
+#import <TIMCommon/TIMDefine.h>
+#import <TUICore/NSDictionary+TUISafe.h>
+#import <TUICore/TUICore.h>
+#import <TUICore/TUILogin.h>
+#import "TUIBaseChatViewController+ProtectedAPI.h"
+#import "TUIGroupChatViewController.h"
+#import "TUIGroupPendencyController.h"
+#import "TUIGroupPendencyDataProvider.h"
+#import "TUILinkCellData.h"
+#import "TUIMessageDataProvider.h"
+#import "TUITextMessageCellData.h"
+#import "KSMuteTipsView.h"
+#import "CustomNavViewController.h"
 
-@interface KSTXGroupChatViewController ()
+@interface KSTXGroupChatViewController ()<V2TIMGroupListener>
+
+@property(nonatomic, strong) UIView *tipsView;
+@property(nonatomic, strong) UILabel *pendencyLabel;
+@property(nonatomic, strong) UIButton *pendencyBtn;
+
+@property(nonatomic, strong) TUIGroupPendencyDataProvider *pendencyViewModel;
+@property(nonatomic, strong) NSMutableArray<TUIUserModel *> *atUserList;
+@property(nonatomic, assign) BOOL responseKeyboard;
+
+@property (nonatomic, strong) UIView *muteView;
+
+@property (nonatomic, strong) dispatch_group_t requestGroup;
+
+@property (nonatomic, assign) BOOL isGroupMute; // 是否群禁言
+
+@property (nonatomic, assign) BOOL isUserMute;  // 是否个人禁言
+
+@property (nonatomic, assign) BOOL isGroupManager; // 是否管理员
+
+@property (nonatomic, assign) BOOL isMute;
 
 @end
 
 @implementation KSTXGroupChatViewController
 
+- (void)setIsMute:(BOOL)isMute {
+    _isMute = isMute;
+    UIView *viewContainer = self.inputController.inputBar;
+    if (isMute) {
+        if ([viewContainer.subviews containsObject:self.muteView]) {
+            [viewContainer bringSubviewToFront:self.muteView];
+        }
+        else {
+            [viewContainer addSubview:self.muteView];
+            [self.muteView mas_makeConstraints:^(MASConstraintMaker *make) {
+                make.left.right.top.bottom.mas_equalTo(viewContainer);
+            }];
+        }
+        @weakObj(self);
+        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+            @strongObj(self);
+            [self resetStatus];
+        });
+    }
+    else {
+        if ([viewContainer.subviews containsObject:self.muteView]) {
+            [self.muteView removeFromSuperview];
+        }
+    }
+}
+
+- (void)resetStatus {
+    UIViewController *ctrl = [self theTopviewControler];
+    if ([ctrl isKindOfClass:NSClassFromString(@"KSGroupConversationController")] || [ctrl isKindOfClass:NSClassFromString(@"UIDocumentPickerViewController")]) {
+        // 重置键盘状态
+        [self.inputController reset];
+        [self.inputController exitReplyAndReference:nil];
+        [self.inputController.inputBar clearInput];
+        [self.inputController.inputBar.inputTextView resignFirstResponder];
+        [self removePopMemuView];
+        [self.messageController enableMultiSelectedMode:NO]; // 关闭选择
+    }
+}
+
+- (UIViewController *)theTopviewControler {
+    UIViewController *rootVC = [[UIApplication sharedApplication].delegate window].rootViewController;
+    UIViewController *parent = rootVC;
+    while ((parent = rootVC.presentedViewController) != nil) {
+        rootVC = parent;
+    }
+    while ([rootVC isKindOfClass:[UINavigationController class]]) {
+        rootVC = [(UINavigationController *)rootVC topViewController];
+    }
+    while ([rootVC isKindOfClass:[UITabBarController class]]) {
+        UITabBarController *tab = (UITabBarController *)rootVC;
+        CustomNavViewController *ctrl = (CustomNavViewController *)tab.selectedViewController;
+        if (ctrl.presentedViewController) {
+            rootVC = ctrl.presentedViewController;
+        }
+        else {
+            rootVC = [ctrl topViewController];
+        }
+    }
+    return rootVC;
+}
+- (void)removePopMemuView {
+    for (UIView *view in self.messageController.tableView.subviews) {
+        if ([view isKindOfClass:NSClassFromString(@"TUIChatPopMenu")]) {
+            [view removeFromSuperview];
+        }
+    }
+}
+
+- (dispatch_group_t)requestGroup {
+    if (!_requestGroup) {
+        _requestGroup = dispatch_group_create();
+    }
+    return _requestGroup;
+}
+
+- (UIView *)muteView {
+    if (!_muteView) {
+        _muteView = [[UIView alloc] initWithFrame:CGRectZero];
+        _muteView.backgroundColor = HexRGB(0xEBF0F6);
+        KSMuteTipsView *tipsView = [KSMuteTipsView shareInstance];
+        [_muteView addSubview:tipsView];
+        [tipsView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.top.mas_equalTo(_muteView.mas_top).offset(10);
+            make.left.mas_equalTo(_muteView.mas_left).offset(12);
+            make.right.mas_equalTo(_muteView.mas_right).offset(-12);
+            make.height.mas_equalTo(36);
+        }];
+    }
+    return _muteView;
+}
+
 - (void)viewDidLoad {
     [super viewDidLoad];
     // Do any additional setup after loading the view.
+    [self setupTipsView];
+    
+    [[V2TIMManager sharedInstance] addGroupListener:self];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
+    [self getGroupAndMemberInfo];
+}
+
+- (void)getGroupAndMemberInfo {
+    [self getGroupInfo];
+    [self getMineInfo];
+    dispatch_group_notify(self.requestGroup, dispatch_get_main_queue(), ^{
+        [self modifyMuteViewDisplay];
+    });
+}
+
+- (void)getMineInfo {
+    dispatch_group_enter(self.requestGroup);
+    
+    [[V2TIMManager sharedInstance] getGroupMembersInfo:self.conversationData.groupID memberList:@[UserDefault(IM_USERID)] succ:^(NSArray<V2TIMGroupMemberFullInfo *> *memberList) {
+        for (V2TIMGroupMemberFullInfo *memberInfo in memberList) {
+            uint64_t currentTime = [self getCurrentTime];
+            
+            if (memberInfo.muteUntil > currentTime) { // 存在禁言时间
+                self.isUserMute = YES;
+            }
+            else {
+                self.isUserMute = NO;
+            }
+        }
+        dispatch_group_leave(self.requestGroup);
+    } fail:^(int code, NSString *desc) {
+        dispatch_group_leave(self.requestGroup);
+    }];
+}
+
+- (uint64_t)getCurrentTime {
+    return [[V2TIMManager sharedInstance] getServerTime];
+}
+
+- (void)getGroupInfo {
+    dispatch_group_enter(self.requestGroup);
+    [[V2TIMManager sharedInstance] getGroupsInfo:@[self.conversationData.groupID] succ:^(NSArray<V2TIMGroupInfoResult *> *groupResultList) {
+        for (V2TIMGroupInfoResult *result in groupResultList) {
+            V2TIMGroupInfo *groupInfo = result.info;
+            if (groupInfo.role == 300 || groupInfo.role == 400) {
+                self.isGroupManager = YES;
+            }
+            else {
+                self.isGroupManager = NO;
+            }
+            
+            if (groupInfo.allMuted) { // 全员禁言
+                self.isGroupMute = YES;
+            }
+            else {
+                self.isGroupMute = NO;
+            }
+        }
+        dispatch_group_leave(self.requestGroup);
+    } fail:^(int code, NSString *desc) {
+        dispatch_group_leave(self.requestGroup);
+    }];
+    
+}
+
+- (void)modifyMuteViewDisplay {
+    
+    if ((self.isGroupMute && self.isGroupManager == NO) || self.isUserMute) {
+        self.isMute = YES;
+    }
+    else {
+        self.isMute = NO;
+    }
+    
+}
+
+- (void)dealloc {
+    [TUICore unRegisterEventByObject:self];
+}
+
+- (void)setupTipsView {
+    self.tipsView = [[UIView alloc] initWithFrame:CGRectZero];
+    self.tipsView.backgroundColor = RGB(246, 234, 190);
+    [self.view addSubview:self.tipsView];
+    self.tipsView.mm_height(24).mm_width(self.view.mm_w);
+    
+    self.pendencyLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+    [self.tipsView addSubview:self.pendencyLabel];
+    self.pendencyLabel.font = [UIFont systemFontOfSize:12];
+    
+    self.pendencyBtn = [UIButton buttonWithType:UIButtonTypeSystem];
+    [self.tipsView addSubview:self.pendencyBtn];
+    [self.pendencyBtn setTitle:TIMCommonLocalizableString(TUIKitChatPendencyTitle) forState:UIControlStateNormal];
+    [self.pendencyBtn.titleLabel setFont:[UIFont systemFontOfSize:12]];
+    [self.pendencyBtn addTarget:self action:@selector(openPendency:) forControlEvents:UIControlEventTouchUpInside];
+    [self.pendencyBtn sizeToFit];
+    self.tipsView.alpha = 0;
+    
+    @weakify(self);
+    [RACObserve(self.pendencyViewModel, unReadCnt) subscribeNext:^(NSNumber *unReadCnt) {
+        @strongify(self);
+        if ([unReadCnt intValue]) {
+            self.pendencyLabel.text = [NSString stringWithFormat:TIMCommonLocalizableString(TUIKitChatPendencyRequestToJoinGroupFormat), unReadCnt];
+            [self.pendencyLabel sizeToFit];
+            CGFloat gap = (self.tipsView.mm_w - self.pendencyLabel.mm_w - self.pendencyBtn.mm_w - 8) / 2;
+            self.pendencyLabel.mm_left(gap).mm__centerY(self.tipsView.mm_h / 2);
+            self.pendencyBtn.mm_hstack(8);
+            
+            self.tipsView.alpha = 1;
+            UIView *topView = [TUIGroupChatViewController customTopView];
+            self.tipsView.mm_top(topView ? topView.mm_h : 0);
+        } else {
+            self.tipsView.alpha = 0;
+        }
+    }];
+    
+    [self getPendencyList];
+}
+
+- (void)getPendencyList {
+    if (self.conversationData.groupID.length > 0) [self.pendencyViewModel loadData];
+}
+
+- (void)openPendency:(id)sender {
+    TUIGroupPendencyController *vc = [[TUIGroupPendencyController alloc] init];
+    @weakify(self);
+    vc.cellClickBlock = ^(TUIGroupPendencyCell *_Nonnull cell) {
+        if (cell.pendencyData.isRejectd || cell.pendencyData.isAccepted) {
+            // 选择后不再进详情页了
+            return;
+        }
+        @strongify(self);
+        [[V2TIMManager sharedInstance] getUsersInfo:@[ cell.pendencyData.fromUser ]
+                                               succ:^(NSArray<V2TIMUserFullInfo *> *profiles) {
+            // 显示用户资料 VC
+            NSDictionary *param = @{
+                TUICore_TUIContactObjectFactory_UserProfileController_UserProfile : profiles.firstObject,
+                TUICore_TUIContactObjectFactory_UserProfileController_PendencyData : cell.pendencyData,
+                TUICore_TUIContactObjectFactory_UserProfileController_ActionType : @(3)
+            };
+            [self.navigationController pushViewController:TUICore_TUIContactObjectFactory_UserProfileController_Classic
+                                                    param:param
+                                                forResult:nil];
+        }
+                                               fail:nil];
+    };
+    vc.viewModel = self.pendencyViewModel;
+    [self.navigationController pushViewController:vc animated:YES];
+}
+
+- (void)setConversationData:(TUIChatConversationModel *)conversationData {
+    [super setConversationData:conversationData];
+    
+    if (self.conversationData.groupID.length > 0) {
+        _pendencyViewModel = [TUIGroupPendencyDataProvider new];
+        _pendencyViewModel.groupId = conversationData.groupID;
+    }
+    
+    self.atUserList = [NSMutableArray array];
+}
+
+#pragma mark - V2TIMGroupListener
+- (void)onReceiveJoinApplication:(NSString *)groupID member:(V2TIMGroupMemberInfo *)member opReason:(NSString *)opReason {
+    [self getPendencyList];
+}
+
+- (void)onGroupInfoChanged:(NSString *)groupID changeInfoList:(NSArray<V2TIMGroupChangeInfo *> *)changeInfoList {
+    if (![groupID isEqualToString:self.conversationData.groupID]) {
+        return;
+    }
+    for (V2TIMGroupChangeInfo *changeInfo in changeInfoList) {
+        if (changeInfo.type == V2TIM_GROUP_INFO_CHANGE_TYPE_NAME) {
+            self.conversationData.title = changeInfo.value;
+            return;
+        }
+        else if (changeInfo.type == V2TIM_GROUP_INFO_CHANGE_TYPE_SHUT_UP_ALL) { // 群禁言
+            // 提示
+            BOOL mute = changeInfo.boolValue;
+            if (mute) {
+                self.isGroupMute = YES;
+            }
+            else {
+                self.isGroupMute = NO;
+            }
+            // 刷新状态
+            [self modifyMuteViewDisplay];
+        }
+        else if (changeInfo.type == V2TIM_GROUP_INFO_CHANGE_TYPE_OWNER)  { // 群主变更
+            NSString *userID = changeInfo.value;
+            if ([userID isEqualToString:UserDefault(IM_USERID)]) {
+                self.isGroupManager = YES;
+                // 刷新状态
+                [self modifyMuteViewDisplay];
+            }
+        }
+    }
+}
+//searchGroupMembers
+- (void)onMemberInfoChanged:(NSString *)groupID changeInfoList:(NSArray<V2TIMGroupMemberChangeInfo *> *)changeInfoList {
+    for (V2TIMGroupMemberChangeInfo *memberChangeInfo in changeInfoList) {
+        if ([memberChangeInfo.userID isEqualToString:UserDefault(IM_USERID)]) {
+            if (memberChangeInfo.muteTime > 0) {
+                self.isUserMute = YES;
+            }
+            else {
+                self.isUserMute = NO;
+            }
+        }
+    }
+    // 刷新状态
+    [self modifyMuteViewDisplay];
+}
+
+/// 指定管理员身份
+- (void)onGrantAdministrator:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser memberList:(NSArray <V2TIMGroupMemberInfo *> *)memberList {
+    for (V2TIMGroupMemberInfo *memberInfo in memberList) {
+        if ([memberInfo.userID isEqualToString:UserDefault(IM_USERID)]) {
+            self.isGroupManager = YES;
+        }
+    }
+    // 刷新状态
+    [self modifyMuteViewDisplay];
+}
+
+/// 取消管理员身份
+- (void)onRevokeAdministrator:(NSString *)groupID opUser:(V2TIMGroupMemberInfo *)opUser memberList:(NSArray <V2TIMGroupMemberInfo *> *)memberList {
+    for (V2TIMGroupMemberInfo *memberInfo in memberList) {
+        if ([memberInfo.userID isEqualToString:UserDefault(IM_USERID)]) {
+            self.isGroupManager = NO;
+        }
+    }
+    // 刷新状态
+    [self modifyMuteViewDisplay];
+}
+
+#pragma mark - TUIInputControllerDelegate
+- (void)inputController:(TUIInputController *)inputController didSendMessage:(V2TIMMessage *)msg {
+    /**
+     * 文本消息如果有 @ 用户,需要 createTextAtMessage
+     * If the text message has @ user, createTextAtMessage is required
+     */
+    if (msg.elemType == V2TIM_ELEM_TYPE_TEXT) {
+        NSMutableArray *atUserList = [NSMutableArray array];
+        for (TUIUserModel *model in self.atUserList) {
+            if (model.userId) {
+                [atUserList addObject:model.userId];
+            }
+        }
+        if (atUserList.count > 0) {
+            NSData *cloudCustomData = msg.cloudCustomData;
+            msg = [[V2TIMManager sharedInstance] createTextAtMessage:msg.textElem.text atUserList:atUserList];
+            msg.cloudCustomData = cloudCustomData;
+        }
+        /**
+         * 消息发送完后 atUserList 要重置
+         * After the message is sent, the atUserList need to be reset
+         */
+        [self.atUserList removeAllObjects];
+    }
+    [super inputController:inputController didSendMessage:msg];
+}
+
+- (void)inputControllerDidInputAt:(TUIInputController *)inputController {
+    [super inputControllerDidInputAt:inputController];
+    /**
+     * 检测到 @ 字符的输入
+     * Input of @ character detected
+     */
+    if (self.conversationData.groupID.length > 0) {
+        if ([self.navigationController.topViewController isKindOfClass:NSClassFromString(@"TUISelectGroupMemberViewController")]) {
+            return;
+        }
+        __weak typeof(self) weakSelf = self;
+        NSMutableDictionary *param = [NSMutableDictionary dictionary];
+        param[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_GroupID] = self.conversationData.groupID;
+        param[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Name] = TIMCommonLocalizableString(TUIKitAtSelectMemberTitle);
+        param[TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_OptionalStyle] = @(1);
+        [self.navigationController
+         pushViewController:TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_Classic
+         param:param
+         forResult:^(NSDictionary *_Nonnull param) {
+            NSArray<TUIUserModel *> *modelList = [param tui_objectForKey:TUICore_TUIGroupObjectFactory_SelectGroupMemberVC_ResultUserList
+                                                                 asClass:NSArray.class];
+            NSMutableString *atText = [[NSMutableString alloc] init];
+            for (int i = 0; i < modelList.count; i++) {
+                TUIUserModel *model = modelList[i];
+                if (![model isKindOfClass:TUIUserModel.class]) {
+                    NSAssert(NO, @"Error data-type in modelList");
+                    continue;
+                }
+                [weakSelf.atUserList addObject:model];
+                if (i == 0) {
+                    [atText appendString:[NSString stringWithFormat:@"%@ ", model.name]];
+                } else {
+                    [atText appendString:[NSString stringWithFormat:@"@%@ ", model.name]];
+                }
+            }
+            
+            NSAttributedString *spaceString = [[NSAttributedString alloc]
+                                               initWithString:atText
+                                               attributes:@{NSFontAttributeName : kTUIInputNoramlFont, NSForegroundColorAttributeName : kTUIInputNormalTextColor}];
+            NSRange range = weakSelf.inputController.inputBar.inputTextView.selectedRange;
+            [weakSelf.inputController.inputBar.inputTextView.textStorage insertAttributedString:spaceString atIndex:range.location + range.length];
+            [weakSelf.inputController.inputBar updateTextViewFrame];
+        }];
+    }
+}
+
+- (void)inputController:(TUIInputController *)inputController didDeleteAt:(NSString *)atText {
+    [super inputController:inputController didDeleteAt:atText];
+    
+    for (TUIUserModel *user in self.atUserList) {
+        if ([atText rangeOfString:user.name].location != NSNotFound) {
+            [self.atUserList removeObject:user];
+            break;
+        }
+    }
+}
+
+- (void)inputController:(TUIInputController *)inputController didSelectMoreCell:(TUIInputMoreCell *)cell {
+    [super inputController:inputController didSelectMoreCell:cell];
+}
+
+#pragma mark - TUIBaseMessageControllerDelegate
+- (void)messageController:(TUIBaseMessageController *)controller onLongSelectMessageAvatar:(TUIMessageCell *)cell {
+    if (self.isMute) {
+        return;
+    }
+    if (!cell || !cell.messageData || !cell.messageData.identifier) {
+        return;
+    }
+    if ([cell.messageData.identifier isEqualToString:[TUILogin getUserID]]) {
+        return;
+    }
+    BOOL atUserExist = NO;
+    for (TUIUserModel *model in self.atUserList) {
+        if ([model.userId isEqualToString:cell.messageData.identifier]) {
+            atUserExist = YES;
+            break;
+        }
+    }
+    if (!atUserExist) {
+        TUIUserModel *user = [[TUIUserModel alloc] init];
+        user.userId = cell.messageData.identifier;
+        user.name = cell.messageData.name;
+        [self.atUserList addObject:user];
+        
+        NSString *nameString = [NSString stringWithFormat:@"@%@ ", user.name];
+        UIFont *textFont = kTUIInputNoramlFont;
+        NSAttributedString *spaceString = [[NSAttributedString alloc] initWithString:nameString attributes:@{NSFontAttributeName : textFont}];
+        [self.inputController.inputBar.inputTextView.textStorage insertAttributedString:spaceString
+                                                                                atIndex:self.inputController.inputBar.inputTextView.textStorage.length];
+        [self.inputController.inputBar.inputTextView becomeFirstResponder];
+        self.inputController.inputBar.inputTextView.selectedRange =
+        NSMakeRange(spaceString.length + self.inputController.inputBar.inputTextView.textStorage.length, 0);
+    }
+}
+
+- (void)messageController:(TUIBaseMessageController *)controller onSelectMessageMenu:(NSInteger)menuType withData:(TUIMessageCellData *)data {
+    if (self.isMute) {
+        [self.messageController enableMultiSelectedMode:NO]; // 关闭选择
+        return;
+    }
+    [self onSelectMessageMenu:menuType withData:data];
+}
+
+
+- (void)messageController:(TUIBaseMessageController *)controller onRelyMessage:(TUIMessageCellData *)data {
+    if (self.isMute) {
+        return;
+    }
+    [super messageController:controller onRelyMessage:data];
+}
+
+- (void)messageController:(TUIBaseMessageController *)controller onReferenceMessage:(TUIMessageCellData *)data {
+    if (self.isMute) {
+        return;
+    }
+    [super messageController:controller onReferenceMessage:data];
+
+}
+
+- (void)messageController:(TUIBaseMessageController *)controller modifyMessage:(nonnull TUIMessageCellData *)cellData reactEmoji:(NSString *)emojiName {
+    if (self.isMute) {
+        return;
+    }
+    [super messageController:controller modifyMessage:cellData reactEmoji:emojiName];
+}
+
+- (void)messageController:(TUIBaseMessageController *)controller onReEditMessage:(TUIMessageCellData *)data {
+    if (self.isMute) {
+        return;
+    }
+    [super messageController:controller onReEditMessage:data];
+}
+
+
+#pragma mark - Override Methods
+- (NSString *)forwardTitleWithMyName:(NSString *)nameStr {
+    return TIMCommonLocalizableString(TUIKitRelayGroupChatHistory);
 }
 
 

+ 70 - 4
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/Controller/GroupSettingViewController.m

@@ -20,6 +20,7 @@
 #import "CustomNavViewController.h"
 #import "TenantChooseMemberViewController.h"
 #import "TenantStuModel.h"
+#import "GroupBanListViewController.h"
 
 @interface GroupSettingViewController ()
 
@@ -33,6 +34,10 @@
 
 @property (nonatomic, strong) KSPublicAlertView *alertView;
 
+@property (nonatomic, strong) NSString *groupRoleType;
+
+@property (nonatomic, assign) BOOL isMute;
+
 @end
 
 @implementation GroupSettingViewController
@@ -45,12 +50,18 @@
 }
 
 - (void)configUI {
-    self.scrollView.frame = CGRectMake(0, 0, kScreenWidth, kScreenHeight - kNaviBarHeight - iPhoneXSafeBottomMargin);
+    self.scrollView.frame = CGRectMake(0, 0, KPortraitWidth, KPortraitHeight - kNaviBarHeight - iPhoneXSafeBottomMargin);
     self.bodyView = [GroupSettingBodyView shareInstance];
-    CGFloat height = kScreenHeight - kNaviBarHeight - iPhoneXSafeBottomMargin > 700 ? kScreenHeight - kNaviBarHeight - iPhoneXSafeBottomMargin : 700;
-    self.bodyView.frame = CGRectMake(0, 0, kScreenWidth, height);
+    CGFloat viewHeight = [self.bodyView getViewHeight:self.groupRoleType];
+    CGFloat height = KPortraitHeight - kNaviBarHeight - iPhoneXSafeBottomMargin > viewHeight ? KPortraitHeight - kNaviBarHeight - iPhoneXSafeBottomMargin : viewHeight;
+    self.bodyView.groupRoleType = @"";
     [self.scrollView addSubview:self.bodyView];
-    [self.scrollView setContentSize:CGSizeMake(kScreenWidth, height)];
+    [self.bodyView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self.view);
+        make.top.mas_equalTo(self.scrollView.mas_top);
+        make.bottom.mas_equalTo(self.scrollView.mas_bottom);
+        make.height.mas_equalTo(height);
+    }];
 }
 
 - (void)rightBtnClick {
@@ -80,6 +91,14 @@
 }
 
 - (void)evaluateMessge {
+    
+    self.bodyView.groupRoleType = self.groupRoleType;
+    CGFloat viewHeight = [self.bodyView getViewHeight:self.groupRoleType];
+    CGFloat height = kScreenHeight - kNaviBarHeight - iPhoneXSafeBottomMargin > viewHeight ? kScreenHeight - kNaviBarHeight - iPhoneXSafeBottomMargin : viewHeight;
+    [self.bodyView mas_updateConstraints:^(MASConstraintMaker *make) {
+        make.height.mas_equalTo(height);
+    }];
+
     NSMutableArray *memberArray = [NSMutableArray array];
     for (GroupMemberModel *model in self.sourceArray) {
         if (model.isAdmin) {
@@ -98,6 +117,15 @@
         if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
             NSDictionary *subDic = [dic ks_dictionaryValueForKey:@"data"];
             self.sourceModel = [[GroupListModel alloc] initWithDictionary:subDic];
+            NSString *jsonString = [subDic ks_stringValueForKey:@"configJson"];
+            if (![NSString isEmptyString:jsonString]) {
+                NSData *jsonData = [jsonString mj_JSONData];
+                NSDictionary *configJson = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];
+                self.isMute = [configJson ks_boolValueForKey:@"mute"];
+            }
+            else {
+                self.isMute = NO;
+            }
             [self refreshUI];
         }
         else if ([dic ks_integerValueForKey:@"code"] == 204) {
@@ -122,6 +150,9 @@
             NSArray *sourceArray = [dic ks_arrayValueForKey:@"data"];
             for (NSDictionary *parm in sourceArray) {
                 GroupMemberModel *model = [[GroupMemberModel alloc] initWithDictionary:parm];
+                if ([model.imUserId isEqualToString:UserDefault(IM_USERID)]) {
+                    self.groupRoleType = model.groupRoleType;
+                }
                 [self.sourceArray addObject:model];
             }
             [self evaluateMessge];
@@ -153,6 +184,7 @@
 }
 
 - (void)refreshUI {
+    self.bodyView.isMute = self.isMute;
     MJWeakSelf;
     [self.bodyView configWithSource:self.sourceModel callback:^(GROUPSETTING type) {
         [weakSelf operationWithType:type];
@@ -238,11 +270,45 @@
             [self.navigationController pushViewController:ctrl animated:YES];
         }
             break;
+        case GROUPSETTING_MUTE: // 禁言操作
+        {
+            if (self.sourceModel) {
+                [self muteAction];
+            }
+            else {
+                [LOADING_MANAGER MBShowAUTOHidingInWindow:@"您已不在当前群聊"];
+            }
+        }
+            break;
+        case GROUPSETTING_BANLIST: // 禁言列表
+        {
+            GroupBanListViewController *ctrl = [[GroupBanListViewController alloc] init];
+            ctrl.groupId = self.groupId;
+            [self.navigationController pushViewController:ctrl animated:YES];
+        }
+            break;
         default:
             break;
     }
 }
 
+- (void)muteAction {
+    BOOL isMute = !self.isMute;
+    [KSNetworkingManager imGroupMuteAllRequest:KS_POST groupId:self.groupId muteAll:isMute success:^(NSDictionary * _Nonnull dic) {
+        if ([dic ks_integerValueForKey:@"code"] == 200) {
+            [LOADING_MANAGER KSShowMsg:@"设置成功" promptCompletion:^{
+                [self requestData];
+            }];
+        }
+        else {
+            self.bodyView.isMute = self.isMute;
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        self.bodyView.isMute = self.isMute;
+    }];
+}
+
 - (void)addMember:(NSMutableArray *)array {
     if (array.count == 0) {
         return;

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

@@ -17,6 +17,8 @@ typedef NS_ENUM(NSInteger, GROUPSETTING) {
     GROUPSETTING_FEEDBACK, // 反馈
     GROUPSETTING_DISMISS, // 解散群聊
     GROUPSETTING_ADDMENBER, // 添加成员
+    GROUPSETTING_MUTE,  // 静言
+    GROUPSETTING_BANLIST, // 禁言列表
 };
 
 
@@ -26,18 +28,24 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface GroupSettingBodyView : UIView
 
+@property (nonatomic, strong) NSString *groupRoleType;
+
 @property (nonatomic, strong) NSString *groupType;
 
 @property (nonatomic, assign) NSInteger applyMember;
 
 @property (nonatomic, assign) BOOL isOn;
 
+@property (nonatomic, assign) BOOL isMute;
+
 + (instancetype)shareInstance;
 
 - (void)configWithSource:(id)source callback:(GroupSettingBlock)callback;
 
 - (void)evaluateStudentArray:(NSArray *)studentArray;
 
+- (CGFloat)getViewHeight:(NSString *)roleType;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 78 - 4
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Group/View/GroupSettingBodyView.m

@@ -134,9 +134,17 @@ typedef void(^ChooseMemberCallback)(NSString *targetId);
 
 @property (nonatomic, strong) UIScrollView *memberScrollView;
 
+@property (weak, nonatomic) IBOutlet UIView *fullbannedView;
+@property (weak, nonatomic) IBOutlet UIButton *muteButton;
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *fullBanHeight;
+
+@property (weak, nonatomic) IBOutlet UIView *banListView;
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *banListHeight;
+
 @end
 
 @implementation GroupSettingBodyView
+
 - (void)awakeFromNib {
     [super awakeFromNib];
     self.isOn = NO;
@@ -335,10 +343,18 @@ typedef void(^ChooseMemberCallback)(NSString *targetId);
     }
 }
 
-- (void)setIsOn:(BOOL)isOn {
-    _isOn = isOn;
-    NSString *imageName = isOn ? @"switch_on" : @"switch_off";
-    [self.switchButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
+- (IBAction)muteAction:(id)sender {
+    self.isMute = !self.isMute;
+    if (self.callback) {
+        self.callback(GROUPSETTING_MUTE);
+    }
+}
+
+
+- (IBAction)displayBanList:(id)sender {
+    if (self.callback) {
+        self.callback(GROUPSETTING_BANLIST);
+    }
 }
 
 - (UIScrollView *)memberScrollView {
@@ -347,6 +363,64 @@ typedef void(^ChooseMemberCallback)(NSString *targetId);
     }
     return _memberScrollView;
 }
+
+- (void)setIsOn:(BOOL)isOn {
+    _isOn = isOn;
+    NSString *imageName = isOn ? @"switch_on" : @"switch_off";
+    [self.switchButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
+}
+
+- (void)setIsMute:(BOOL)isMute {
+    _isMute = isMute;
+    NSString *imageName = isMute ? @"switch_on" : @"switch_off";
+    [self.muteButton setImage:[UIImage imageNamed:imageName] forState:UIControlStateNormal];
+}
+
+/***
+ Owner("群主"),
+ Admin("管理员"),
+ Member("群成员"),
+ */
+- (BOOL)hasManageGroupLimit {
+    if ([self.groupRoleType isEqualToString:@"Owner"] || [self.groupRoleType isEqualToString:@"Admin"]) {
+        return YES;
+    }
+    return NO;
+}
+
+- (void)setGroupRoleType:(NSString *)groupRoleType {
+    _groupRoleType = groupRoleType;
+    
+    if ([groupRoleType isEqualToString:@"Owner"]) {
+        self.fullbannedView.hidden = NO;
+        self.fullBanHeight.constant = 55.0f;
+        self.banListView.hidden = NO;
+        self.banListHeight.constant = 55.0f;
+    }
+    else if ([groupRoleType isEqualToString:@"Admin"]) {
+        self.fullbannedView.hidden = NO;
+        self.fullBanHeight.constant = 55.0f;
+        self.banListView.hidden = NO;
+        self.banListHeight.constant = 55.0f;
+        
+    }
+    else {
+        self.fullbannedView.hidden = YES;
+        self.fullBanHeight.constant = 0.0f;
+        self.banListView.hidden = YES;
+        self.banListHeight.constant = 0.0f;
+    }
+}
+
+- (CGFloat)getViewHeight:(NSString *)roleType {
+    BOOL bottomSpace = IS_iPhoneX ? iPhoneXSafeBottomMargin : 20;
+    if ([self.groupRoleType isEqualToString:@"Owner"] || [self.groupRoleType isEqualToString:@"Admin"]) {
+        return 790 + bottomSpace;
+    }
+    else {
+        return 680 + bottomSpace;
+    }
+}
 /*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.

+ 107 - 9
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="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" 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="21679"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
         <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="896"/>
+            <rect key="frame" x="0.0" y="0.0" width="414" height="817"/>
             <autoresizingMask key="autoresizingMask"/>
             <subviews>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AOx-4a-71e">
@@ -211,7 +211,7 @@
                     </connections>
                 </view>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aOO-cS-gdV">
-                    <rect key="frame" x="0.0" y="436" width="414" height="55"/>
+                    <rect key="frame" x="0.0" y="546" width="414" height="55"/>
                     <subviews>
                         <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="fl2-Rm-1E9">
                             <rect key="frame" x="347" y="7.5" width="47" height="40"/>
@@ -241,7 +241,7 @@
                     </constraints>
                 </view>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="0hZ-Dj-wqy">
-                    <rect key="frame" x="0.0" y="503" width="414" height="55"/>
+                    <rect key="frame" x="0.0" y="613" width="414" height="55"/>
                     <subviews>
                         <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mine_next" translatesAutoresizingMaskIntoConstraints="NO" id="jgL-fA-2h0">
                             <rect key="frame" x="392" y="20.5" width="7" height="14"/>
@@ -333,7 +333,7 @@
                     </connections>
                 </view>
                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="H5y-Vp-Aux">
-                    <rect key="frame" x="0.0" y="558" width="414" height="55"/>
+                    <rect key="frame" x="0.0" y="668" 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="392" y="20.5" width="7" height="14"/>
@@ -363,7 +363,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="643" width="358" height="44"/>
+                    <rect key="frame" x="28" y="753" width="358" height="44"/>
                     <color key="backgroundColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="calibratedRGB"/>
                     <constraints>
                         <constraint firstAttribute="height" constant="44" id="zlf-6G-YkC"/>
@@ -378,9 +378,92 @@
                         <action selector="dismissGroup:" destination="iN0-l3-epB" eventType="touchUpInside" id="Rr5-R1-TuG"/>
                     </connections>
                 </button>
+                <view autoresizesSubviews="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fy6-IY-oQY">
+                    <rect key="frame" x="0.0" y="424" width="414" height="55"/>
+                    <subviews>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="O4h-2N-H8x">
+                            <rect key="frame" x="13" y="0.0" width="388" height="1"/>
+                            <color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="1" id="uKJ-wQ-DcZ"/>
+                            </constraints>
+                        </view>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" layoutMarginsFollowReadableWidth="YES" text="学生禁言" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QbV-a9-wg4">
+                            <rect key="frame" x="13" y="17.5" width="65.5" height="20"/>
+                            <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>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="3mj-vH-cZt">
+                            <rect key="frame" x="347" y="7.5" width="47" height="40"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="40" id="XOU-8Q-QP6"/>
+                                <constraint firstAttribute="width" constant="47" id="bvx-hY-Qyf"/>
+                            </constraints>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" image="switch_off"/>
+                            <connections>
+                                <action selector="muteAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="wS6-9J-5no"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <constraints>
+                        <constraint firstItem="QbV-a9-wg4" firstAttribute="centerY" secondItem="fy6-IY-oQY" secondAttribute="centerY" id="24Y-gj-GnG"/>
+                        <constraint firstAttribute="trailing" secondItem="O4h-2N-H8x" secondAttribute="trailing" constant="13" id="AQ8-az-aKE"/>
+                        <constraint firstItem="O4h-2N-H8x" firstAttribute="leading" secondItem="fy6-IY-oQY" secondAttribute="leading" constant="13" id="He8-tc-JXN"/>
+                        <constraint firstItem="3mj-vH-cZt" firstAttribute="centerY" secondItem="fy6-IY-oQY" secondAttribute="centerY" id="WCh-oQ-eED"/>
+                        <constraint firstAttribute="trailing" secondItem="3mj-vH-cZt" secondAttribute="trailing" constant="20" id="ZAI-2d-uCC"/>
+                        <constraint firstAttribute="trailing" secondItem="3mj-vH-cZt" secondAttribute="trailing" constant="20" id="dOV-ng-lcX"/>
+                        <constraint firstItem="O4h-2N-H8x" firstAttribute="top" secondItem="fy6-IY-oQY" secondAttribute="top" id="nob-ZP-O4G"/>
+                        <constraint firstItem="QbV-a9-wg4" firstAttribute="leading" secondItem="fy6-IY-oQY" secondAttribute="leading" constant="13" id="vE7-HQ-HbE"/>
+                        <constraint firstAttribute="height" constant="55" id="wSL-OO-F62"/>
+                    </constraints>
+                </view>
+                <view tag="1012" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="351-sB-JCZ">
+                    <rect key="frame" x="0.0" y="479" width="414" height="55"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mine_next" translatesAutoresizingMaskIntoConstraints="NO" id="sGO-wF-f08">
+                            <rect key="frame" x="394" y="20.5" width="7" height="14"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="7" id="vQf-54-whb"/>
+                                <constraint firstAttribute="height" constant="14" id="zZ8-YS-Y8C"/>
+                            </constraints>
+                        </imageView>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" layoutMarginsFollowReadableWidth="YES" text="禁言名单" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="VVt-xF-zQW">
+                            <rect key="frame" x="13" y="17.5" width="65.5" height="20"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                            <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="B4z-Xs-JGO">
+                            <rect key="frame" x="13" y="0.0" width="388" height="1"/>
+                            <color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="1" id="hXt-p6-vz3"/>
+                            </constraints>
+                        </view>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <gestureRecognizers/>
+                    <constraints>
+                        <constraint firstItem="VVt-xF-zQW" firstAttribute="leading" secondItem="351-sB-JCZ" secondAttribute="leading" constant="13" id="6Xq-cf-W5j"/>
+                        <constraint firstItem="B4z-Xs-JGO" firstAttribute="top" secondItem="351-sB-JCZ" secondAttribute="top" id="DlR-ov-c7z"/>
+                        <constraint firstItem="sGO-wF-f08" firstAttribute="centerY" secondItem="351-sB-JCZ" secondAttribute="centerY" id="EIJ-UV-KdK"/>
+                        <constraint firstAttribute="trailing" secondItem="sGO-wF-f08" secondAttribute="trailing" constant="13" id="En0-ln-AE1"/>
+                        <constraint firstAttribute="height" constant="55" id="e2x-ks-Y8i"/>
+                        <constraint firstItem="B4z-Xs-JGO" firstAttribute="leading" secondItem="351-sB-JCZ" secondAttribute="leading" constant="13" id="fUR-Nq-f5e"/>
+                        <constraint firstItem="VVt-xF-zQW" firstAttribute="centerY" secondItem="351-sB-JCZ" secondAttribute="centerY" id="si4-4D-x0f"/>
+                        <constraint firstAttribute="trailing" secondItem="B4z-Xs-JGO" secondAttribute="trailing" constant="13" id="vsh-Tx-v2i"/>
+                    </constraints>
+                    <connections>
+                        <outletCollection property="gestureRecognizers" destination="9gG-Rf-jod" appends="YES" id="kGP-tY-O8e"/>
+                    </connections>
+                </view>
             </subviews>
             <color key="backgroundColor" red="0.96470588235294119" green="0.97254901960784312" blue="0.97647058823529409" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
             <constraints>
+                <constraint firstAttribute="trailing" secondItem="fy6-IY-oQY" secondAttribute="trailing" id="1Ig-ct-u5t"/>
                 <constraint firstItem="H5y-Vp-Aux" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="3wU-vo-NNQ"/>
                 <constraint firstItem="UZO-j7-eJs" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="4RH-2B-XdQ"/>
                 <constraint firstItem="DCz-5K-rHE" firstAttribute="top" secondItem="fRV-DB-sBs" secondAttribute="bottom" constant="12" id="5zV-xA-WL1"/>
@@ -397,16 +480,21 @@
                 <constraint firstItem="hNX-kx-Qhp" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Ki4-NK-uXf"/>
                 <constraint firstItem="0hZ-Dj-wqy" firstAttribute="top" secondItem="aOO-cS-gdV" secondAttribute="bottom" constant="12" id="MIH-E6-hx0"/>
                 <constraint firstItem="9Zk-Ss-xf8" firstAttribute="top" secondItem="H5y-Vp-Aux" secondAttribute="bottom" constant="30" id="N1t-gx-92V"/>
+                <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="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"/>
                 <constraint firstItem="hNX-kx-Qhp" firstAttribute="top" secondItem="DCz-5K-rHE" secondAttribute="bottom" id="dGJ-9S-cVx"/>
                 <constraint firstAttribute="trailing" secondItem="hNX-kx-Qhp" secondAttribute="trailing" id="ilu-5a-WOE"/>
                 <constraint firstAttribute="trailing" secondItem="9Zk-Ss-xf8" secondAttribute="trailing" constant="28" id="jPR-6G-jho"/>
                 <constraint firstAttribute="trailing" secondItem="DCz-5K-rHE" secondAttribute="trailing" id="ksy-CG-efB"/>
-                <constraint firstItem="aOO-cS-gdV" firstAttribute="top" secondItem="UZO-j7-eJs" secondAttribute="bottom" constant="12" id="miC-9L-nUn"/>
+                <constraint firstItem="351-sB-JCZ" firstAttribute="top" secondItem="fy6-IY-oQY" secondAttribute="bottom" id="lwb-rj-bpN"/>
+                <constraint firstItem="351-sB-JCZ" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="vhT-9a-u5w"/>
                 <constraint firstItem="H5y-Vp-Aux" firstAttribute="top" secondItem="0hZ-Dj-wqy" secondAttribute="bottom" id="vyf-Ns-eUM"/>
+                <constraint firstItem="aOO-cS-gdV" firstAttribute="top" secondItem="351-sB-JCZ" secondAttribute="bottom" constant="12" id="x1A-la-Wpa"/>
                 <constraint firstAttribute="trailing" secondItem="UZO-j7-eJs" secondAttribute="trailing" id="xBL-hk-DiD"/>
             </constraints>
             <nil key="simulatedTopBarMetrics"/>
@@ -416,15 +504,20 @@
                 <outlet property="applyCount" destination="hPH-bg-uLo" id="17Q-Ua-2GT"/>
                 <outlet property="applyView" destination="DCz-5K-rHE" id="tLd-wb-qgx"/>
                 <outlet property="applyViewHeight" destination="4Ur-wR-24e" id="mZ5-62-3aA"/>
+                <outlet property="banListHeight" destination="e2x-ks-Y8i" id="5UD-hD-GXN"/>
+                <outlet property="banListView" destination="351-sB-JCZ" id="JY9-Rm-pkz"/>
+                <outlet property="fullBanHeight" destination="wSL-OO-F62" id="vV3-qG-A2f"/>
+                <outlet property="fullbannedView" destination="fy6-IY-oQY" id="pl8-jV-jOy"/>
                 <outlet property="groupImage" destination="Pgc-8e-F0o" id="cD2-2v-pf4"/>
                 <outlet property="groupMemberDesc" destination="mGj-Ko-LcU" id="oD7-d5-0hD"/>
                 <outlet property="groupName" destination="hDS-dB-bma" id="Rpk-gW-4hb"/>
                 <outlet property="groupRemark" destination="Sg5-z3-lFr" id="VaL-W6-ZXb"/>
                 <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="switchButton" destination="fl2-Rm-1E9" id="xTR-c2-UCT"/>
             </connections>
-            <point key="canvasLocation" x="131.8840579710145" y="77.678571428571431"/>
+            <point key="canvasLocation" x="136.23188405797103" y="-59.933035714285708"/>
         </view>
         <tapGestureRecognizer id="hZ3-TO-Qmd">
             <connections>
@@ -456,6 +549,11 @@
                 <action selector="feedBack:" destination="iN0-l3-epB" id="8dM-yn-lG9"/>
             </connections>
         </tapGestureRecognizer>
+        <tapGestureRecognizer id="9gG-Rf-jod">
+            <connections>
+                <action selector="displayBanList:" destination="iN0-l3-epB" id="I8w-Ka-XSN"/>
+            </connections>
+        </tapGestureRecognizer>
     </objects>
     <resources>
         <image name="chat_group_Logo" width="44" height="44"/>

+ 3 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Model/GroupMemberModel.h

@@ -24,6 +24,9 @@
 @property (nonatomic, strong) NSString *firstLetter;
 @property (nonatomic, strong) NSString *imUserId;
 
+@property (nonatomic, strong) NSString *groupRoleType;
+
+
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
 - (instancetype)initWithDictionary:(NSDictionary *)dict;
 - (NSDictionary *)dictionaryRepresentation;

+ 11 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Chat/Model/GroupMemberModel.m

@@ -18,6 +18,7 @@ NSString *const kGroupMemberModelIsAdmin = @"isAdmin";
 NSString *const kGroupMemberModelGroupId = @"groupId";
 NSString *const kGroupMemberModelCreateTime = @"createTime";
 NSString *const kGroupMemberModelImUserId = @"imUserId";
+NSString *const kGroupMemberModelGroupRoleType = @"groupRoleType";
 
 @interface GroupMemberModel ()
 
@@ -37,6 +38,7 @@ NSString *const kGroupMemberModelImUserId = @"imUserId";
 @synthesize groupId = _groupId;
 @synthesize createTime = _createTime;
 @synthesize imUserId = _imUserId;
+@synthesize groupRoleType = _groupRoleType;
 
 + (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
 {
@@ -60,6 +62,8 @@ NSString *const kGroupMemberModelImUserId = @"imUserId";
             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];
+
     }
     
     return self;
@@ -79,6 +83,8 @@ NSString *const kGroupMemberModelImUserId = @"imUserId";
     [mutableDict setValue:self.groupId forKey:kGroupMemberModelGroupId];
     [mutableDict setValue:self.createTime forKey:kGroupMemberModelCreateTime];
     [mutableDict setValue:self.imUserId forKey:kGroupMemberModelImUserId];
+    [mutableDict setValue:self.groupRoleType forKey:kGroupMemberModelGroupRoleType];
+
     return [NSDictionary dictionaryWithDictionary:mutableDict];
 }
 
@@ -115,6 +121,8 @@ NSString *const kGroupMemberModelImUserId = @"imUserId";
     self.groupId = [aDecoder decodeObjectForKey:kGroupMemberModelGroupId];
     self.createTime = [aDecoder decodeObjectForKey:kGroupMemberModelCreateTime];
     self.imUserId = [aDecoder decodeObjectForKey:kGroupMemberModelImUserId];
+    self.groupRoleType = [aDecoder decodeObjectForKey:kGroupMemberModelGroupRoleType];
+
     return self;
 }
 
@@ -131,6 +139,8 @@ NSString *const kGroupMemberModelImUserId = @"imUserId";
     [aCoder encodeObject:_groupId forKey:kGroupMemberModelGroupId];
     [aCoder encodeObject:_createTime forKey:kGroupMemberModelCreateTime];
     [aCoder encodeObject:_imUserId forKey:kGroupMemberModelImUserId];
+    [aCoder encodeObject:_groupRoleType forKey:kGroupMemberModelGroupRoleType];
+
 }
 
 - (id)copyWithZone:(NSZone *)zone
@@ -149,6 +159,7 @@ NSString *const kGroupMemberModelImUserId = @"imUserId";
         copy.groupId = [self.groupId copyWithZone:zone];
         copy.createTime = [self.createTime copyWithZone:zone];
         copy.imUserId = [self.imUserId copyWithZone:zone];
+        copy.groupRoleType = [self.groupRoleType copyWithZone:zone];
     }
     
     return copy;