Kyle Smart hai 6 meses
pai
achega
c17feda692
Modificáronse 20 ficheiros con 1057 adicións e 117 borrados
  1. 32 0
      KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj
  2. 2 2
      KulexiuForStudent/KulexiuForStudent.xcodeproj/xcshareddata/xcschemes/KulexiuForStudent.xcscheme
  3. 9 0
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.h
  4. 13 0
      KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m
  5. 0 4
      KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/TXCustom/KSTXBaseChatViewController.h
  6. 31 31
      KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/TXCustom/KSTXBaseChatViewController.m
  7. 21 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Controller/GroupNoticeDetailViewController.h
  8. 50 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Controller/GroupNoticeDetailViewController.m
  9. 2 1
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Controller/GroupNoticeViewController.m
  10. 34 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Model/GroupNoticeDetailModel.h
  11. 197 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Model/GroupNoticeDetailModel.m
  12. 11 7
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeCell.m
  13. 74 72
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeCell.xib
  14. 24 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeDetailBodyView.h
  15. 85 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeDetailBodyView.m
  16. 166 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeDetailBodyView.xib
  17. 30 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/KSPopView.h
  18. 105 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/KSPopView.m
  19. 147 0
      KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/KSPopView.xib
  20. 24 0
      KulexiuForStudent/Pods/Pods.xcodeproj/project.pbxproj

+ 32 - 0
KulexiuForStudent/KulexiuForStudent.xcodeproj/project.pbxproj

@@ -316,6 +316,12 @@
 		BC27A074280FF60B00F91E27 /* AccompanyDetailBottomView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC27A073280FF60B00F91E27 /* AccompanyDetailBottomView.m */; };
 		BC27A076280FF61300F91E27 /* AccompanyDetailBottomView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC27A075280FF61300F91E27 /* AccompanyDetailBottomView.xib */; };
 		BC27A079280FFA2200F91E27 /* EvaluateDetailModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC27A078280FFA2200F91E27 /* EvaluateDetailModel.m */; };
+		BC2820FC2C9186E5008BD2CC /* GroupNoticeDetailModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC2820FB2C9186E5008BD2CC /* GroupNoticeDetailModel.m */; };
+		BC2821032C91875C008BD2CC /* GroupNoticeDetailBodyView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC2820FD2C91875B008BD2CC /* GroupNoticeDetailBodyView.xib */; };
+		BC2821042C91875C008BD2CC /* KSPopView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC2820FF2C91875B008BD2CC /* KSPopView.xib */; };
+		BC2821052C91875C008BD2CC /* KSPopView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC2821002C91875C008BD2CC /* KSPopView.m */; };
+		BC2821062C91875C008BD2CC /* GroupNoticeDetailBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC2821022C91875C008BD2CC /* GroupNoticeDetailBodyView.m */; };
+		BC2821092C918778008BD2CC /* GroupNoticeDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC2821072C918778008BD2CC /* GroupNoticeDetailViewController.m */; };
 		BC28582B2809036D0024697C /* StudentInfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC28582A2809036D0024697C /* StudentInfoModel.m */; };
 		BC2888582A80F7BF0064B773 /* KSLoginManager.m in Sources */ = {isa = PBXBuildFile; fileRef = BC2888552A80F7BF0064B773 /* KSLoginManager.m */; };
 		BC2888592A80F7BF0064B773 /* TXIMLinsenter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC2888572A80F7BF0064B773 /* TXIMLinsenter.m */; };
@@ -1526,6 +1532,16 @@
 		BC27A075280FF61300F91E27 /* AccompanyDetailBottomView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccompanyDetailBottomView.xib; sourceTree = "<group>"; };
 		BC27A077280FFA2100F91E27 /* EvaluateDetailModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EvaluateDetailModel.h; sourceTree = "<group>"; };
 		BC27A078280FFA2200F91E27 /* EvaluateDetailModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EvaluateDetailModel.m; sourceTree = "<group>"; };
+		BC2820FA2C9186E5008BD2CC /* GroupNoticeDetailModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupNoticeDetailModel.h; sourceTree = "<group>"; };
+		BC2820FB2C9186E5008BD2CC /* GroupNoticeDetailModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupNoticeDetailModel.m; sourceTree = "<group>"; };
+		BC2820FD2C91875B008BD2CC /* GroupNoticeDetailBodyView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GroupNoticeDetailBodyView.xib; sourceTree = "<group>"; };
+		BC2820FE2C91875B008BD2CC /* KSPopView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSPopView.h; sourceTree = "<group>"; };
+		BC2820FF2C91875B008BD2CC /* KSPopView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSPopView.xib; sourceTree = "<group>"; };
+		BC2821002C91875C008BD2CC /* KSPopView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSPopView.m; sourceTree = "<group>"; };
+		BC2821012C91875C008BD2CC /* GroupNoticeDetailBodyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupNoticeDetailBodyView.h; sourceTree = "<group>"; };
+		BC2821022C91875C008BD2CC /* GroupNoticeDetailBodyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupNoticeDetailBodyView.m; sourceTree = "<group>"; };
+		BC2821072C918778008BD2CC /* GroupNoticeDetailViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GroupNoticeDetailViewController.m; sourceTree = "<group>"; };
+		BC2821082C918778008BD2CC /* GroupNoticeDetailViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GroupNoticeDetailViewController.h; sourceTree = "<group>"; };
 		BC2858292809036C0024697C /* StudentInfoModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StudentInfoModel.h; sourceTree = "<group>"; };
 		BC28582A2809036D0024697C /* StudentInfoModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StudentInfoModel.m; sourceTree = "<group>"; };
 		BC2888542A80F7BF0064B773 /* TXIMLinsenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXIMLinsenter.h; sourceTree = "<group>"; };
@@ -2589,6 +2605,8 @@
 				2723B5E227F157D400E0B90B /* GroupNoticeEditController.m */,
 				2723B5E327F157D400E0B90B /* GroupNoticeViewController.h */,
 				2723B5E027F157D400E0B90B /* GroupNoticeViewController.m */,
+				BC2821082C918778008BD2CC /* GroupNoticeDetailViewController.h */,
+				BC2821072C918778008BD2CC /* GroupNoticeDetailViewController.m */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -2598,6 +2616,8 @@
 			children = (
 				2723B5E527F157D400E0B90B /* GroupNoticeModel.h */,
 				2723B5E627F157D400E0B90B /* GroupNoticeModel.m */,
+				BC2820FA2C9186E5008BD2CC /* GroupNoticeDetailModel.h */,
+				BC2820FB2C9186E5008BD2CC /* GroupNoticeDetailModel.m */,
 			);
 			path = Model;
 			sourceTree = "<group>";
@@ -2612,6 +2632,12 @@
 				2723B5E927F157D400E0B90B /* NoticeEditBodyView.h */,
 				2723B5F127F157D400E0B90B /* NoticeEditBodyView.m */,
 				2723B5EA27F157D400E0B90B /* NoticeEditBodyView.xib */,
+				BC2821012C91875C008BD2CC /* GroupNoticeDetailBodyView.h */,
+				BC2821022C91875C008BD2CC /* GroupNoticeDetailBodyView.m */,
+				BC2820FD2C91875B008BD2CC /* GroupNoticeDetailBodyView.xib */,
+				BC2820FE2C91875B008BD2CC /* KSPopView.h */,
+				BC2821002C91875C008BD2CC /* KSPopView.m */,
+				BC2820FF2C91875B008BD2CC /* KSPopView.xib */,
 			);
 			path = View;
 			sourceTree = "<group>";
@@ -6260,6 +6286,7 @@
 				BCC583D028A9EC6400BAB4CF /* cloud_animation_3.png in Resources */,
 				BCC0F66F2A8CD8F500C4EFA4 /* TXClassRoomAlertView.xib in Resources */,
 				BC89AC102AB0843000B077AF /* TenantNewMusicView.xib in Resources */,
+				BC2821042C91875C008BD2CC /* KSPopView.xib in Resources */,
 				BC71D26A288804CD0010F14B /* img_19.png in Resources */,
 				BC1D02422C0490AB001F6A94 /* KSMuteTipsView.xib in Resources */,
 				BCC0F6032A8CD86C00C4EFA4 /* TX3ASettingView.xib in Resources */,
@@ -6422,6 +6449,7 @@
 				BC71D269288804CD0010F14B /* img_31.png in Resources */,
 				BC71D25D288804CD0010F14B /* img_47.png in Resources */,
 				BCA353F12859BB2900377661 /* MusicRoomCourseCell.xib in Resources */,
+				BC2821032C91875C008BD2CC /* GroupNoticeDetailBodyView.xib in Resources */,
 				BCC583B828A9EC6400BAB4CF /* cloud_animation_23.png in Resources */,
 				BC756CC328FE7DA900AA9ECB /* UserDetailNavView.xib in Resources */,
 				2723B66E27F15CFC00E0B90B /* PhoneCheckBodyView.xib in Resources */,
@@ -6806,6 +6834,7 @@
 				BC2933002AAEFC810024D98E /* INSSettingViewController.m in Sources */,
 				BCB5B2D12ABAFE8E005BF25D /* HomeMusicSheetLayout.m in Sources */,
 				BC31BF0D2B21925700F7D538 /* WidgetViewController.m in Sources */,
+				BC2821062C91875C008BD2CC /* GroupNoticeDetailBodyView.m in Sources */,
 				BC542E4B28409E9F00633781 /* InstrumentChooseViewController.m in Sources */,
 				BC9AA0DE2ABC434900CD954D /* KSCustomLoadingView.m in Sources */,
 				BC11927A280FB07F00A716F7 /* AccompanyArrangeCell.m in Sources */,
@@ -6883,6 +6912,7 @@
 				BC1E28492C77151A0063E0A1 /* KSDeleteFailedAlertView.m in Sources */,
 				BC2888592A80F7BF0064B773 /* TXIMLinsenter.m in Sources */,
 				BCC0F6D42A8CE1BE00C4EFA4 /* LoginHelper.m in Sources */,
+				BC2821052C91875C008BD2CC /* KSPopView.m in Sources */,
 				275FA23C27E7356B00CFEA2E /* VefiBodyView.m in Sources */,
 				BCED5CA7284F55A0009A42DE /* FriendListModel.m in Sources */,
 				BC106C012A933829000759A9 /* TXLiveMessageBlockUser.m in Sources */,
@@ -6962,6 +6992,7 @@
 				BCC0F6B42A8CDD4000C4EFA4 /* KSRemoteUserManager.m in Sources */,
 				BC106C072A933829000759A9 /* TXLiveMessageLikeCount.m in Sources */,
 				BCBFDF46281159990052AFE5 /* HomeHotAlbumView.m in Sources */,
+				BC2821092C918778008BD2CC /* GroupNoticeDetailViewController.m in Sources */,
 				2779356A27E324A70010E277 /* YKNodeModel.m in Sources */,
 				BC106C052A933829000759A9 /* TXLiveMessageKickOut.m in Sources */,
 				BCB6348227F6D29600ACFDCF /* SeatContentView.m in Sources */,
@@ -7015,6 +7046,7 @@
 				BC38C45F2AFA095D00ABFCC2 /* MineWorksBottomView.m in Sources */,
 				BC38C45A2AFA095D00ABFCC2 /* MineWorksNavView.m in Sources */,
 				BC494A8028696BC300CCD343 /* MusicRoomListModel.m in Sources */,
+				BC2820FC2C9186E5008BD2CC /* GroupNoticeDetailModel.m in Sources */,
 				BCB9FA4A286EDE1A005D766B /* BaseAlertView.m in Sources */,
 				2779355B27E324A70010E277 /* KSStatusView.m in Sources */,
 				BC31BF312B21925700F7D538 /* IACircleSliderThumbLayer.m in Sources */,

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

@@ -51,7 +51,7 @@
       </Testables>
    </TestAction>
    <LaunchAction
-      buildConfiguration = "Debug"
+      buildConfiguration = "DEV"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       launchStyle = "0"
@@ -92,7 +92,7 @@
       buildConfiguration = "Debug">
    </AnalyzeAction>
    <ArchiveAction
-      buildConfiguration = "Release"
+      buildConfiguration = "DEV"
       revealArchiveInOrganizer = "YES">
    </ArchiveAction>
 </Scheme>

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

@@ -393,6 +393,15 @@ NS_ASSUME_NONNULL_BEGIN
 /// @param faliure 失败
 + (void)queryNoticeListRequest:(NSString *)post groupId:(NSString *)groupId page:(NSString *)page rows:(NSString *)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
 
+// api-student/imGroupNotice/get
+
+/// 群公告详情
+/// @param get get
+/// @param noticeId 公告ID
+/// @param success 成功
+/// @param faliure 失败
++ (void)imGroupNoticeDetailRequest:(NSString *)get noticeId:(NSString *)noticeId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure;
+
 #pragma mark ----- 直播相关
 // 进入直播房间
 // /api-student/liveRoom/joinRoom

+ 13 - 0
KulexiuForStudent/KulexiuForStudent/Common/Base/KSNetworkingManager.m

@@ -905,6 +905,19 @@
     [self request:post andWithUrl:url and:parm success:success faliure:faliure];
 }
 
+// api-student/imGroupNotice/get
+
+/// 群公告详情
+/// @param get get
+/// @param noticeId 公告ID
+/// @param success 成功
+/// @param faliure 失败
++ (void)imGroupNoticeDetailRequest:(NSString *)get noticeId:(NSString *)noticeId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
+    NSString *url = [NSString stringWithFormat:@"%@%@/%@", hostURL, @"/api-student/imGroupNotice/get", noticeId];
+    NSMutableDictionary *parm = [NSMutableDictionary dictionary];
+    [self request:get andWithUrl:url and:parm success:success faliure:faliure];
+}
+
 #pragma mark ----- 直播相关
 // 进入直播房间
 // /api-student/liveRoom/joinRoom

+ 0 - 4
KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/TXCustom/KSTXBaseChatViewController.h

@@ -6,10 +6,6 @@
 //
 
 #import "TUIBaseChatViewController.h"
-#import <UIKit/UIKit.h>
-#import "TUIBaseMessageController.h"
-#import "TUIChatConversationModel.h"
-#import "TUIInputController.h"
 
 NS_ASSUME_NONNULL_BEGIN
 

+ 31 - 31
KulexiuForStudent/KulexiuForStudent/Module/Chat/Controller/TXCustom/KSTXBaseChatViewController.m

@@ -6,37 +6,7 @@
 //
 
 #import "KSTXBaseChatViewController.h"
-#import <AVFoundation/AVFoundation.h>
-#import <AssetsLibrary/AssetsLibrary.h>
-#import <MobileCoreServices/MobileCoreServices.h>
-#import <Photos/Photos.h>
-#import <TIMCommon/NSString+TUIEmoji.h>
-#import <TIMCommon/TIMDefine.h>
-#import <TUICore/NSDictionary+TUISafe.h>
-#import <TUICore/TUICore.h>
-#import <TUICore/TUILogin.h>
-#import <TUICore/TUIThemeManager.h>
-#import <TUICore/TUITool.h>
-#import "ReactiveObjC/ReactiveObjC.h"
-#import "TUIAIDenoiseSignatureManager.h"
-#import "TUIBaseMessageController.h"
-#import "TUICameraViewController.h"
-#import "TUIChatConfig.h"
-#import "TUIChatDataProvider.h"
-#import "TUIChatMediaDataProvider.h"
-#import "TUIChatModifyMessageHelper.h"
-#import "TUICloudCustomDataTypeCenter.h"
-#import "TUIFileMessageCellData.h"
-#import "TUIImageMessageCellData.h"
-#import "TUIJoinGroupMessageCell.h"
-#import "TUIMessageController.h"
-#import "TUIMessageDataProvider.h"
-#import "TUIMessageMultiChooseView.h"
-#import "TUIMessageReadViewController.h"
-#import "TUIReplyMessageCellData.h"
-#import "TUITextMessageCellData.h"
-#import "TUIVideoMessageCellData.h"
-#import "TUIVoiceMessageCellData.h"
+
 
 #import "KSChatUserDetailViewController.h"
 #import "KSBaseWKWebViewController.h"
@@ -47,6 +17,8 @@
 #import <KSToolLibrary/RecordCheckManager.h>
 #import "KSPremissionAlert.h"
 
+#import "GroupNoticeDetailViewController.h"
+
 static UIView *gCustomTopView;
 
 @interface KSTXBaseChatViewController ()
@@ -115,10 +87,38 @@ static UIView *gCustomTopView;
             NSString *roomId = [param ks_stringValueForKey:@"roomUID"];
             [self enterLiveRoom:roomId];
         }
+        else if ([[param ks_stringValueForKey:@"businessID"] isEqualToString:@"TC_GROUP_NOTICE"]) {
+            NSString *noticeID = [param ks_stringValueForKey:@"msgId"];
+
+            if (![NSString isEmptyString:noticeID]) {
+                [self checkNoticeDetail:noticeID];
+            }
+            else {
+                NSLog(@"无法查看当前群公告");
+            }
+        }
     }
     
 }
 
+- (void)checkNoticeDetail:(NSString *)noticeId {
+    
+    [KSNetworkingManager imGroupNoticeDetailRequest:KS_GET noticeId:noticeId success:^(NSDictionary * _Nonnull dic) {
+        if ([dic ks_integerValueForKey:@"code"] == 200 && [dic ks_boolValueForKey:@"status"]) {
+            GroupNoticeDetailModel *model = [[GroupNoticeDetailModel alloc] initWithDictionary:[dic ks_dictionaryValueForKey:@"data"]];
+            GroupNoticeDetailViewController *ctrl = [[GroupNoticeDetailViewController alloc] init];
+            ctrl.sourceModel = model;
+            ctrl.canEdit = NO;
+            [self.navigationController pushViewController:ctrl animated:YES];
+        }
+        else {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        
+    }];
+}
+
 - (void)enterLiveRoom:(NSString *)roomId {
     [KSEnterLiveroomManager joinLiveWithRoomId:roomId inController:(CustomNavViewController *)self.navigationController callback:^{
         

+ 21 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Controller/GroupNoticeDetailViewController.h

@@ -0,0 +1,21 @@
+//
+//  GroupNoticeDetailViewController.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2024/9/9.
+//
+
+#import "KSBaseViewController.h"
+#import "GroupNoticeDetailModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupNoticeDetailViewController : KSBaseViewController
+
+@property (nonatomic, assign) BOOL canEdit;
+
+@property (nonatomic, strong) GroupNoticeDetailModel *sourceModel;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 50 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Controller/GroupNoticeDetailViewController.m

@@ -0,0 +1,50 @@
+//
+//  GroupNoticeDetailViewController.m
+//  GuanYueTeamManager
+//
+//  Created by 王智 on 2024/9/2.
+//
+
+#import "GroupNoticeDetailViewController.h"
+#import "GroupNoticeDetailBodyView.h"
+
+@interface GroupNoticeDetailViewController ()
+
+@property (nonatomic, strong) GroupNoticeDetailBodyView *bodyView;
+
+@end
+
+@implementation GroupNoticeDetailViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    [self configUI];
+}
+
+- (void)configUI {
+    [self allocTitle:@"公告详情"];
+    [self.scrollView removeFromSuperview];
+    self.bodyView = [GroupNoticeDetailBodyView shareInstance];
+    [self.view addSubview:self.bodyView];
+    [self.bodyView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.bottom.mas_equalTo(self.view);
+    }];
+    
+    [self.bodyView configWithSource:self.sourceModel enable:self.canEdit callback:^(id  _Nonnull sourceModel, UIButton * _Nonnull sender) {
+        
+    }];
+}
+
+
+/*
+#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

+ 2 - 1
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Controller/GroupNoticeViewController.m

@@ -58,6 +58,7 @@
             [weakSelf.tableView.mj_footer endRefreshingWithNoMoreData];
         }
     }];
+    self.tableView.mj_footer.ignoredScrollViewContentInsetBottom = IS_iPhoneX ? iPhoneXSafeBottomMargin : 0;
 }
 
 - (void)endRefresh {
@@ -188,7 +189,7 @@
 #pragma mark --- lazy
 - (UITableView *)tableView {
     if (!_tableView) {
-        _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 1, kScreenWidth, kScreenHeight - kNaviBarHeight - iPhoneXSafeBottomMargin) style:UITableViewStylePlain];
+        _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, KPortraitHeight - kNaviBarHeight) style:UITableViewStylePlain];
         _tableView.delegate = self;
         _tableView.dataSource = self;
         _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

+ 34 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Model/GroupNoticeDetailModel.h

@@ -0,0 +1,34 @@
+//
+//  GroupNoticeDetailModel.h
+//
+//  Created by Steven  on 2024/9/11
+//  Copyright (c) 2024 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+
+@interface GroupNoticeDetailModel : NSObject <NSCoding, NSCopying>
+
+@property (nonatomic, strong) NSString *internalBaseClassIdentifier;
+@property (nonatomic, strong) NSString *updateTime;
+@property (nonatomic, assign) BOOL delFlag;
+@property (nonatomic, strong) NSString *clientType;
+@property (nonatomic, assign) BOOL isSentToNewMember;
+@property (nonatomic, strong) NSString *imGroupId;
+@property (nonatomic, assign) double tenantId;
+@property (nonatomic, strong) NSString *title;
+@property (nonatomic, strong) NSString *avatar;
+@property (nonatomic, strong) NSString *createTime;
+@property (nonatomic, strong) NSString *username;
+@property (nonatomic, assign) double operatorId;
+@property (nonatomic, assign) BOOL isTop;
+@property (nonatomic, strong) NSString *messageSeqId;
+@property (nonatomic, strong) NSString *content;
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
+- (instancetype)initWithDictionary:(NSDictionary *)dict;
+- (NSDictionary *)dictionaryRepresentation;
+
+@end

+ 197 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/Model/GroupNoticeDetailModel.m

@@ -0,0 +1,197 @@
+//
+//  GroupNoticeDetailModel.m
+//
+//  Created by Steven  on 2024/9/11
+//  Copyright (c) 2024 __MyCompanyName__. All rights reserved.
+//
+
+#import "GroupNoticeDetailModel.h"
+
+
+NSString *const kGroupNoticeDetailModelId = @"id";
+NSString *const kGroupNoticeDetailModelUpdateTime = @"updateTime";
+NSString *const kGroupNoticeDetailModelDelFlag = @"delFlag";
+NSString *const kGroupNoticeDetailModelClientType = @"clientType";
+NSString *const kGroupNoticeDetailModelIsSentToNewMember = @"isSentToNewMember";
+NSString *const kGroupNoticeDetailModelImGroupId = @"imGroupId";
+NSString *const kGroupNoticeDetailModelTenantId = @"tenantId";
+NSString *const kGroupNoticeDetailModelTitle = @"title";
+NSString *const kGroupNoticeDetailModelAvatar = @"avatar";
+NSString *const kGroupNoticeDetailModelCreateTime = @"createTime";
+NSString *const kGroupNoticeDetailModelUsername = @"username";
+NSString *const kGroupNoticeDetailModelOperatorId = @"operatorId";
+NSString *const kGroupNoticeDetailModelIsTop = @"isTop";
+NSString *const kGroupNoticeDetailModelMessageSeqId = @"messageSeqId";
+NSString *const kGroupNoticeDetailModelContent = @"content";
+
+
+@interface GroupNoticeDetailModel ()
+
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict;
+
+@end
+
+@implementation GroupNoticeDetailModel
+
+@synthesize internalBaseClassIdentifier = _internalBaseClassIdentifier;
+@synthesize updateTime = _updateTime;
+@synthesize delFlag = _delFlag;
+@synthesize clientType = _clientType;
+@synthesize isSentToNewMember = _isSentToNewMember;
+@synthesize imGroupId = _imGroupId;
+@synthesize tenantId = _tenantId;
+@synthesize title = _title;
+@synthesize avatar = _avatar;
+@synthesize createTime = _createTime;
+@synthesize username = _username;
+@synthesize operatorId = _operatorId;
+@synthesize isTop = _isTop;
+@synthesize messageSeqId = _messageSeqId;
+@synthesize content = _content;
+
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict
+{
+    return [[self alloc] initWithDictionary:dict];
+}
+
+- (instancetype)initWithDictionary:(NSDictionary *)dict
+{
+    self = [super init];
+    
+    // This check serves to make sure that a non-NSDictionary object
+    // passed into the model class doesn't break the parsing.
+    if(self && [dict isKindOfClass:[NSDictionary class]]) {
+            self.internalBaseClassIdentifier = [self objectOrNilForKey:kGroupNoticeDetailModelId fromDictionary:dict];
+            self.updateTime = [self objectOrNilForKey:kGroupNoticeDetailModelUpdateTime fromDictionary:dict];
+            self.delFlag = [[self objectOrNilForKey:kGroupNoticeDetailModelDelFlag fromDictionary:dict] boolValue];
+            self.clientType = [self objectOrNilForKey:kGroupNoticeDetailModelClientType fromDictionary:dict];
+            self.isSentToNewMember = [[self objectOrNilForKey:kGroupNoticeDetailModelIsSentToNewMember fromDictionary:dict] boolValue];
+            self.imGroupId = [self objectOrNilForKey:kGroupNoticeDetailModelImGroupId fromDictionary:dict];
+            self.tenantId = [[self objectOrNilForKey:kGroupNoticeDetailModelTenantId fromDictionary:dict] doubleValue];
+            self.title = [self objectOrNilForKey:kGroupNoticeDetailModelTitle fromDictionary:dict];
+            self.avatar = [self objectOrNilForKey:kGroupNoticeDetailModelAvatar fromDictionary:dict];
+            self.createTime = [self objectOrNilForKey:kGroupNoticeDetailModelCreateTime fromDictionary:dict];
+            self.username = [self objectOrNilForKey:kGroupNoticeDetailModelUsername fromDictionary:dict];
+            self.operatorId = [[self objectOrNilForKey:kGroupNoticeDetailModelOperatorId fromDictionary:dict] doubleValue];
+            self.isTop = [[self objectOrNilForKey:kGroupNoticeDetailModelIsTop fromDictionary:dict] boolValue];
+            self.messageSeqId = [self objectOrNilForKey:kGroupNoticeDetailModelMessageSeqId fromDictionary:dict];
+            self.content = [self objectOrNilForKey:kGroupNoticeDetailModelContent fromDictionary:dict];
+
+    }
+    
+    return self;
+    
+}
+
+- (NSDictionary *)dictionaryRepresentation
+{
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    [mutableDict setValue:self.internalBaseClassIdentifier forKey:kGroupNoticeDetailModelId];
+    [mutableDict setValue:self.updateTime forKey:kGroupNoticeDetailModelUpdateTime];
+    [mutableDict setValue:[NSNumber numberWithBool:self.delFlag] forKey:kGroupNoticeDetailModelDelFlag];
+    [mutableDict setValue:self.clientType forKey:kGroupNoticeDetailModelClientType];
+    [mutableDict setValue:[NSNumber numberWithBool:self.isSentToNewMember] forKey:kGroupNoticeDetailModelIsSentToNewMember];
+    [mutableDict setValue:self.imGroupId forKey:kGroupNoticeDetailModelImGroupId];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.tenantId] forKey:kGroupNoticeDetailModelTenantId];
+    [mutableDict setValue:self.title forKey:kGroupNoticeDetailModelTitle];
+    [mutableDict setValue:self.avatar forKey:kGroupNoticeDetailModelAvatar];
+    [mutableDict setValue:self.createTime forKey:kGroupNoticeDetailModelCreateTime];
+    [mutableDict setValue:self.username forKey:kGroupNoticeDetailModelUsername];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.operatorId] forKey:kGroupNoticeDetailModelOperatorId];
+    [mutableDict setValue:[NSNumber numberWithBool:self.isTop] forKey:kGroupNoticeDetailModelIsTop];
+    [mutableDict setValue:self.messageSeqId forKey:kGroupNoticeDetailModelMessageSeqId];
+    [mutableDict setValue:self.content forKey:kGroupNoticeDetailModelContent];
+
+    return [NSDictionary dictionaryWithDictionary:mutableDict];
+}
+
+- (NSString *)description
+{
+    return [NSString stringWithFormat:@"%@", [self dictionaryRepresentation]];
+}
+
+#pragma mark - Helper Method
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict
+{
+    id object = [dict objectForKey:aKey];
+    if ([object isKindOfClass:[NSNumber class]]) {
+        NSNumber *number = object;
+        object = [number stringValue];
+    }
+    return [object isEqual:[NSNull null]] ? nil : object;
+}
+
+
+#pragma mark - NSCoding Methods
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super init];
+
+    self.internalBaseClassIdentifier = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelId];
+    self.updateTime = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelUpdateTime];
+    self.delFlag = [aDecoder decodeBoolForKey:kGroupNoticeDetailModelDelFlag];
+    self.clientType = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelClientType];
+    self.isSentToNewMember = [aDecoder decodeBoolForKey:kGroupNoticeDetailModelIsSentToNewMember];
+    self.imGroupId = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelImGroupId];
+    self.tenantId = [aDecoder decodeDoubleForKey:kGroupNoticeDetailModelTenantId];
+    self.title = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelTitle];
+    self.avatar = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelAvatar];
+    self.createTime = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelCreateTime];
+    self.username = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelUsername];
+    self.operatorId = [aDecoder decodeDoubleForKey:kGroupNoticeDetailModelOperatorId];
+    self.isTop = [aDecoder decodeBoolForKey:kGroupNoticeDetailModelIsTop];
+    self.messageSeqId = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelMessageSeqId];
+    self.content = [aDecoder decodeObjectForKey:kGroupNoticeDetailModelContent];
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+
+    [aCoder encodeObject:_internalBaseClassIdentifier forKey:kGroupNoticeDetailModelId];
+    [aCoder encodeObject:_updateTime forKey:kGroupNoticeDetailModelUpdateTime];
+    [aCoder encodeBool:_delFlag forKey:kGroupNoticeDetailModelDelFlag];
+    [aCoder encodeObject:_clientType forKey:kGroupNoticeDetailModelClientType];
+    [aCoder encodeBool:_isSentToNewMember forKey:kGroupNoticeDetailModelIsSentToNewMember];
+    [aCoder encodeObject:_imGroupId forKey:kGroupNoticeDetailModelImGroupId];
+    [aCoder encodeDouble:_tenantId forKey:kGroupNoticeDetailModelTenantId];
+    [aCoder encodeObject:_title forKey:kGroupNoticeDetailModelTitle];
+    [aCoder encodeObject:_avatar forKey:kGroupNoticeDetailModelAvatar];
+    [aCoder encodeObject:_createTime forKey:kGroupNoticeDetailModelCreateTime];
+    [aCoder encodeObject:_username forKey:kGroupNoticeDetailModelUsername];
+    [aCoder encodeDouble:_operatorId forKey:kGroupNoticeDetailModelOperatorId];
+    [aCoder encodeBool:_isTop forKey:kGroupNoticeDetailModelIsTop];
+    [aCoder encodeObject:_messageSeqId forKey:kGroupNoticeDetailModelMessageSeqId];
+    [aCoder encodeObject:_content forKey:kGroupNoticeDetailModelContent];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    GroupNoticeDetailModel *copy = [[GroupNoticeDetailModel alloc] init];
+    
+    if (copy) {
+
+        copy.internalBaseClassIdentifier = [self.internalBaseClassIdentifier copyWithZone:zone];
+        copy.updateTime = [self.updateTime copyWithZone:zone];
+        copy.delFlag = self.delFlag;
+        copy.clientType = [self.clientType copyWithZone:zone];
+        copy.isSentToNewMember = self.isSentToNewMember;
+        copy.imGroupId = [self.imGroupId copyWithZone:zone];
+        copy.tenantId = self.tenantId;
+        copy.title = [self.title copyWithZone:zone];
+        copy.avatar = [self.avatar copyWithZone:zone];
+        copy.createTime = [self.createTime copyWithZone:zone];
+        copy.username = [self.username copyWithZone:zone];
+        copy.operatorId = self.operatorId;
+        copy.isTop = self.isTop;
+        copy.messageSeqId = [self.messageSeqId copyWithZone:zone];
+        copy.content = [self.content copyWithZone:zone];
+    }
+    
+    return copy;
+}
+
+
+@end

+ 11 - 7
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeCell.m

@@ -49,16 +49,20 @@
     if ([source isKindOfClass:[GroupNoticeModel class]]) {
         GroupNoticeModel *model = source;
         self.userName.text = [NSString returnNoNullStringWithString:model.username];
-        [self.userLogo sd_setImageWithURL:[NSURL URLWithString:[model.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:TEACHER_AVATAR]];
-
         self.noticeTitle.text = [NSString returnNoNullStringWithString:model.title];
-        NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
-        [paragraphStyle setLineSpacing:4];//调整行间距
-        NSMutableAttributedString *attrs = [[NSMutableAttributedString alloc] initWithString:[NSString returnNoNullStringWithString:model.content] attributes:@{NSParagraphStyleAttributeName:paragraphStyle,NSFontAttributeName:[UIFont systemFontOfSize:16.0f],NSForegroundColorAttributeName:HexRGB(0x777777)}];
-        self.noticeContent.attributedText = attrs;
-        
         self.focusLabel.hidden = model.top ? NO : YES;
         self.modifyTime.text = [NSString returnNoNullStringWithString:model.updateTime];
+        [self.userLogo sd_setImageWithURL:[NSURL URLWithString:[model.avatar getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:TEACHER_AVATAR]];
+        self.noticeContent.text = [NSString returnNoNullStringWithString:model.content];
+        if (![NSString isEmptyString:model.content]) {
+            NSMutableAttributedString *attrs = [[NSMutableAttributedString alloc] initWithString:model.content attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14 weight:UIFontWeightRegular], NSForegroundColorAttributeName:HexRGB(0x777777)}];
+            self.noticeContent.attributedText = attrs;
+        }
+        else {
+            self.noticeContent.text = @"";
+        }
+        
+        
     }
 }
 

+ 74 - 72
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeCell.xib

@@ -11,18 +11,18 @@
     <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="183" id="KGk-i7-Jjw" customClass="GroupNoticeCell">
-            <rect key="frame" x="0.0" y="0.0" width="359" height="183"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="253" id="KGk-i7-Jjw" customClass="GroupNoticeCell">
+            <rect key="frame" x="0.0" y="0.0" width="359" height="253"/>
             <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="359" height="183"/>
+                <rect key="frame" x="0.0" y="0.0" width="359" height="253"/>
                 <autoresizingMask key="autoresizingMask"/>
                 <subviews>
-                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qWq-La-TpT">
-                        <rect key="frame" x="13" y="12" width="333" height="171"/>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Jdh-Fo-Wpn">
+                        <rect key="frame" x="13" y="12" width="333" height="241"/>
                         <subviews>
                             <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="teacher_avatar" translatesAutoresizingMaskIntoConstraints="NO" id="Gkn-L8-UCb">
-                                <rect key="frame" x="16" y="12" width="48" height="48"/>
+                                <rect key="frame" x="12" y="12" width="48" height="48"/>
                                 <constraints>
                                     <constraint firstAttribute="height" constant="48" id="8bz-sK-gjT"/>
                                     <constraint firstAttribute="width" constant="48" id="VaV-68-izM"/>
@@ -33,99 +33,102 @@
                                     </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="vad-UL-yLE">
-                                <rect key="frame" x="74" y="41" width="0.0" height="20"/>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="陈老师" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2c3-yX-YxS">
+                                <rect key="frame" x="70" y="14" width="207.5" height="22"/>
                                 <constraints>
-                                    <constraint firstAttribute="height" constant="20" id="G1H-uK-NYV"/>
+                                    <constraint firstAttribute="height" constant="22" id="dMw-tJ-YFP"/>
                                 </constraints>
-                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
-                                <color key="textColor" red="0.54117647058823526" green="0.54117647058823526" blue="0.54117647058823526" alpha="1" colorSpace="calibratedRGB"/>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
+                                <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2023-07-24 15:34:26" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vad-UL-yLE">
+                                <rect key="frame" x="70" y="40" width="132.5" height="18"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="18" id="G1H-uK-NYV"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                <color key="textColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Gv9-px-E4j">
+                                <rect key="frame" x="289.5" y="5.5" width="40" height="40"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="40" id="0ay-Cx-fo8"/>
+                                    <constraint firstAttribute="height" constant="40" id="v9h-3o-0Hd"/>
+                                </constraints>
+                                <state key="normal" image="notice_action"/>
+                                <connections>
+                                    <action selector="editAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="LKl-Wu-uAP"/>
+                                </connections>
+                            </button>
                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="置顶" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Fse-Bd-Rui">
-                                <rect key="frame" x="80" y="41" width="40" height="20"/>
+                                <rect key="frame" x="208.5" y="39.5" width="40" height="19"/>
                                 <constraints>
-                                    <constraint firstAttribute="height" constant="20" id="eAd-Zt-CN7"/>
+                                    <constraint firstAttribute="height" constant="19" id="eAd-Zt-CN7"/>
                                     <constraint firstAttribute="width" constant="40" id="gtu-Jt-duR"/>
                                 </constraints>
-                                <fontDescription key="fontDescription" type="system" pointSize="13"/>
-                                <color key="textColor" red="0.99607843137254903" green="0.14117647058823529" blue="0.31764705882352939" alpha="1" colorSpace="calibratedRGB"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                <color key="textColor" red="1" green="0.31764705882352939" blue="0.31764705882352939" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                                 <userDefinedRuntimeAttributes>
                                     <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
-                                        <real key="value" value="10"/>
+                                        <real key="value" value="9.5"/>
                                     </userDefinedRuntimeAttribute>
                                     <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
-                                        <color key="value" red="0.99607843137254903" green="0.14117647058823529" blue="0.31764705882352939" alpha="1" colorSpace="calibratedRGB"/>
+                                        <color key="value" red="1" green="0.31764705882352939" blue="0.31764705882352939" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                     </userDefinedRuntimeAttribute>
                                     <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
                                         <real key="value" value="1"/>
                                     </userDefinedRuntimeAttribute>
                                 </userDefinedRuntimeAttributes>
                             </label>
-                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Gv9-px-E4j">
-                                <rect key="frame" x="285" y="6.5" width="40" height="40"/>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="47L-aP-812">
+                                <rect key="frame" x="12" y="72" width="309" height="1"/>
+                                <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <constraints>
-                                    <constraint firstAttribute="width" constant="40" id="0ay-Cx-fo8"/>
-                                    <constraint firstAttribute="height" constant="40" id="v9h-3o-0Hd"/>
+                                    <constraint firstAttribute="height" constant="1" id="34R-6j-HXV"/>
                                 </constraints>
-                                <state key="normal" image="notice_action"/>
-                                <connections>
-                                    <action selector="editAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="LKl-Wu-uAP"/>
-                                </connections>
-                            </button>
-                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="038-4g-5JZ">
-                                <rect key="frame" x="16" y="76" width="301" height="1"/>
-                                <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="calibratedRGB"/>
+                            </view>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" text="今日作业" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gxd-9e-9Xw">
+                                <rect key="frame" x="12" y="85" width="309" height="21"/>
                                 <constraints>
-                                    <constraint firstAttribute="height" constant="1" id="3Wh-Ue-Sj3"/>
+                                    <constraint firstAttribute="height" constant="21" id="JGE-BZ-edM"/>
                                 </constraints>
-                            </view>
-                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" text="" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="gxd-9e-9Xw">
-                                <rect key="frame" x="16" y="93" width="301" height="50"/>
-                                <fontDescription key="fontDescription" type="system" weight="medium" pointSize="18"/>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="15"/>
                                 <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" text="" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FWq-QF-ONl">
-                                <rect key="frame" x="16" y="156" width="301" height="0.0"/>
-                                <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                                <rect key="frame" x="12" y="111" width="298" height="114"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                 <color key="textColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
-                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2c3-yX-YxS">
-                                <rect key="frame" x="74" y="14" width="199" height="25"/>
-                                <constraints>
-                                    <constraint firstAttribute="height" constant="25" id="dMw-tJ-YFP"/>
-                                </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="custom" customColorSpace="sRGB"/>
-                                <nil key="highlightedColor"/>
-                            </label>
                         </subviews>
                         <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                         <constraints>
-                            <constraint firstAttribute="trailing" secondItem="038-4g-5JZ" secondAttribute="trailing" constant="16" id="ART-lR-s3C"/>
-                            <constraint firstItem="Gkn-L8-UCb" firstAttribute="leading" secondItem="qWq-La-TpT" secondAttribute="leading" constant="16" id="IYn-ew-2ea"/>
-                            <constraint firstItem="Gv9-px-E4j" firstAttribute="leading" secondItem="2c3-yX-YxS" secondAttribute="trailing" constant="12" id="Izw-tV-fyQ"/>
-                            <constraint firstItem="2c3-yX-YxS" firstAttribute="leading" secondItem="Gkn-L8-UCb" secondAttribute="trailing" constant="10" id="J3a-nQ-zqB"/>
-                            <constraint firstItem="vad-UL-yLE" firstAttribute="leading" secondItem="2c3-yX-YxS" secondAttribute="leading" id="JDu-Se-aI6"/>
-                            <constraint firstAttribute="trailing" secondItem="Gv9-px-E4j" secondAttribute="trailing" constant="8" id="N4A-xt-LAp"/>
-                            <constraint firstItem="vad-UL-yLE" firstAttribute="top" secondItem="2c3-yX-YxS" secondAttribute="bottom" constant="2" id="N7G-Ce-QIc"/>
-                            <constraint firstItem="gxd-9e-9Xw" firstAttribute="leading" secondItem="qWq-La-TpT" secondAttribute="leading" constant="16" id="NDs-Xr-hHO"/>
-                            <constraint firstItem="038-4g-5JZ" firstAttribute="top" secondItem="Gkn-L8-UCb" secondAttribute="bottom" constant="16" id="PH8-z7-60N"/>
-                            <constraint firstAttribute="trailing" secondItem="gxd-9e-9Xw" secondAttribute="trailing" constant="16" id="S2d-pS-kaY"/>
-                            <constraint firstItem="FWq-QF-ONl" firstAttribute="top" secondItem="gxd-9e-9Xw" secondAttribute="bottom" constant="13" id="Vf4-jv-WpV"/>
-                            <constraint firstItem="gxd-9e-9Xw" firstAttribute="top" secondItem="038-4g-5JZ" secondAttribute="bottom" constant="16" id="WdV-Qv-AqI"/>
-                            <constraint firstAttribute="bottom" secondItem="FWq-QF-ONl" secondAttribute="bottom" constant="15" id="YVP-D4-aqo"/>
-                            <constraint firstItem="2c3-yX-YxS" firstAttribute="top" secondItem="Gkn-L8-UCb" secondAttribute="top" constant="2" id="ay7-jB-Ghd"/>
-                            <constraint firstItem="Fse-Bd-Rui" firstAttribute="leading" secondItem="vad-UL-yLE" secondAttribute="trailing" constant="6" id="b7x-ei-t05"/>
-                            <constraint firstItem="038-4g-5JZ" firstAttribute="leading" secondItem="qWq-La-TpT" secondAttribute="leading" constant="16" id="bC8-ah-beD"/>
-                            <constraint firstItem="FWq-QF-ONl" firstAttribute="trailing" secondItem="gxd-9e-9Xw" secondAttribute="trailing" id="bcZ-KL-EUb"/>
-                            <constraint firstItem="Gv9-px-E4j" firstAttribute="centerY" secondItem="2c3-yX-YxS" secondAttribute="centerY" id="g8r-p1-BL2"/>
-                            <constraint firstItem="Fse-Bd-Rui" firstAttribute="centerY" secondItem="vad-UL-yLE" secondAttribute="centerY" id="lF9-xB-hfp"/>
-                            <constraint firstItem="FWq-QF-ONl" firstAttribute="leading" secondItem="gxd-9e-9Xw" secondAttribute="leading" id="mTh-u9-qZf"/>
-                            <constraint firstItem="Gkn-L8-UCb" firstAttribute="top" secondItem="qWq-La-TpT" secondAttribute="top" constant="12" id="vJe-1d-d4U"/>
+                            <constraint firstItem="Gv9-px-E4j" firstAttribute="leading" secondItem="2c3-yX-YxS" secondAttribute="trailing" constant="12" id="0d1-2V-f0c"/>
+                            <constraint firstItem="vad-UL-yLE" firstAttribute="top" secondItem="2c3-yX-YxS" secondAttribute="bottom" constant="4" id="1f7-zg-Ca8"/>
+                            <constraint firstItem="Gkn-L8-UCb" firstAttribute="leading" secondItem="Jdh-Fo-Wpn" secondAttribute="leading" constant="12" id="3ZI-Dn-gaU"/>
+                            <constraint firstItem="vad-UL-yLE" firstAttribute="leading" secondItem="2c3-yX-YxS" secondAttribute="leading" id="42C-LT-gAz"/>
+                            <constraint firstAttribute="trailing" secondItem="FWq-QF-ONl" secondAttribute="trailing" constant="23" id="5Nd-hL-tIw"/>
+                            <constraint firstItem="Fse-Bd-Rui" firstAttribute="centerY" secondItem="vad-UL-yLE" secondAttribute="centerY" id="CZX-IK-w9g"/>
+                            <constraint firstAttribute="trailing" secondItem="47L-aP-812" secondAttribute="trailing" constant="12" id="HyT-AX-INN"/>
+                            <constraint firstAttribute="trailing" secondItem="gxd-9e-9Xw" secondAttribute="trailing" constant="12" id="KKO-wI-16S"/>
+                            <constraint firstItem="Fse-Bd-Rui" firstAttribute="leading" secondItem="vad-UL-yLE" secondAttribute="trailing" constant="6" id="Oss-CV-BSR"/>
+                            <constraint firstItem="2c3-yX-YxS" firstAttribute="top" secondItem="Jdh-Fo-Wpn" secondAttribute="top" constant="14" id="P5L-2G-u6a"/>
+                            <constraint firstItem="Gv9-px-E4j" firstAttribute="top" secondItem="Jdh-Fo-Wpn" secondAttribute="top" constant="5.5" id="QXL-oK-dMf"/>
+                            <constraint firstItem="gxd-9e-9Xw" firstAttribute="top" secondItem="47L-aP-812" secondAttribute="bottom" constant="12" id="V1V-pl-ind"/>
+                            <constraint firstItem="Gkn-L8-UCb" firstAttribute="top" secondItem="Jdh-Fo-Wpn" secondAttribute="top" constant="12" id="aQo-eC-AFc"/>
+                            <constraint firstItem="FWq-QF-ONl" firstAttribute="top" secondItem="gxd-9e-9Xw" secondAttribute="bottom" constant="5" id="cRa-gO-pGN"/>
+                            <constraint firstItem="gxd-9e-9Xw" firstAttribute="leading" secondItem="Jdh-Fo-Wpn" secondAttribute="leading" constant="12" id="d0r-ff-dgf"/>
+                            <constraint firstItem="FWq-QF-ONl" firstAttribute="leading" secondItem="Jdh-Fo-Wpn" secondAttribute="leading" constant="12" id="dK1-ff-rKg"/>
+                            <constraint firstItem="47L-aP-812" firstAttribute="leading" secondItem="Jdh-Fo-Wpn" secondAttribute="leading" constant="12" id="eRE-Hj-7oe"/>
+                            <constraint firstAttribute="bottom" secondItem="FWq-QF-ONl" secondAttribute="bottom" constant="16" id="gKg-yF-TE1"/>
+                            <constraint firstItem="47L-aP-812" firstAttribute="top" secondItem="Gkn-L8-UCb" secondAttribute="bottom" constant="12" id="oji-Pv-sfT"/>
+                            <constraint firstAttribute="trailing" secondItem="Gv9-px-E4j" secondAttribute="trailing" constant="3.5" id="upH-rK-Lrc"/>
+                            <constraint firstItem="2c3-yX-YxS" firstAttribute="leading" secondItem="Gkn-L8-UCb" secondAttribute="trailing" constant="10" id="xyi-iI-XSB"/>
                         </constraints>
                         <userDefinedRuntimeAttributes>
                             <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
@@ -134,12 +137,11 @@
                         </userDefinedRuntimeAttributes>
                     </view>
                 </subviews>
-                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                 <constraints>
-                    <constraint firstItem="qWq-La-TpT" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="12" id="3nM-FI-Z4T"/>
-                    <constraint firstAttribute="trailing" secondItem="qWq-La-TpT" secondAttribute="trailing" constant="13" id="4UE-wr-frc"/>
-                    <constraint firstItem="qWq-La-TpT" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="13" id="5XS-Wg-4HZ"/>
-                    <constraint firstAttribute="bottom" secondItem="qWq-La-TpT" secondAttribute="bottom" id="ghz-gf-5wb"/>
+                    <constraint firstItem="Jdh-Fo-Wpn" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="13" id="5Ur-ba-gvN"/>
+                    <constraint firstAttribute="bottom" secondItem="Jdh-Fo-Wpn" secondAttribute="bottom" id="7Cq-Lz-jgf"/>
+                    <constraint firstAttribute="trailing" secondItem="Jdh-Fo-Wpn" secondAttribute="trailing" constant="13" id="NCQ-Ic-naP"/>
+                    <constraint firstItem="Jdh-Fo-Wpn" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="12" id="cig-xD-hB8"/>
                 </constraints>
             </tableViewCellContentView>
             <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
@@ -153,7 +155,7 @@
                 <outlet property="userLogo" destination="Gkn-L8-UCb" id="Gj8-xH-KxL"/>
                 <outlet property="userName" destination="2c3-yX-YxS" id="lOP-EJ-tfh"/>
             </connections>
-            <point key="canvasLocation" x="125.36231884057972" y="215.29017857142856"/>
+            <point key="canvasLocation" x="125.36231884057972" y="191.85267857142856"/>
         </tableViewCell>
     </objects>
     <resources>

+ 24 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeDetailBodyView.h

@@ -0,0 +1,24 @@
+//
+//  GroupNoticeDetailBodyView.h
+//  GuanYueTeamManager
+//
+//  Created by 王智 on 2024/9/2.
+//
+
+#import <UIKit/UIKit.h>
+#import "GroupNoticeCell.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface GroupNoticeDetailBodyView : UIView
+
++ (instancetype)shareInstance;
+
+- (void)refreshSource:(id)source;
+
+- (void)configWithSource:(id)source enable:(BOOL)canEdit callback:(EditCallback)callback;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 85 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeDetailBodyView.m

@@ -0,0 +1,85 @@
+//
+//  GroupNoticeDetailBodyView.m
+//  GuanYueTeamManager
+//
+//  Created by 王智 on 2024/9/2.
+//
+
+#import "GroupNoticeDetailBodyView.h"
+#import "GroupNoticeDetailModel.h"
+
+@interface GroupNoticeDetailBodyView ()
+
+@property (weak, nonatomic) IBOutlet UIImageView *userLogo;
+@property (weak, nonatomic) IBOutlet UILabel *userName;
+@property (weak, nonatomic) IBOutlet UILabel *modifyTime;
+@property (weak, nonatomic) IBOutlet UIButton *modifyButton;
+@property (weak, nonatomic) IBOutlet UILabel *focusLabel;
+@property (weak, nonatomic) IBOutlet UILabel *noticeTitle;
+@property (weak, nonatomic) IBOutlet UILabel *noticeContent;
+
+@property (nonatomic, copy) EditCallback callback;
+
+@property (nonatomic, strong) id sourceModel;
+
+@end
+
+@implementation GroupNoticeDetailBodyView
+
++ (instancetype)shareInstance {
+    GroupNoticeDetailBodyView *view = [[[NSBundle mainBundle] loadNibNamed:@"GroupNoticeDetailBodyView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)refreshSource:(id)source {
+    self.sourceModel = source;
+    // 赋值
+    if ([source isKindOfClass:[GroupNoticeDetailModel class]]) {
+        GroupNoticeDetailModel *model = source;
+        self.userName.text = [NSString returnNoNullStringWithString:model.username];
+        [self.userLogo sd_setImageWithURL:[NSURL URLWithString:model.avatar] placeholderImage:[UIImage imageNamed:TEACHER_AVATAR]];
+        self.noticeTitle.text = [NSString returnNoNullStringWithString:model.title];
+        self.focusLabel.hidden = model.isTop ? NO : YES;
+        self.modifyTime.text = [NSString returnNoNullStringWithString:model.updateTime];
+        
+        self.noticeContent.text = [NSString returnNoNullStringWithString:model.content];
+        if (![NSString isEmptyString:model.content]) {
+            NSMutableAttributedString *attrs = [[NSMutableAttributedString alloc] initWithString:model.content attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14 weight:UIFontWeightRegular], NSForegroundColorAttributeName:HexRGB(0x777777)}];
+            self.noticeContent.attributedText = attrs;
+        }
+        else {
+            self.noticeContent.text = @"";
+        }
+    }
+}
+
+- (void)configWithSource:(id)source enable:(BOOL)canEdit callback:(EditCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    [self refreshSource:source];
+    self.modifyButton.userInteractionEnabled = NO;
+    self.modifyButton.hidden = YES;
+    if (canEdit) {
+        self.modifyButton.userInteractionEnabled = YES;
+        self.modifyButton.hidden = NO;
+    }
+    
+    
+}
+
+- (IBAction)editAction:(UIButton *)sender {
+    if (self.callback) {
+        self.callback(self.sourceModel,sender);
+    }
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 166 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/GroupNoticeDetailBodyView.xib

@@ -0,0 +1,166 @@
+<?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="22685"/>
+        <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"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="GroupNoticeDetailBodyView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="U45-g3-TEP">
+                    <rect key="frame" x="13" y="12" width="367" height="127"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="teacher_avatar" translatesAutoresizingMaskIntoConstraints="NO" id="62c-65-fwx">
+                            <rect key="frame" x="12" y="12" width="48" height="48"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="48" id="1IK-Yj-cYx"/>
+                                <constraint firstAttribute="width" constant="48" id="nKy-8p-3Ee"/>
+                            </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="70t-nX-m7j">
+                            <rect key="frame" x="69.999999999999986" y="14" width="243.66666666666663" height="22"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="22" id="Oto-pk-Eo6"/>
+                            </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="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="I5b-RG-0dE">
+                            <rect key="frame" x="70" y="40" width="0.0" height="18"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="18" id="6DK-if-GKt"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                            <color key="textColor" red="0.46666666670000001" green="0.46666666670000001" blue="0.46666666670000001" alpha="1" colorSpace="calibratedRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="r31-Oy-hyD">
+                            <rect key="frame" x="323.66666666666669" y="5.6666666666666679" width="40" height="40"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="40" id="6gF-M8-hb4"/>
+                                <constraint firstAttribute="width" constant="40" id="pkD-bc-Q44"/>
+                            </constraints>
+                            <state key="normal" image="notice_action"/>
+                            <connections>
+                                <action selector="editAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="Ztu-Gg-myz"/>
+                            </connections>
+                        </button>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="置顶" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="g5H-XJ-LiA">
+                            <rect key="frame" x="76" y="39.666666666666664" width="40" height="19"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="19" id="eRu-fc-vHH"/>
+                                <constraint firstAttribute="width" constant="40" id="hi9-Wa-xYC"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                            <color key="textColor" red="1" green="0.31764705882352939" blue="0.31764705882352939" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="9.5"/>
+                                </userDefinedRuntimeAttribute>
+                                <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
+                                    <color key="value" red="1" green="0.31764705882352939" blue="0.31764705882352939" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                </userDefinedRuntimeAttribute>
+                                <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
+                                    <real key="value" value="1"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                        </label>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="NH8-Zj-ieK">
+                            <rect key="frame" x="12" y="72" width="343" height="1"/>
+                            <color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="1" id="P9W-60-LWJ"/>
+                            </constraints>
+                        </view>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="749" text="" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="6Xh-iI-Zl8">
+                            <rect key="frame" x="12" y="85" width="343" height="21"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="21" id="qXR-a3-h5j"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="15"/>
+                            <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" text="" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="RUn-oI-u4C">
+                            <rect key="frame" x="12" y="111" width="332" height="0.0"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <color key="textColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <constraints>
+                        <constraint firstItem="62c-65-fwx" firstAttribute="top" secondItem="U45-g3-TEP" secondAttribute="top" constant="12" id="95n-hq-uux"/>
+                        <constraint firstAttribute="trailing" secondItem="6Xh-iI-Zl8" secondAttribute="trailing" constant="12" id="CDd-eV-WJh"/>
+                        <constraint firstItem="70t-nX-m7j" firstAttribute="top" secondItem="U45-g3-TEP" secondAttribute="top" constant="14" id="DzK-hi-wVo"/>
+                        <constraint firstItem="I5b-RG-0dE" firstAttribute="top" secondItem="70t-nX-m7j" secondAttribute="bottom" constant="4" id="Fc4-dB-leq"/>
+                        <constraint firstItem="NH8-Zj-ieK" firstAttribute="leading" secondItem="U45-g3-TEP" secondAttribute="leading" constant="12" id="H1p-dx-VTB"/>
+                        <constraint firstAttribute="trailing" secondItem="NH8-Zj-ieK" secondAttribute="trailing" constant="12" id="I1k-Ij-4yJ"/>
+                        <constraint firstItem="RUn-oI-u4C" firstAttribute="leading" secondItem="U45-g3-TEP" secondAttribute="leading" constant="12" id="QQo-RW-ufF"/>
+                        <constraint firstItem="RUn-oI-u4C" firstAttribute="top" secondItem="6Xh-iI-Zl8" secondAttribute="bottom" constant="5" id="QlV-bU-NDL"/>
+                        <constraint firstItem="g5H-XJ-LiA" firstAttribute="centerY" secondItem="I5b-RG-0dE" secondAttribute="centerY" id="WAK-Jv-OBg"/>
+                        <constraint firstItem="6Xh-iI-Zl8" firstAttribute="top" secondItem="NH8-Zj-ieK" secondAttribute="bottom" constant="12" id="Wfw-w5-jaS"/>
+                        <constraint firstAttribute="trailing" secondItem="RUn-oI-u4C" secondAttribute="trailing" constant="23" id="ZZY-7F-NSz"/>
+                        <constraint firstAttribute="bottom" secondItem="RUn-oI-u4C" secondAttribute="bottom" constant="16" id="ewD-oI-JY8"/>
+                        <constraint firstItem="g5H-XJ-LiA" firstAttribute="leading" secondItem="I5b-RG-0dE" secondAttribute="trailing" constant="6" id="jIe-U3-gnt"/>
+                        <constraint firstItem="70t-nX-m7j" firstAttribute="leading" secondItem="62c-65-fwx" secondAttribute="trailing" constant="10" id="lhs-RK-8UB"/>
+                        <constraint firstItem="r31-Oy-hyD" firstAttribute="leading" secondItem="70t-nX-m7j" secondAttribute="trailing" constant="10" id="lke-VY-HYi"/>
+                        <constraint firstItem="NH8-Zj-ieK" firstAttribute="top" secondItem="62c-65-fwx" secondAttribute="bottom" constant="12" id="oEx-Li-k9L"/>
+                        <constraint firstItem="62c-65-fwx" firstAttribute="leading" secondItem="U45-g3-TEP" secondAttribute="leading" constant="12" id="rCc-3u-NH1"/>
+                        <constraint firstItem="6Xh-iI-Zl8" firstAttribute="leading" secondItem="U45-g3-TEP" secondAttribute="leading" constant="12" id="ro4-MV-ZGq"/>
+                        <constraint firstAttribute="trailing" secondItem="r31-Oy-hyD" secondAttribute="trailing" constant="3.5" id="rpy-xC-GXd"/>
+                        <constraint firstItem="I5b-RG-0dE" firstAttribute="leading" secondItem="70t-nX-m7j" secondAttribute="leading" id="wQq-Pu-SxK"/>
+                        <constraint firstItem="r31-Oy-hyD" firstAttribute="top" secondItem="U45-g3-TEP" secondAttribute="top" constant="5.5" id="zYN-jN-bQk"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="10"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
+            <color key="backgroundColor" red="0.97254901960784312" green="0.97254901960784312" blue="0.97254901960784312" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstItem="U45-g3-TEP" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="13" id="64m-Px-O5U"/>
+                <constraint firstItem="U45-g3-TEP" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="12" id="dwy-C5-bXj"/>
+                <constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="U45-g3-TEP" secondAttribute="trailing" constant="13" id="w2Q-S6-cMM"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="focusLabel" destination="g5H-XJ-LiA" id="mrU-gE-oBC"/>
+                <outlet property="modifyButton" destination="r31-Oy-hyD" id="oBq-87-yDO"/>
+                <outlet property="modifyTime" destination="I5b-RG-0dE" id="72O-5k-3IT"/>
+                <outlet property="noticeContent" destination="RUn-oI-u4C" id="Imh-Ye-imh"/>
+                <outlet property="noticeTitle" destination="6Xh-iI-Zl8" id="dOp-LE-gpT"/>
+                <outlet property="userLogo" destination="62c-65-fwx" id="pNk-fp-hlD"/>
+                <outlet property="userName" destination="70t-nX-m7j" id="e4Z-yA-lxV"/>
+            </connections>
+            <point key="canvasLocation" x="65" y="20"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="notice_action" width="24" height="25"/>
+        <image name="teacher_avatar" width="150" height="150"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 30 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/KSPopView.h

@@ -0,0 +1,30 @@
+//
+//  KSPopView.h
+//  GuanYueTeamManager
+//
+//  Created by 王智 on 2024/9/10.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSInteger, KSPOP_TAG) {
+    KSPOP_TAG_EDIT,    // 编辑
+    KSPOP_TAG_TOP,     // 设为置顶
+    KSPOP_TAG_CANCELTOP, // 取消置顶
+    KSPOP_TAG_DELETE,  // 删除公告
+};
+typedef void(^PopActionCallback)(KSPOP_TAG tag);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSPopView : UIView
+
+@property (nonatomic, assign) BOOL isNoticeTop;
+
++ (instancetype)shareInstance;
+
+- (void)showPopToView:(CGPoint)locationPoint callBack:(PopActionCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 105 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/KSPopView.m

@@ -0,0 +1,105 @@
+//
+//  KSPopView.m
+//  GuanYueTeamManager
+//
+//  Created by 王智 on 2024/9/10.
+//
+
+#import "KSPopView.h"
+#define POP_VIEW_HEIGHT (133)
+#define POP_VIEW_MARGIN (16)
+
+@interface KSPopView ()<UIGestureRecognizerDelegate>
+
+@property (weak, nonatomic) IBOutlet UIView *containerView;
+
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topSpace;
+
+@property (weak, nonatomic) IBOutlet UILabel *topTitleLabel;
+
+@property (nonatomic, copy) PopActionCallback callback;
+
+@end
+
+@implementation KSPopView
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    UITapGestureRecognizer *gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapAction:)];
+    gesture.delegate = self;
+    [self addGestureRecognizer:gesture];
+}
+
+- (void)tapAction:(UITapGestureRecognizer *)gesture {
+    [self hideView];
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
+    if ([touch.view isDescendantOfView:self.containerView]) {
+        return NO;
+    }
+    return YES;
+}
+
++ (instancetype)shareInstance {
+    KSPopView *view = [[[NSBundle mainBundle] loadNibNamed:@"KSPopView" owner:nil options:nil] firstObject];
+    view.frame = CGRectMake(0, 0, KPortraitWidth, KPortraitHeight);
+    return view;
+}
+
+- (void)showPopToView:(CGPoint)locationPoint callBack:(PopActionCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    [[NSObject getKeyWindow] addSubview:self];
+    CGFloat maxY = locationPoint.y;
+    CGFloat topSpace = maxY;
+    if (maxY + POP_VIEW_HEIGHT + POP_VIEW_MARGIN > KPortraitHeight) {
+        topSpace = maxY - POP_VIEW_HEIGHT;
+    }
+    self.topSpace.constant = topSpace;
+}
+
+- (void)hideView {
+    [self removeFromSuperview];
+}
+
+- (IBAction)editAction:(id)sender {
+    if (self.callback) {
+        self.callback(KSPOP_TAG_EDIT);
+    }
+    [self hideView];
+}
+
+- (IBAction)topEdit:(id)sender {
+    if (self.callback) {
+        KSPOP_TAG tag = self.isNoticeTop ? KSPOP_TAG_CANCELTOP : KSPOP_TAG_TOP;
+        self.callback(tag);
+    }
+    [self hideView];
+}
+
+- (IBAction)deleteAction:(id)sender {
+    if (self.callback) {
+        self.callback(KSPOP_TAG_DELETE);
+    }
+    [self hideView];
+}
+
+- (void)setIsNoticeTop:(BOOL)isNoticeTop {
+    _isNoticeTop = isNoticeTop;
+    NSString *text = isNoticeTop ? @"取消置顶" : @"设为置顶";
+    self.topTitleLabel.text = text;
+}
+
+
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 147 - 0
KulexiuForStudent/KulexiuForStudent/Module/Chat/GroupNotice/View/KSPopView.xib

@@ -0,0 +1,147 @@
+<?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="22685"/>
+        <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="KSPopView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="852"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6Df-ZE-Y9L">
+                    <rect key="frame" x="248" y="12" width="120" height="133"/>
+                    <subviews>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="IDo-c1-nTp">
+                            <rect key="frame" x="10" y="44" width="100" height="0.6666666666666643"/>
+                            <color key="backgroundColor" red="0.94901960784313721" green="0.94901960784313721" blue="0.94901960784313721" alpha="1" colorSpace="calibratedRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="0.5" id="Upm-wN-YY5"/>
+                            </constraints>
+                        </view>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hQI-LV-wxX">
+                            <rect key="frame" x="12" y="88.666666666666671" width="96" height="0.3333333333333286"/>
+                            <color key="backgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.94901960780000005" alpha="1" colorSpace="calibratedRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="0.5" id="dqg-PY-dXB"/>
+                            </constraints>
+                        </view>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="编辑公告" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7ix-16-rz7">
+                            <rect key="frame" x="31" y="12" width="58" height="20"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="设为置顶" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QP3-T1-SDn">
+                            <rect key="frame" x="31" y="56.666666666666671" width="58" height="20"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <color key="textColor" red="0.20000000000000001" green="0.20000000000000001" blue="0.20000000000000001" alpha="1" colorSpace="calibratedRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="删除公告" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="klu-yq-5fT">
+                            <rect key="frame" x="31" y="101" width="58" height="20"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <color key="textColor" red="0.96862745098039216" green="0.24705882352941178" blue="0.23137254901960785" alpha="1" colorSpace="calibratedRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="stG-tB-UBc">
+                            <rect key="frame" x="0.0" y="0.0" width="120" height="44"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="editAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="37I-Eu-bQK"/>
+                            </connections>
+                        </button>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mPU-Ib-uuF">
+                            <rect key="frame" x="0.0" y="44.666666666666657" width="120" height="44"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="topEdit:" destination="iN0-l3-epB" eventType="touchUpInside" id="Xu2-Ic-2yE"/>
+                            </connections>
+                        </button>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="PGh-2k-dsu">
+                            <rect key="frame" x="0.0" y="89" width="120" height="44"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="deleteAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="4HP-aM-4jY"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                    <constraints>
+                        <constraint firstItem="stG-tB-UBc" firstAttribute="leading" secondItem="6Df-ZE-Y9L" secondAttribute="leading" id="1Su-Q2-LRV"/>
+                        <constraint firstItem="7ix-16-rz7" firstAttribute="centerX" secondItem="6Df-ZE-Y9L" secondAttribute="centerX" id="3DY-aN-ydn"/>
+                        <constraint firstAttribute="bottom" secondItem="klu-yq-5fT" secondAttribute="bottom" constant="12" id="5gI-7a-HqV"/>
+                        <constraint firstItem="hQI-LV-wxX" firstAttribute="top" secondItem="IDo-c1-nTp" secondAttribute="bottom" constant="44" id="BDY-k5-b1o"/>
+                        <constraint firstAttribute="trailing" secondItem="stG-tB-UBc" secondAttribute="trailing" id="DtU-sX-SmK"/>
+                        <constraint firstItem="IDo-c1-nTp" firstAttribute="top" secondItem="7ix-16-rz7" secondAttribute="bottom" constant="12" id="E6F-Zl-PRK"/>
+                        <constraint firstItem="hQI-LV-wxX" firstAttribute="top" secondItem="QP3-T1-SDn" secondAttribute="bottom" constant="12" id="HyF-9q-2ja"/>
+                        <constraint firstItem="hQI-LV-wxX" firstAttribute="leading" secondItem="6Df-ZE-Y9L" secondAttribute="leading" constant="12" id="Md0-I2-asL"/>
+                        <constraint firstItem="PGh-2k-dsu" firstAttribute="top" secondItem="hQI-LV-wxX" secondAttribute="bottom" id="Nm5-cp-nCe"/>
+                        <constraint firstItem="QP3-T1-SDn" firstAttribute="centerX" secondItem="6Df-ZE-Y9L" secondAttribute="centerX" id="OfU-vw-Ny9"/>
+                        <constraint firstAttribute="trailing" secondItem="PGh-2k-dsu" secondAttribute="trailing" id="PQK-MR-FnD"/>
+                        <constraint firstItem="IDo-c1-nTp" firstAttribute="top" secondItem="6Df-ZE-Y9L" secondAttribute="top" constant="44" id="Tqc-mB-AdP"/>
+                        <constraint firstItem="mPU-Ib-uuF" firstAttribute="leading" secondItem="6Df-ZE-Y9L" secondAttribute="leading" id="V8L-32-uZA"/>
+                        <constraint firstItem="klu-yq-5fT" firstAttribute="centerX" secondItem="6Df-ZE-Y9L" secondAttribute="centerX" id="WPJ-qi-pCj"/>
+                        <constraint firstItem="stG-tB-UBc" firstAttribute="top" secondItem="6Df-ZE-Y9L" secondAttribute="top" id="Y8g-Kf-Aii"/>
+                        <constraint firstAttribute="height" constant="133" id="c3y-QS-uab"/>
+                        <constraint firstItem="7ix-16-rz7" firstAttribute="top" secondItem="6Df-ZE-Y9L" secondAttribute="top" constant="12" id="d7d-Ik-NbW"/>
+                        <constraint firstItem="klu-yq-5fT" firstAttribute="top" secondItem="hQI-LV-wxX" secondAttribute="bottom" constant="12" id="dNk-mN-i8i"/>
+                        <constraint firstAttribute="trailing" secondItem="hQI-LV-wxX" secondAttribute="trailing" constant="12" id="hAM-Xc-tKU"/>
+                        <constraint firstItem="mPU-Ib-uuF" firstAttribute="top" secondItem="IDo-c1-nTp" secondAttribute="bottom" id="l7C-2S-enQ"/>
+                        <constraint firstAttribute="trailing" secondItem="IDo-c1-nTp" secondAttribute="trailing" constant="10" id="m1W-Vw-0hf"/>
+                        <constraint firstItem="IDo-c1-nTp" firstAttribute="leading" secondItem="6Df-ZE-Y9L" secondAttribute="leading" constant="10" id="mX4-62-bPs"/>
+                        <constraint firstItem="hQI-LV-wxX" firstAttribute="top" secondItem="mPU-Ib-uuF" secondAttribute="bottom" id="nSR-NF-Iz4"/>
+                        <constraint firstItem="PGh-2k-dsu" firstAttribute="leading" secondItem="6Df-ZE-Y9L" secondAttribute="leading" id="o8f-n3-nE9"/>
+                        <constraint firstAttribute="width" constant="120" id="qIr-uu-bRn"/>
+                        <constraint firstItem="IDo-c1-nTp" firstAttribute="top" secondItem="stG-tB-UBc" secondAttribute="bottom" id="v4k-k6-ECn"/>
+                        <constraint firstAttribute="trailing" secondItem="mPU-Ib-uuF" secondAttribute="trailing" id="vib-w7-zhb"/>
+                        <constraint firstAttribute="bottom" secondItem="PGh-2k-dsu" secondAttribute="bottom" id="wMz-nk-GIO"/>
+                        <constraint firstItem="QP3-T1-SDn" firstAttribute="top" secondItem="IDo-c1-nTp" secondAttribute="bottom" constant="12" id="xiS-LV-bLP"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="12"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="size" keyPath="shadowOffset">
+                            <size key="value" width="0.0" height="2"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="color" keyPath="shadowUIColor">
+                            <color key="value" red="0.0" green="0.0" blue="0.0" alpha="0.10000000000000001" colorSpace="custom" customColorSpace="calibratedRGB"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="shadowOpacity">
+                            <real key="value" value="1"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="number" keyPath="shadowRadius">
+                            <real key="value" value="10"/>
+                        </userDefinedRuntimeAttribute>
+                        <userDefinedRuntimeAttribute type="boolean" keyPath="maskToBounces" value="NO"/>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="6Df-ZE-Y9L" secondAttribute="trailing" constant="25" id="Uck-oi-EdS"/>
+                <constraint firstItem="6Df-ZE-Y9L" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="12" id="sZE-qw-O3j"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="containerView" destination="6Df-ZE-Y9L" id="w9t-eM-Hg2"/>
+                <outlet property="topSpace" destination="sZE-qw-O3j" id="QZo-VV-AvM"/>
+                <outlet property="topTitleLabel" destination="QP3-T1-SDn" id="6yJ-kU-yoy"/>
+            </connections>
+            <point key="canvasLocation" x="43.511450381679388" y="19.718309859154932"/>
+        </view>
+    </objects>
+    <resources>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>

+ 24 - 0
KulexiuForStudent/Pods/Pods.xcodeproj/project.pbxproj

@@ -1566,6 +1566,12 @@
 		BBF45E9D6F4C464EC35063C56F8334C9 /* RACEmptySequence.h in Headers */ = {isa = PBXBuildFile; fileRef = 693D9830E109F32453D148154726B834 /* RACEmptySequence.h */; settings = {ATTRIBUTES = (Project, ); }; };
 		BC0CC39F5FAA5CBA2CE9365F95C17B22 /* QCloudUploadPartResult.h in Headers */ = {isa = PBXBuildFile; fileRef = CEAF9A1B75CE7D07F57DE2A57ECEEB07 /* QCloudUploadPartResult.h */; settings = {ATTRIBUTES = (Project, ); }; };
 		BC21AAB3DF90CB6719EDE4A9579DB7B4 /* JXCategoryTitleCell.h in Headers */ = {isa = PBXBuildFile; fileRef = F41571EBA2838393779A36584724EE88 /* JXCategoryTitleCell.h */; settings = {ATTRIBUTES = (Project, ); }; };
+		BC28210C2C918873008BD2CC /* TXGroupNoticeMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = BC28210A2C918873008BD2CC /* TXGroupNoticeMessage.h */; };
+		BC28210D2C918873008BD2CC /* TXGroupNoticeMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = BC28210B2C918873008BD2CC /* TXGroupNoticeMessage.m */; };
+		BC2821122C918884008BD2CC /* TXGroupNoticeMessageContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = BC28210E2C918884008BD2CC /* TXGroupNoticeMessageContentView.h */; };
+		BC2821132C918884008BD2CC /* TXGroupNoticeMessageContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC28210F2C918884008BD2CC /* TXGroupNoticeMessageContentView.m */; };
+		BC2821142C918884008BD2CC /* TXGroupNoticeMessageCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BC2821102C918884008BD2CC /* TXGroupNoticeMessageCell.h */; };
+		BC2821152C918884008BD2CC /* TXGroupNoticeMessageCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC2821112C918884008BD2CC /* TXGroupNoticeMessageCell.m */; };
 		BCB13876DAE2BF3E8AC7A539C1A69B6D /* LOTShapeFill.m in Sources */ = {isa = PBXBuildFile; fileRef = A224FD8F30B8138E6EF4BCFBEE8A2CCF /* LOTShapeFill.m */; settings = {COMPILER_FLAGS = "-w -Xanalyzer -analyzer-disable-all-checks"; }; };
 		BCCE8FB859A66819765E8033629F3622 /* KS3ListBucketsResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 7943C36CCE953F3ED2EE70BB9B339F29 /* KS3ListBucketsResponse.h */; settings = {ATTRIBUTES = (Project, ); }; };
 		BCD8968974D5DCA846F00EAE3DCA40FA /* WhiteSDK+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AF6D0B0A2F8FE1A7F2C2A4F4F2497D96 /* WhiteSDK+Private.h */; settings = {ATTRIBUTES = (Project, ); }; };
@@ -4600,6 +4606,12 @@
 		BC0931DBC4A297AA87386D230A2BBF6A /* TUIAIDenoiseSignatureManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TUIAIDenoiseSignatureManager.m; path = TUIChat/CommonModel/TUIAIDenoiseSignatureManager.m; sourceTree = "<group>"; };
 		BC14DFA8577A598DC1801A5191A38C89 /* TUIGroupRequestViewController.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = TUIGroupRequestViewController.m; path = TUIGroup/UI_Classic/UI/TUIGroupRequestViewController.m; sourceTree = "<group>"; };
 		BC1CE621A39F287A0CD1EE4E5AB9B5EA /* QCloudHTTPSessionManager.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = QCloudHTTPSessionManager.m; path = QCloudCore/Classes/Base/QCLOUDRestNet/SessionSupport/QCloudHTTPSessionManager.m; sourceTree = "<group>"; };
+		BC28210A2C918873008BD2CC /* TXGroupNoticeMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXGroupNoticeMessage.h; sourceTree = "<group>"; };
+		BC28210B2C918873008BD2CC /* TXGroupNoticeMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXGroupNoticeMessage.m; sourceTree = "<group>"; };
+		BC28210E2C918884008BD2CC /* TXGroupNoticeMessageContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXGroupNoticeMessageContentView.h; sourceTree = "<group>"; };
+		BC28210F2C918884008BD2CC /* TXGroupNoticeMessageContentView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXGroupNoticeMessageContentView.m; sourceTree = "<group>"; };
+		BC2821102C918884008BD2CC /* TXGroupNoticeMessageCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TXGroupNoticeMessageCell.h; sourceTree = "<group>"; };
+		BC2821112C918884008BD2CC /* TXGroupNoticeMessageCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TXGroupNoticeMessageCell.m; sourceTree = "<group>"; };
 		BC2B09C1C83AFD62D0D84FA376FDDDE0 /* UIStepper+RACSignalSupport.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; name = "UIStepper+RACSignalSupport.m"; path = "ReactiveObjC/UIStepper+RACSignalSupport.m"; sourceTree = "<group>"; };
 		BC2BDDE86DF05B1FB453E55B99ED4254 /* TUIChatExtensionObserver.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = TUIChatExtensionObserver.h; path = TUIChat/UI_Classic/Service/TUIChatExtensionObserver.h; sourceTree = "<group>"; };
 		BC752FC3B946A977AABB78E1D4EEB45D /* KS3InitiateMultipartUploadRequest.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = KS3InitiateMultipartUploadRequest.h; path = KS3YunSDK/KS3YunSDK/KSYS3/KSYModel/Object/KS3InitiateMultipartUploadRequest.h; sourceTree = "<group>"; };
@@ -6051,6 +6063,8 @@
 				B95D6988319406DE798998F8D98A8BEE /* TXChatMusicMessage.m */,
 				6DA11063A4C8E35D120F61183681C995 /* TXLiveShareMessage.h */,
 				8B668212B9B8FD2BACA2742FEE5EFDCA /* TXLiveShareMessage.m */,
+				BC28210A2C918873008BD2CC /* TXGroupNoticeMessage.h */,
+				BC28210B2C918873008BD2CC /* TXGroupNoticeMessage.m */,
 			);
 			name = Custom;
 			sourceTree = "<group>";
@@ -7590,6 +7604,10 @@
 				A91CA925A2548B7A8AB21509FD7CB510 /* TXShareLiveCellContentView.m */,
 				2CB861720E0E972E8F398C9D9C7184B9 /* TXShareMusicCellContentView.h */,
 				742577E700F63C81056EFE9CF4B62265 /* TXShareMusicCellContentView.m */,
+				BC2821102C918884008BD2CC /* TXGroupNoticeMessageCell.h */,
+				BC2821112C918884008BD2CC /* TXGroupNoticeMessageCell.m */,
+				BC28210E2C918884008BD2CC /* TXGroupNoticeMessageContentView.h */,
+				BC28210F2C918884008BD2CC /* TXGroupNoticeMessageContentView.m */,
 			);
 			name = Custom;
 			sourceTree = "<group>";
@@ -10376,6 +10394,7 @@
 				D2B260F42D0ACD5FAF19F8DEF855ED8A /* dec_if.h in Headers */,
 				FC4D51B616F0FB414CCE0674E95475F4 /* EMVoiceConverter.h in Headers */,
 				DCAF03E3961F0BE30F4102930BADB870 /* if_rom.h in Headers */,
+				BC2821142C918884008BD2CC /* TXGroupNoticeMessageCell.h in Headers */,
 				500AD5B6F273EDA870284FC4F7531166 /* interf_dec.h in Headers */,
 				6AD59CA4A5BA3BD5379C11427AE03137 /* interf_enc.h in Headers */,
 				9B8BAB789A382E26A49331BCC9E60115 /* TUIAIDenoiseSignatureManager.h in Headers */,
@@ -10384,6 +10403,7 @@
 				DC1DA0BF16615C4D7B33241EC0979D0E /* TUIBaseChatViewController+ProtectedAPI.h in Headers */,
 				31C523FD3F99F6E0AC8B48F393FCFCC5 /* TUIBaseMessageController.h in Headers */,
 				C623801449B25890C32CCCD7B69041C1 /* TUIBaseMessageController+ProtectedAPI.h in Headers */,
+				BC28210C2C918873008BD2CC /* TXGroupNoticeMessage.h in Headers */,
 				A649CA50F72A57910B2F01CB7139D4FF /* TUIBaseMessageControllerDelegate.h in Headers */,
 				61F2CBB41D621D9E29117784D8EA7A4F /* TUIC2CChatViewController.h in Headers */,
 				8732C394FDF6DAF2A364F5D11083F0FF /* TUICameraMacro.h in Headers */,
@@ -10428,6 +10448,7 @@
 				ED1DBA2083E80289DD9AAF385AAF1857 /* TUIFileMessageCellData.h in Headers */,
 				EC5F9F3B7C8ED4B6AA4ACD6BA7A8C092 /* TUIFileReplyQuoteView.h in Headers */,
 				68DE49BAB97694300077D3C4CA43E1A5 /* TUIFileReplyQuoteViewData.h in Headers */,
+				BC2821122C918884008BD2CC /* TXGroupNoticeMessageContentView.h in Headers */,
 				028FB54E76DABD424E171FFD2C4C33DC /* TUIFileViewController.h in Headers */,
 				CCB445A4E2BAB424E76CDAC7358D0033 /* TUIGroupChatViewController.h in Headers */,
 				E8A1668CA2F08B473F61E8ABBC0A7809 /* TUIGroupCreatedCell.h in Headers */,
@@ -12186,6 +12207,7 @@
 				29C2350C1AEB76FD9B06B6090C28572C /* TUIChat-dummy.m in Sources */,
 				6B84CED43D22342B9849BD21657CDA6D /* TUIChatBaseDataProvider.m in Sources */,
 				0F0AE184B509C3AB76F73E1F79D384CA /* TUIChatCallingDataProvider.m in Sources */,
+				BC28210D2C918873008BD2CC /* TXGroupNoticeMessage.m in Sources */,
 				33E512AEFCCA088680D5AA58645E821A /* TUIChatConfig.m in Sources */,
 				0C2B75884498AA82CD7C85013C431FEE /* TUIChatContextEmojiDetailController.m in Sources */,
 				CC76AC9AAD8FFB9D947782A4CD291A68 /* TUIChatConversationModel.m in Sources */,
@@ -12260,6 +12282,7 @@
 				982E9BACFAE986921B3E815737AA1A75 /* TUIMessageReadViewController.m in Sources */,
 				0BF584310768BFEB9A0F417DD0313E99 /* TUIMessageSearchDataProvider.m in Sources */,
 				54500A56F74AA1A06251B3C56E698E75 /* TUIMoreView.m in Sources */,
+				BC2821132C918884008BD2CC /* TXGroupNoticeMessageContentView.m in Sources */,
 				5EBB1CC1ED50BBC6E4D00908A1F5C6BA /* TUIMotionManager.m in Sources */,
 				AA00AD3DEFB146B674F7AEBF7AAA865D /* TUIMovieManager.m in Sources */,
 				52039BF84A1293AC9129C064FD1A35E4 /* TUIOrderCell.m in Sources */,
@@ -12286,6 +12309,7 @@
 				76B55154BDA120459653433D286C44FF /* TUIVideoReplyQuoteViewData.m in Sources */,
 				7F9F6887030FC959B55AADC8A634EAE7 /* TUIVoiceMessageCell.m in Sources */,
 				1790412C7C61856E0777F2AF8F6096EA /* TUIVoiceMessageCellData.m in Sources */,
+				BC2821152C918884008BD2CC /* TXGroupNoticeMessageCell.m in Sources */,
 				8409BA117ADF2C7C34689B3A953D432D /* TUIVoiceReplyQuoteView.m in Sources */,
 				A1517A34D4FF1D07A50F95ABA9A97220 /* TUIVoiceReplyQuoteViewData.m in Sources */,
 				F3D8586CB161560EB8490511CDBBE166 /* TXChatMusicMessage.m in Sources */,