浏览代码

首页曲目和统计的web

Steven 3 月之前
父节点
当前提交
960bfab033
共有 27 个文件被更改,包括 907 次插入3 次删除
  1. 50 0
      KulexiuForTeacher/KulexiuForTeacher.xcodeproj/project.pbxproj
  2. 1 1
      KulexiuForTeacher/KulexiuForTeacher.xcodeproj/xcshareddata/xcschemes/KulexiuForTeacher.xcscheme
  3. 6 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/Contents.json
  4. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_hot_music.imageset/Contents.json
  5. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_hot_music.imageset/home_hot_music@2x.png
  6. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_hot_music.imageset/home_hot_music@3x.png
  7. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_newest_music.imageset/Contents.json
  8. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_newest_music.imageset/home_newest_music@2x.png
  9. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_newest_music.imageset/home_newest_music@3x.png
  10. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_recommend_music.imageset/Contents.json
  11. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_recommend_music.imageset/home_recommend_music@2x.png
  12. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_recommend_music.imageset/home_recommend_music@3x.png
  13. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_album_icon.imageset/Contents.json
  14. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_album_icon.imageset/home_album_icon@2x.png
  15. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_album_icon.imageset/home_album_icon@3x.png
  16. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_music_icon.imageset/Contents.json
  17. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_music_icon.imageset/home_music_icon@2x.png
  18. 二进制
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_music_icon.imageset/home_music_icon@3x.png
  19. 24 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/HomeStatistics/HomeStatisticsView.h
  20. 268 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/HomeStatistics/HomeStatisticsView.m
  21. 2 2
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeHotAlbumCell.xib
  22. 31 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeMusicPageView/HomeMusicPageView.h
  23. 44 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeMusicPageView/HomeMusicPageView.m
  24. 168 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeMusicPageView/HomeMusicPageView.xib
  25. 27 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeNewAlbum/HomeNewAlbumView.h
  26. 48 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeNewAlbum/HomeNewAlbumView.m
  27. 128 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeNewAlbum/HomeNewAlbumView.xib

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

@@ -882,6 +882,11 @@
 		BCA353E92859A6FB00377661 /* MusicRoomHomeworkCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA353E72859A6FA00377661 /* MusicRoomHomeworkCell.m */; };
 		BCA353EA2859A6FB00377661 /* MusicRoomHomeworkCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA353E82859A6FA00377661 /* MusicRoomHomeworkCell.xib */; };
 		BCA353ED2859B4EC00377661 /* MusicRoomHomeworkStudentController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA353EC2859B4EC00377661 /* MusicRoomHomeworkStudentController.m */; };
+		BCA409F52D1D269700A387F1 /* HomeStatisticsView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA409F42D1D269700A387F1 /* HomeStatisticsView.m */; };
+		BCA409F92D1D2A5D00A387F1 /* HomeNewAlbumView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA409F82D1D2A5D00A387F1 /* HomeNewAlbumView.m */; };
+		BCA409FB2D1D2A6600A387F1 /* HomeNewAlbumView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA409FA2D1D2A6600A387F1 /* HomeNewAlbumView.xib */; };
+		BCA409FF2D1D2EC800A387F1 /* HomeMusicPageView.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA409FE2D1D2EC800A387F1 /* HomeMusicPageView.m */; };
+		BCA40A012D1D2ECF00A387F1 /* HomeMusicPageView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA40A002D1D2ECF00A387F1 /* HomeMusicPageView.xib */; };
 		BCA723FB2806A96000DA0D0D /* HomeworkDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA723FA2806A96000DA0D0D /* HomeworkDetailViewController.m */; };
 		BCA723FF2806AEA000DA0D0D /* AccompanyHomeworkCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BCA723FD2806AEA000DA0D0D /* AccompanyHomeworkCell.m */; };
 		BCA724002806AEA000DA0D0D /* AccompanyHomeworkCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BCA723FE2806AEA000DA0D0D /* AccompanyHomeworkCell.xib */; };
@@ -2677,6 +2682,14 @@
 		BCA353E82859A6FA00377661 /* MusicRoomHomeworkCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MusicRoomHomeworkCell.xib; sourceTree = "<group>"; };
 		BCA353EB2859B4EC00377661 /* MusicRoomHomeworkStudentController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MusicRoomHomeworkStudentController.h; sourceTree = "<group>"; };
 		BCA353EC2859B4EC00377661 /* MusicRoomHomeworkStudentController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MusicRoomHomeworkStudentController.m; sourceTree = "<group>"; };
+		BCA409F32D1D269700A387F1 /* HomeStatisticsView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeStatisticsView.h; sourceTree = "<group>"; };
+		BCA409F42D1D269700A387F1 /* HomeStatisticsView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeStatisticsView.m; sourceTree = "<group>"; };
+		BCA409F72D1D2A5D00A387F1 /* HomeNewAlbumView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeNewAlbumView.h; sourceTree = "<group>"; };
+		BCA409F82D1D2A5D00A387F1 /* HomeNewAlbumView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeNewAlbumView.m; sourceTree = "<group>"; };
+		BCA409FA2D1D2A6600A387F1 /* HomeNewAlbumView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeNewAlbumView.xib; sourceTree = "<group>"; };
+		BCA409FD2D1D2EC800A387F1 /* HomeMusicPageView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeMusicPageView.h; sourceTree = "<group>"; };
+		BCA409FE2D1D2EC800A387F1 /* HomeMusicPageView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeMusicPageView.m; sourceTree = "<group>"; };
+		BCA40A002D1D2ECF00A387F1 /* HomeMusicPageView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeMusicPageView.xib; sourceTree = "<group>"; };
 		BCA723F92806A96000DA0D0D /* HomeworkDetailViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HomeworkDetailViewController.h; sourceTree = "<group>"; };
 		BCA723FA2806A96000DA0D0D /* HomeworkDetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HomeworkDetailViewController.m; sourceTree = "<group>"; };
 		BCA723FC2806AEA000DA0D0D /* AccompanyHomeworkCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AccompanyHomeworkCell.h; sourceTree = "<group>"; };
@@ -3827,6 +3840,7 @@
 		277935FA27E32BBF0010E277 /* Home */ = {
 			isa = PBXGroup;
 			children = (
+				BCA409F22D1D267400A387F1 /* HomeStatistics */,
 				BCB9FA17286D52CF005D766B /* ScanView */,
 				BCFE540A28178BD100AD6786 /* Income */,
 				BC1365BE280D44D500EB03E2 /* NotiferMessage */,
@@ -3872,6 +3886,8 @@
 		277935FD27E32BBF0010E277 /* View */ = {
 			isa = PBXGroup;
 			children = (
+				BCA409FC2D1D2EBA00A387F1 /* HomeMusicPageView */,
+				BCA409F62D1D2A4F00A387F1 /* HomeNewAlbum */,
 				BC7E77092900DD8E00EB37AF /* HomeDragButton */,
 				BC1263A628FF98C300509E90 /* HomeRecommendMusic */,
 				BC1263A028FF98BB00509E90 /* HomeNewMusic */,
@@ -6858,6 +6874,35 @@
 			path = BanList;
 			sourceTree = "<group>";
 		};
+		BCA409F22D1D267400A387F1 /* HomeStatistics */ = {
+			isa = PBXGroup;
+			children = (
+				BCA409F32D1D269700A387F1 /* HomeStatisticsView.h */,
+				BCA409F42D1D269700A387F1 /* HomeStatisticsView.m */,
+			);
+			path = HomeStatistics;
+			sourceTree = "<group>";
+		};
+		BCA409F62D1D2A4F00A387F1 /* HomeNewAlbum */ = {
+			isa = PBXGroup;
+			children = (
+				BCA409F72D1D2A5D00A387F1 /* HomeNewAlbumView.h */,
+				BCA409F82D1D2A5D00A387F1 /* HomeNewAlbumView.m */,
+				BCA409FA2D1D2A6600A387F1 /* HomeNewAlbumView.xib */,
+			);
+			path = HomeNewAlbum;
+			sourceTree = "<group>";
+		};
+		BCA409FC2D1D2EBA00A387F1 /* HomeMusicPageView */ = {
+			isa = PBXGroup;
+			children = (
+				BCA409FD2D1D2EC800A387F1 /* HomeMusicPageView.h */,
+				BCA409FE2D1D2EC800A387F1 /* HomeMusicPageView.m */,
+				BCA40A002D1D2ECF00A387F1 /* HomeMusicPageView.xib */,
+			);
+			path = HomeMusicPageView;
+			sourceTree = "<group>";
+		};
 		BCA9A5B22D18F67500C7CC9D /* GroupCourse */ = {
 			isa = PBXGroup;
 			children = (
@@ -8070,6 +8115,7 @@
 				BCECE2242B3D648700C0D555 /* CourseFileDisplayView.xib in Resources */,
 				2755C06927EC71C8007D9070 /* GroupSettingBodyView.xib in Resources */,
 				BC2820E52C9182D9008BD2CC /* GroupNoticeDetailBodyView.xib in Resources */,
+				BCA40A012D1D2ECF00A387F1 /* HomeMusicPageView.xib in Resources */,
 				BC71D1EF2887FDD40010F14B /* img_2.png in Resources */,
 				BC8B641D28F3E8D800A08D16 /* KSAwardAlertView.xib in Resources */,
 				BCD1606B2CED870700A78B43 /* MyCourseGroupNavView.xib in Resources */,
@@ -8327,6 +8373,7 @@
 				BC245710286C437D00D1F7C0 /* synthgms.sf2 in Resources */,
 				BC71D1EE2887FDD40010F14B /* img_13.png in Resources */,
 				BCF1BA5B27F5CF3C00FA36C4 /* LiveSeatApplyCell.xib in Resources */,
+				BCA409FB2D1D2A6600A387F1 /* HomeNewAlbumView.xib in Resources */,
 				2780C92427E4903500A95A4F /* PasswordBodyView.xib in Resources */,
 				BC81F0EF29233228004106AF /* CoursewareSearchView.xib in Resources */,
 				27F902FF27E864AE00C08A19 /* KSNetworkAlert.xib in Resources */,
@@ -8763,6 +8810,7 @@
 				BC106BA42A8F45AA000759A9 /* TXLiveChatListCell.m in Sources */,
 				BC86A2C92CD36B6400A15A53 /* MineWorkSortView.m in Sources */,
 				BC31BF9C2B219C5700F7D538 /* WidgetBottomButtonView.m in Sources */,
+				BCA409F92D1D2A5D00A387F1 /* HomeNewAlbumView.m in Sources */,
 				BC1263A428FF98BB00509E90 /* HomeNewMusicView.m in Sources */,
 				BCDE359E289BC03E00A9A560 /* HomeAlbumModel.m in Sources */,
 				BC3BF6362B9ED1F600831494 /* StateView.m in Sources */,
@@ -8952,6 +9000,7 @@
 				BCA193BE282B9866004A585D /* MinePageGroupModel.m in Sources */,
 				BCB633F827F6A18200ACFDCF /* KSTipsView.m in Sources */,
 				BCF748602D156F4900CD7EB4 /* EvaluateReceiveBodyView.m in Sources */,
+				BCA409FF2D1D2EC800A387F1 /* HomeMusicPageView.m in Sources */,
 				BC0A22B72847523E0065C1AB /* MemberBottomView.m in Sources */,
 				BC02BCDA28B3243F005CB483 /* LiveSeatActionView.m in Sources */,
 				BCECE21A2B3D5F0800C0D555 /* KSSortButtonView.m in Sources */,
@@ -9041,6 +9090,7 @@
 				275B172927EB26920081FDEF /* ChatAddressHeaderView.m in Sources */,
 				BC7CFFA22817D72200CAEB21 /* IncomeListModel.m in Sources */,
 				BCB6F45E2CF57F13000D8805 /* TeacherStyleFlowLayout.m in Sources */,
+				BCA409F52D1D269700A387F1 /* HomeStatisticsView.m in Sources */,
 				2755C06C27EC7F0E007D9070 /* KSChatComplainController.m in Sources */,
 				BC12638528FEB5B900509E90 /* UserDetailBodyView.m in Sources */,
 				BC14A61728A0B0440086395C /* MineBottomView.m in Sources */,

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

@@ -53,7 +53,7 @@
       </Testables>
    </TestAction>
    <LaunchAction
-      buildConfiguration = "Debug"
+      buildConfiguration = "TEST"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       launchStyle = "0"

+ 6 - 0
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/Contents.json

@@ -0,0 +1,6 @@
+{
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_hot_music.imageset/Contents.json

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

二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_hot_music.imageset/home_hot_music@2x.png


二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_hot_music.imageset/home_hot_music@3x.png


+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_newest_music.imageset/Contents.json

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

二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_newest_music.imageset/home_newest_music@2x.png


二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_newest_music.imageset/home_newest_music@3x.png


+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_recommend_music.imageset/Contents.json

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

二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_recommend_music.imageset/home_recommend_music@2x.png


二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/HomeMusic/home_recommend_music.imageset/home_recommend_music@3x.png


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

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

二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_album_icon.imageset/home_album_icon@2x.png


二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_album_icon.imageset/home_album_icon@3x.png


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

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

二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_music_icon.imageset/home_music_icon@2x.png


二进制
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/Home/home_music_icon.imageset/home_music_icon@3x.png


+ 24 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/HomeStatistics/HomeStatisticsView.h

@@ -0,0 +1,24 @@
+//
+//  HomeStatisticsView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/26.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef void(^RefreshViewHeightCallback)(CGFloat viewHeight);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HomeStatisticsView : UIView
+
+@property (nonatomic, weak) UINavigationController *naviController;
+
++ (instancetype)sharedInstance;
+
+- (void)configWebViewRefreshCallback:(RefreshViewHeightCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 268 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/HomeStatistics/HomeStatisticsView.m

@@ -0,0 +1,268 @@
+//
+//  HomeStatisticsView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/26.
+//
+
+#import "HomeStatisticsView.h"
+#import <WebKit/WebKit.h>
+#import <WeakWebViewScriptMessageDelegate.h>
+#import "KSBaseWKWebViewController.h"
+#import "KSWebLoadRefreshView.h"
+#import <AuthChallengeManager.h>
+
+@interface HomeStatisticsView ()<WKUIDelegate,WKNavigationDelegate,WKScriptMessageHandler,UIScrollViewDelegate>
+
+@property (nonatomic, strong) WKWebView *myWebView;
+
+@property (nonatomic, strong) NSString *url;
+
+@property (nonatomic, strong) KSWebLoadRefreshView *errorView;
+
+@property (nonatomic, copy) RefreshViewHeightCallback callback;
+@end
+
+@implementation HomeStatisticsView
+
++ (instancetype)sharedInstance {
+    HomeStatisticsView *view = [[[NSBundle mainBundle] loadNibNamed:@"HomeStatisticsView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+
+- (void)configWebViewRefreshCallback:(RefreshViewHeightCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    self.url = [NSString stringWithFormat:@"%@%@",WEBHOST,@"/#/home-echarts"];
+    [self addSubview:self.myWebView];
+    [self.myWebView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.mas_equalTo(self);
+        make.top.mas_equalTo(self.mas_top);
+        make.bottom.mas_equalTo(self.mas_bottom);
+    }];
+    [self loadRequest];
+}
+
+- (void)configUserAgent:(WKWebViewConfiguration *)config {
+    NSString *oldUserAgent = config.applicationNameForUserAgent;
+    NSString *newAgent = [NSString stringWithFormat:@"%@ %@ %@",oldUserAgent,AGENT_NAME,AGENT_DOMAIN];
+    config.applicationNameForUserAgent = newAgent;
+}
+
+
++ (WKProcessPool*)singleWkProcessPool {
+    static WKProcessPool *sharedPool;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        sharedPool = [[WKProcessPool alloc] init];
+    });
+    return sharedPool;
+}
+
+- (void)loadRequest {
+    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.url] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0f];
+    [self.myWebView loadRequest:request];
+}
+
+- (NSDictionary *)convertJsonStringToNSDictionary:(NSString *)jsonString {
+    if (jsonString == nil) {
+        return nil;
+    }
+    NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
+    NSError *error;
+    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
+    if (error) {
+        NSLog(@"jsonString解析失败:%@", error);
+        return nil;
+    }
+    return json;
+}
+
+#pragma mark - WKScriptMessageHandler
+- (void)userContentController:(WKUserContentController *)userContentController
+      didReceiveScriptMessage:(WKScriptMessage *)message {
+    
+    if ([message.name isEqualToString:SCRIPT_NAME]) {
+        NSDictionary *parm = [self convertJsonStringToNSDictionary:message.body];
+        // 回到主线程
+        dispatch_async(dispatch_get_main_queue(), ^{
+            [self handleScriptMessageSource:parm];
+        });
+    }
+}
+
+- (void)handleScriptMessageSource:(NSDictionary *)parm {
+    if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"openWebView"]) {
+        NSDictionary *valueDic = [parm ks_dictionaryValueForKey:@"content"];
+        
+        KSBaseWKWebViewController *detailCtrl = [[KSBaseWKWebViewController alloc] init];
+        detailCtrl.url = [valueDic ks_stringValueForKey:@"url"];
+        detailCtrl.parmDic = valueDic;
+        NSInteger orientation = [valueDic ks_integerValueForKey:@"orientation"];
+        BOOL isLandScape = orientation == 0 ? YES : NO;
+        detailCtrl.ks_landScape = isLandScape;
+        [self postMessage:parm];
+
+        [self.naviController pushViewController:detailCtrl animated:YES];
+    }
+//    else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@""]) { // 下载文件
+//        
+//    }
+}
+
+
+#pragma mark ----- lazying
+- (WKWebView *)myWebView {
+    if (!_myWebView) {
+        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
+        config.selectionGranularity = WKSelectionGranularityDynamic;
+        config.allowsInlineMediaPlayback = YES;
+        config.mediaTypesRequiringUserActionForPlayback = NO;
+        config.processPool = [HomeStatisticsView singleWkProcessPool];
+        config.websiteDataStore = [WKWebsiteDataStore defaultDataStore];
+        [self configUserAgent:config];
+        
+        //自定义的WKScriptMessageHandler 是为了解决内存不释放的问题
+        WeakWebViewScriptMessageDelegate *weakScriptMessageDelegate = [[WeakWebViewScriptMessageDelegate alloc] initWithDelegate:self];
+        //这个类主要用来做native与JavaScript的交互管理
+        WKUserContentController * wkUController = [[WKUserContentController alloc] init];
+        [wkUController addScriptMessageHandler:weakScriptMessageDelegate name:SCRIPT_NAME];
+        config.userContentController = wkUController;
+        
+        WKPreferences *preferences = [WKPreferences new];
+        // 是否支出javaScript
+        preferences.javaScriptEnabled = YES;
+        //不通过用户交互,是否可以打开窗口
+        preferences.javaScriptCanOpenWindowsAutomatically = YES;
+        config.preferences = preferences;
+        _myWebView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
+        _myWebView.UIDelegate = self;
+        _myWebView.navigationDelegate = self;
+        _myWebView.scrollView.bounces = NO;
+        _myWebView.scrollView.opaque = NO;
+        _myWebView.scrollView.alwaysBounceVertical = NO;
+        _myWebView.scrollView.alwaysBounceHorizontal = NO;
+        _myWebView.scrollView.showsVerticalScrollIndicator = NO;
+        _myWebView.scrollView.showsHorizontalScrollIndicator = NO;
+        _myWebView.scrollView.delegate = self;
+    }
+    return _myWebView;
+}
+
+- (void)postMessage:(NSDictionary *)parm {
+    if (_myWebView) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            NSString *jsString = [parm mj_JSONString];
+            [self.myWebView evaluateJavaScript:[NSString stringWithFormat:@"postMessage(%@,'*')", jsString] completionHandler:nil];
+        });
+    }
+}
+
+
+
+- (void)dealloc {
+    [[_myWebView configuration].userContentController removeScriptMessageHandlerForName:SCRIPT_NAME];
+    [_myWebView loadHTMLString:@"" baseURL:nil];
+    [_myWebView removeFromSuperview];
+    _myWebView = nil;
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
+    [self showErrorView];
+}
+
+- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *_Nullable))completionHandler
+{
+    dispatch_queue_t queue =  dispatch_queue_create("webViewChallengeQueue", NULL);
+    dispatch_async(queue, ^{
+        if (SSL_AUTH) {
+
+            NSURLSessionAuthChallengeDisposition disposition = NSURLSessionAuthChallengePerformDefaultHandling;
+            NSURLCredential *customCredential = nil;
+            
+            if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
+                // 默认信任
+                customCredential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
+                disposition = NSURLSessionAuthChallengeUseCredential;
+            }
+            else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate]) {
+                // client authentication
+                SecIdentityRef identity = NULL;
+                SecTrustRef trust = NULL;
+                if ([AuthChallengeManager extractIdentity:&identity andTrust:&trust filePath:CERT_PATH]) {
+                    SecCertificateRef certificate = NULL;
+                    SecIdentityCopyCertificate(identity, &certificate);
+                    const void*certs[] = {certificate};
+                    CFArrayRef certArray =CFArrayCreate(kCFAllocatorDefault, certs,1,NULL);
+                    customCredential =[NSURLCredential credentialWithIdentity:identity certificates:(__bridge  NSArray*)certArray persistence:NSURLCredentialPersistencePermanent];
+                    disposition = NSURLSessionAuthChallengeUseCredential;
+                    // 释放 CFArrayRef 和 SecCertificateRef
+                    CFRelease(certArray);
+                    CFRelease(certificate);
+                }
+            }
+            
+            if (completionHandler) {
+                completionHandler(disposition, customCredential);
+            }
+        }
+        else {
+            if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
+                if (challenge.previousFailureCount == 0) {
+                    NSURLCredential *credential = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
+                    completionHandler(NSURLSessionAuthChallengeUseCredential, credential);
+                } else {
+                    completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
+                }
+            } else {
+                completionHandler(NSURLSessionAuthChallengeUseCredential, nil);
+            }
+        }
+    });
+}
+
+- (KSWebLoadRefreshView *)errorView {
+    if (!_errorView) {
+        _errorView = [KSWebLoadRefreshView shareInstance];
+        _errorView.hideBackButton = YES;
+        MJWeakSelf;
+        [_errorView failViewActionCallback:^(BOOL isBack) {
+            [weakSelf hideErrorView];
+            if (isBack) {
+                
+            }
+            else {
+                [weakSelf loadRequest];
+            }
+        }];
+    }
+    return _errorView;
+}
+
+- (void)showErrorView {
+    if (![self.subviews containsObject:self.errorView]) {
+        [self addSubview:self.errorView];
+        [self.errorView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.right.top.bottom.mas_equalTo(self);
+        }];
+        [self bringSubviewToFront:self.errorView];
+    }
+}
+
+- (void)hideErrorView {
+    if ([self.subviews containsObject:self.errorView]) {
+        [self.errorView removeFromSuperview];
+    }
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 2 - 2
KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeHotAlbumCell.xib

@@ -30,7 +30,7 @@
                         </userDefinedRuntimeAttributes>
                     </imageView>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="萨克斯新手…" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1bh-Zm-ov0">
-                        <rect key="frame" x="3" y="114" width="94" height="20"/>
+                        <rect key="frame" x="3" y="112" width="94" height="20"/>
                         <constraints>
                             <constraint firstAttribute="height" constant="20" id="s4H-Kv-zgp"/>
                         </constraints>
@@ -93,7 +93,7 @@
             </view>
             <viewLayoutGuide key="safeArea" id="SEy-5g-ep8"/>
             <constraints>
-                <constraint firstItem="1bh-Zm-ov0" firstAttribute="top" secondItem="mkp-8k-Rld" secondAttribute="bottom" constant="10" id="8Ah-sJ-mEm"/>
+                <constraint firstItem="1bh-Zm-ov0" firstAttribute="top" secondItem="mkp-8k-Rld" secondAttribute="bottom" constant="8" id="8Ah-sJ-mEm"/>
                 <constraint firstItem="mkp-8k-Rld" firstAttribute="centerX" secondItem="gTV-IL-0wX" secondAttribute="centerX" id="Oca-f5-sam"/>
                 <constraint firstItem="mkp-8k-Rld" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" constant="10" id="XeE-bJ-DC9"/>
                 <constraint firstItem="E1s-oA-ark" firstAttribute="top" secondItem="mkp-8k-Rld" secondAttribute="top" id="fSg-j4-d7O"/>

+ 31 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeMusicPageView/HomeMusicPageView.h

@@ -0,0 +1,31 @@
+//
+//  HomeMusicPageView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/26.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSInteger, HOME_MUSIC_TAG) {
+    HOME_MUSIC_TAG_RECOMMEND, // 推介
+    HOME_MUSIC_TAG_HOT,       // 热门
+    HOME_MUSIC_TAG_NEW,       // 最新
+    HOME_MUSIC_TAG_MORE,      // 更多
+};
+
+typedef void(^HomeMusicPageViewCallback)(HOME_MUSIC_TAG action);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HomeMusicPageView : UIView
+
++ (instancetype)sharedInstance;
+
+- (void)pageActionCallback:(HomeMusicPageViewCallback)callback;
+
++ (CGFloat)getViewHeight;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 44 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeMusicPageView/HomeMusicPageView.m

@@ -0,0 +1,44 @@
+//
+//  HomeMusicPageView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/26.
+//
+
+#import "HomeMusicPageView.h"
+
+@interface HomeMusicPageView ()
+
+@property (nonatomic, copy) HomeMusicPageViewCallback callback;
+
+@end
+
+@implementation HomeMusicPageView
+
+
++ (instancetype)sharedInstance {
+    HomeMusicPageView *view = [[[NSBundle mainBundle] loadNibNamed:@"HomeMusicPageView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)pageActionCallback:(HomeMusicPageViewCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
++ (CGFloat)getViewHeight {
+    CGFloat imageWidth = (KPortraitWidth - 14 * 2 - 12 * 2 - 10 * 2) / 3.0f;
+    CGFloat imageHeight = imageWidth / 101.0f * 92.0f;
+    return 80 + imageHeight;
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 168 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeMusicPageView/HomeMusicPageView.xib

@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <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="HomeMusicPageView">
+            <rect key="frame" x="0.0" y="0.0" width="375" height="172"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ZPo-SV-HeG">
+                    <rect key="frame" x="14" y="12" width="347" height="148"/>
+                    <subviews>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Y5r-ts-DoX">
+                            <rect key="frame" x="290" y="13" width="45" height="18"/>
+                            <subviews>
+                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="更多" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1hk-0n-5Y5">
+                                    <rect key="frame" x="6" y="1.6666666666666679" width="24" height="15"/>
+                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                    <color key="textColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                    <nil key="highlightedColor"/>
+                                </label>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="home_more_green" translatesAutoresizingMaskIntoConstraints="NO" id="DEv-sd-PP4">
+                                    <rect key="frame" x="34" y="5" width="6" height="8"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="8" id="0hE-Zk-eeX"/>
+                                        <constraint firstAttribute="width" constant="6" id="vuN-XZ-xWe"/>
+                                    </constraints>
+                                </imageView>
+                            </subviews>
+                            <color key="backgroundColor" red="0.1764705882" green="0.78039215689999997" blue="0.66666666669999997" alpha="0.10000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstItem="1hk-0n-5Y5" firstAttribute="centerY" secondItem="Y5r-ts-DoX" secondAttribute="centerY" id="3QF-n3-l3i"/>
+                                <constraint firstAttribute="width" constant="45" id="BdX-wa-BdI"/>
+                                <constraint firstAttribute="trailing" secondItem="DEv-sd-PP4" secondAttribute="trailing" constant="5" id="FON-d3-YTL"/>
+                                <constraint firstAttribute="height" constant="18" id="awh-4r-ml1"/>
+                                <constraint firstItem="DEv-sd-PP4" firstAttribute="centerY" secondItem="Y5r-ts-DoX" secondAttribute="centerY" id="sYt-Ge-Iz6"/>
+                                <constraint firstItem="1hk-0n-5Y5" firstAttribute="leading" secondItem="Y5r-ts-DoX" secondAttribute="leading" constant="6" id="zdO-W7-Cyz"/>
+                            </constraints>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="9"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                        </view>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0QL-gB-Zjx">
+                            <rect key="frame" x="290" y="7" width="45" height="30"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="30" id="Wfu-nR-rKi"/>
+                            </constraints>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                        </button>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="home_music_icon" translatesAutoresizingMaskIntoConstraints="NO" id="nbK-4M-Pq7">
+                            <rect key="frame" x="12" y="13" width="18" height="18"/>
+                        </imageView>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="曲目" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ATh-Pl-TWm">
+                            <rect key="frame" x="36" y="12" width="30" height="20"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="20" id="rrL-Mh-nw9"/>
+                            </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>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="biR-35-QOg">
+                            <rect key="frame" x="12" y="44" width="101" height="92"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="home_recommend_music" translatesAutoresizingMaskIntoConstraints="NO" id="FxH-IH-4qd">
+                                    <rect key="frame" x="0.0" y="0.0" width="101" height="92"/>
+                                </imageView>
+                            </subviews>
+                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            <constraints>
+                                <constraint firstItem="FxH-IH-4qd" firstAttribute="top" secondItem="biR-35-QOg" secondAttribute="top" id="Pr2-fS-9rf"/>
+                                <constraint firstAttribute="trailing" secondItem="FxH-IH-4qd" secondAttribute="trailing" id="STk-1K-UE5"/>
+                                <constraint firstItem="FxH-IH-4qd" firstAttribute="leading" secondItem="biR-35-QOg" secondAttribute="leading" id="bf0-qJ-cau"/>
+                                <constraint firstAttribute="width" secondItem="biR-35-QOg" secondAttribute="height" multiplier="101:92" id="m1C-qf-M5D"/>
+                                <constraint firstAttribute="bottom" secondItem="FxH-IH-4qd" secondAttribute="bottom" id="zlb-UD-Kps"/>
+                            </constraints>
+                        </view>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aKe-lV-Gxm">
+                            <rect key="frame" x="123" y="44" width="101" height="92"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="home_hot_music" translatesAutoresizingMaskIntoConstraints="NO" id="fhQ-N6-QVv">
+                                    <rect key="frame" x="0.0" y="0.0" width="101" height="92"/>
+                                </imageView>
+                            </subviews>
+                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            <constraints>
+                                <constraint firstAttribute="width" secondItem="aKe-lV-Gxm" secondAttribute="height" multiplier="101:92" id="Hxn-yJ-JUp"/>
+                                <constraint firstAttribute="trailing" secondItem="fhQ-N6-QVv" secondAttribute="trailing" id="I67-HH-Wmm"/>
+                                <constraint firstItem="fhQ-N6-QVv" firstAttribute="leading" secondItem="aKe-lV-Gxm" secondAttribute="leading" id="Rzb-J3-heH"/>
+                                <constraint firstItem="fhQ-N6-QVv" firstAttribute="top" secondItem="aKe-lV-Gxm" secondAttribute="top" id="qWD-Jk-e8m"/>
+                                <constraint firstAttribute="bottom" secondItem="fhQ-N6-QVv" secondAttribute="bottom" id="rtI-Tb-8oY"/>
+                            </constraints>
+                        </view>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jKd-mQ-8sh">
+                            <rect key="frame" x="234" y="44" width="101" height="92"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="home_newest_music" translatesAutoresizingMaskIntoConstraints="NO" id="Hom-x6-dld">
+                                    <rect key="frame" x="0.0" y="0.0" width="101" height="92"/>
+                                </imageView>
+                            </subviews>
+                            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            <constraints>
+                                <constraint firstAttribute="width" secondItem="jKd-mQ-8sh" secondAttribute="height" multiplier="101:92" id="AJD-jL-7xh"/>
+                                <constraint firstAttribute="bottom" secondItem="Hom-x6-dld" secondAttribute="bottom" id="U1H-IQ-zDz"/>
+                                <constraint firstAttribute="trailing" secondItem="Hom-x6-dld" secondAttribute="trailing" id="dAA-yu-6j1"/>
+                                <constraint firstItem="Hom-x6-dld" firstAttribute="leading" secondItem="jKd-mQ-8sh" secondAttribute="leading" id="qak-qJ-lBb"/>
+                                <constraint firstItem="Hom-x6-dld" firstAttribute="top" secondItem="jKd-mQ-8sh" secondAttribute="top" id="y5i-Xk-YeN"/>
+                            </constraints>
+                        </view>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="aKe-lV-Gxm" firstAttribute="width" secondItem="biR-35-QOg" secondAttribute="width" id="0Ml-AM-z03"/>
+                        <constraint firstItem="Y5r-ts-DoX" firstAttribute="centerY" secondItem="ATh-Pl-TWm" secondAttribute="centerY" id="KJS-B9-0GQ"/>
+                        <constraint firstItem="ATh-Pl-TWm" firstAttribute="top" secondItem="ZPo-SV-HeG" secondAttribute="top" constant="12" id="Kqq-9T-bjt"/>
+                        <constraint firstItem="jKd-mQ-8sh" firstAttribute="leading" secondItem="aKe-lV-Gxm" secondAttribute="trailing" constant="10" id="Q57-J8-VgU"/>
+                        <constraint firstItem="nbK-4M-Pq7" firstAttribute="leading" secondItem="ZPo-SV-HeG" secondAttribute="leading" constant="12" id="QxC-xY-L3y"/>
+                        <constraint firstItem="Y5r-ts-DoX" firstAttribute="centerY" secondItem="0QL-gB-Zjx" secondAttribute="centerY" id="REZ-6g-O9B"/>
+                        <constraint firstItem="biR-35-QOg" firstAttribute="leading" secondItem="ZPo-SV-HeG" secondAttribute="leading" constant="12" id="Run-1w-eLP"/>
+                        <constraint firstItem="jKd-mQ-8sh" firstAttribute="width" secondItem="biR-35-QOg" secondAttribute="width" id="SU7-HB-i1r"/>
+                        <constraint firstAttribute="trailing" secondItem="jKd-mQ-8sh" secondAttribute="trailing" constant="12" id="Tj6-yw-gDL"/>
+                        <constraint firstItem="Y5r-ts-DoX" firstAttribute="leading" secondItem="0QL-gB-Zjx" secondAttribute="leading" id="U3D-lf-SD3"/>
+                        <constraint firstItem="jKd-mQ-8sh" firstAttribute="bottom" secondItem="biR-35-QOg" secondAttribute="bottom" id="XlD-Wn-pzh"/>
+                        <constraint firstAttribute="bottom" secondItem="biR-35-QOg" secondAttribute="bottom" constant="12" id="YwG-AL-nz4"/>
+                        <constraint firstAttribute="trailing" secondItem="Y5r-ts-DoX" secondAttribute="trailing" constant="12" id="cIT-RS-MW0"/>
+                        <constraint firstItem="ATh-Pl-TWm" firstAttribute="centerY" secondItem="nbK-4M-Pq7" secondAttribute="centerY" id="cdu-MC-mKR"/>
+                        <constraint firstItem="ATh-Pl-TWm" firstAttribute="leading" secondItem="nbK-4M-Pq7" secondAttribute="trailing" constant="6" id="fmK-sM-Gol"/>
+                        <constraint firstItem="biR-35-QOg" firstAttribute="top" secondItem="ATh-Pl-TWm" secondAttribute="bottom" constant="12" id="gCX-NM-Sc2"/>
+                        <constraint firstItem="aKe-lV-Gxm" firstAttribute="leading" secondItem="biR-35-QOg" secondAttribute="trailing" constant="10" id="njC-Tu-gZ8"/>
+                        <constraint firstItem="aKe-lV-Gxm" firstAttribute="bottom" secondItem="biR-35-QOg" secondAttribute="bottom" id="pf3-Jv-WnY"/>
+                        <constraint firstItem="Y5r-ts-DoX" firstAttribute="trailing" secondItem="0QL-gB-Zjx" secondAttribute="trailing" id="uiw-yb-xaM"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="10"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="ZPo-SV-HeG" secondAttribute="bottom" constant="12" id="9uM-4W-RwS"/>
+                <constraint firstAttribute="trailing" secondItem="ZPo-SV-HeG" secondAttribute="trailing" constant="14" id="A3w-We-WgU"/>
+                <constraint firstItem="ZPo-SV-HeG" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="14" id="Xxa-ww-q2o"/>
+                <constraint firstItem="ZPo-SV-HeG" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="12" id="e9s-OZ-GpR"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <point key="canvasLocation" x="132.06106870229007" y="73.239436619718319"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="home_hot_music" width="101" height="92"/>
+        <image name="home_more_green" width="5" height="8"/>
+        <image name="home_music_icon" width="18" height="18"/>
+        <image name="home_newest_music" width="101" height="92"/>
+        <image name="home_recommend_music" width="101" height="92"/>
+    </resources>
+</document>

+ 27 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeNewAlbum/HomeNewAlbumView.h

@@ -0,0 +1,27 @@
+//
+//  HomeNewAlbumView.h
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/26.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^HomeNewAlbumMoreBlock)(void);
+
+
+@interface HomeNewAlbumView : UIView
+
+@property (weak, nonatomic) IBOutlet UIView *albumContentView;
+
++ (instancetype)sharedInstance;
+
+- (void)homeAlbumMore:(HomeNewAlbumMoreBlock)callback;
+
++ (CGFloat)getViewHeight;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 48 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeNewAlbum/HomeNewAlbumView.m

@@ -0,0 +1,48 @@
+//
+//  HomeNewAlbumView.m
+//  KulexiuForTeacher
+//
+//  Created by 王智 on 2024/12/26.
+//
+
+#import "HomeNewAlbumView.h"
+
+@interface HomeNewAlbumView ()
+
+@property (nonatomic, copy) HomeNewAlbumMoreBlock callback;
+
+
+@end
+
+@implementation HomeNewAlbumView
+
++ (instancetype)sharedInstance {
+    HomeNewAlbumView *view = [[[NSBundle mainBundle] loadNibNamed:@"HomeNewAlbumView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)homeAlbumMore:(HomeNewAlbumMoreBlock)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+    
+}
+
+- (IBAction)moreAlbum:(id)sender {
+    if (self.callback) {
+        self.callback();
+    }
+}
+
++ (CGFloat)getViewHeight {
+    return 198.0f;
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 128 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Home/View/HomeNewAlbum/HomeNewAlbumView.xib

@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="23504" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="23506"/>
+        <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="HomeNewAlbumView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="198"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="z5G-Gl-4c5">
+                    <rect key="frame" x="14" y="12" width="365" height="186"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="home_album_icon" translatesAutoresizingMaskIntoConstraints="NO" id="OU7-PR-K5u">
+                            <rect key="frame" x="12" y="13" width="18" height="18"/>
+                        </imageView>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="热门专辑" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="2LP-nl-mK2">
+                            <rect key="frame" x="36" y="12" width="60" height="20"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="20" id="igJ-uR-lBF"/>
+                            </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>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jNd-L1-cJI">
+                            <rect key="frame" x="308" y="13" width="45" height="18"/>
+                            <subviews>
+                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="更多" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lYe-vQ-tRQ">
+                                    <rect key="frame" x="6" y="1.6666666666666679" width="24" height="15"/>
+                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                    <color key="textColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                    <nil key="highlightedColor"/>
+                                </label>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="home_more_green" translatesAutoresizingMaskIntoConstraints="NO" id="V1h-0u-u1u">
+                                    <rect key="frame" x="34" y="5" width="6" height="8"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" constant="6" id="hd7-zQ-I3v"/>
+                                        <constraint firstAttribute="height" constant="8" id="tFH-i4-F7h"/>
+                                    </constraints>
+                                </imageView>
+                            </subviews>
+                            <color key="backgroundColor" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="0.10000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
+                            <constraints>
+                                <constraint firstItem="V1h-0u-u1u" firstAttribute="centerY" secondItem="jNd-L1-cJI" secondAttribute="centerY" id="1aT-B8-SAQ"/>
+                                <constraint firstAttribute="width" constant="45" id="BWo-A6-9D0"/>
+                                <constraint firstAttribute="height" constant="18" id="HrV-YU-dNj"/>
+                                <constraint firstItem="lYe-vQ-tRQ" firstAttribute="leading" secondItem="jNd-L1-cJI" secondAttribute="leading" constant="6" id="beg-VB-59T"/>
+                                <constraint firstAttribute="trailing" secondItem="V1h-0u-u1u" secondAttribute="trailing" constant="5" id="eYr-eG-HKw"/>
+                                <constraint firstItem="lYe-vQ-tRQ" firstAttribute="centerY" secondItem="jNd-L1-cJI" secondAttribute="centerY" id="svd-PQ-RQg"/>
+                            </constraints>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="9"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                        </view>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="yQq-3q-xwT">
+                            <rect key="frame" x="308" y="7" width="45" height="30"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="30" id="NRc-5s-nbC"/>
+                            </constraints>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="moreAlbum:" destination="iN0-l3-epB" eventType="touchUpInside" id="G6u-op-kRJ"/>
+                            </connections>
+                        </button>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="x64-uM-YiP">
+                            <rect key="frame" x="0.0" y="42" width="365" height="134"/>
+                            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="134" id="6hD-4P-ZyT"/>
+                            </constraints>
+                        </view>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="OU7-PR-K5u" firstAttribute="leading" secondItem="z5G-Gl-4c5" secondAttribute="leading" constant="12" id="7hP-Ha-cpZ"/>
+                        <constraint firstItem="x64-uM-YiP" firstAttribute="top" secondItem="2LP-nl-mK2" secondAttribute="bottom" constant="10" id="MY1-e5-Wml"/>
+                        <constraint firstItem="jNd-L1-cJI" firstAttribute="centerY" secondItem="2LP-nl-mK2" secondAttribute="centerY" id="QoY-hu-4wO"/>
+                        <constraint firstItem="jNd-L1-cJI" firstAttribute="leading" secondItem="yQq-3q-xwT" secondAttribute="leading" id="QqA-Oe-ZCE"/>
+                        <constraint firstAttribute="trailing" secondItem="jNd-L1-cJI" secondAttribute="trailing" constant="12" id="QtC-HC-YdS"/>
+                        <constraint firstItem="2LP-nl-mK2" firstAttribute="centerY" secondItem="OU7-PR-K5u" secondAttribute="centerY" id="Vda-0C-ufH"/>
+                        <constraint firstItem="x64-uM-YiP" firstAttribute="leading" secondItem="z5G-Gl-4c5" secondAttribute="leading" id="dHL-1w-jES"/>
+                        <constraint firstAttribute="bottom" secondItem="x64-uM-YiP" secondAttribute="bottom" constant="10" id="iK3-eA-Taw"/>
+                        <constraint firstAttribute="trailing" secondItem="x64-uM-YiP" secondAttribute="trailing" id="jKv-Bk-Y0H"/>
+                        <constraint firstItem="2LP-nl-mK2" firstAttribute="top" secondItem="z5G-Gl-4c5" secondAttribute="top" constant="12" id="jVi-PP-qqs"/>
+                        <constraint firstItem="jNd-L1-cJI" firstAttribute="centerY" secondItem="yQq-3q-xwT" secondAttribute="centerY" id="t9h-5i-ns0"/>
+                        <constraint firstItem="2LP-nl-mK2" firstAttribute="leading" secondItem="OU7-PR-K5u" secondAttribute="trailing" constant="6" id="wJO-mp-RZt"/>
+                        <constraint firstItem="jNd-L1-cJI" firstAttribute="trailing" secondItem="yQq-3q-xwT" secondAttribute="trailing" id="x15-7n-gya"/>
+                    </constraints>
+                    <userDefinedRuntimeAttributes>
+                        <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                            <real key="value" value="10"/>
+                        </userDefinedRuntimeAttribute>
+                    </userDefinedRuntimeAttributes>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstItem="z5G-Gl-4c5" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="14" id="QXO-be-HV3"/>
+                <constraint firstItem="z5G-Gl-4c5" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="12" id="Tql-7c-rWP"/>
+                <constraint firstAttribute="bottom" secondItem="z5G-Gl-4c5" secondAttribute="bottom" id="u5u-XB-985"/>
+                <constraint firstAttribute="trailing" secondItem="z5G-Gl-4c5" secondAttribute="trailing" constant="14" id="zl9-3V-2BP"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="albumContentView" destination="x64-uM-YiP" id="LPB-oc-laG"/>
+            </connections>
+            <point key="canvasLocation" x="41.984732824427482" y="100"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="home_album_icon" width="18" height="18"/>
+        <image name="home_more_green" width="5" height="8"/>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>