Przeglądaj źródła

云教练合成功能

Steven 1 rok temu
rodzic
commit
8294d68136
67 zmienionych plików z 3007 dodań i 72 usunięć
  1. 129 17
      KulexiuForTeacher/KulexiuForTeacher.xcodeproj/project.pbxproj
  2. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/choose_status.imageset/Contents.json
  3. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/choose_status.imageset/choose_status@2x.png
  4. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/choose_status.imageset/choose_status@3x.png
  5. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mineWorks_bg.imageset/Contents.json
  6. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mineWorks_bg.imageset/mineWorks_bg@2x.png
  7. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mineWorks_bg.imageset/mineWorks_bg@3x.png
  8. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_musicProduct.imageset/Contents.json
  9. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_musicProduct.imageset/mine_musicProduct@2x.png
  10. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_musicProduct.imageset/mine_musicProduct@3x.png
  11. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_worksTitle.imageset/Contents.json
  12. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_worksTitle.imageset/mine_worksTitle@2x.png
  13. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_worksTitle.imageset/mine_worksTitle@3x.png
  14. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_edit.imageset/Contents.json
  15. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_edit.imageset/product_edit@2x.png
  16. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_edit.imageset/product_edit@3x.png
  17. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_like.imageset/Contents.json
  18. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_like.imageset/product_like@2x.png
  19. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_like.imageset/product_like@3x.png
  20. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_play.imageset/Contents.json
  21. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_play.imageset/product_play@2x.png
  22. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_play.imageset/product_play@3x.png
  23. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/slider_bubble.imageset/slider_bubble@2x.png
  24. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/slider_bubble.imageset/slider_bubble@3x.png
  25. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/sure_delete_image.imageset/Contents.json
  26. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/sure_delete_image.imageset/sure_delete_image@2x.png
  27. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/sure_delete_image.imageset/sure_delete_image@3x.png
  28. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/time_grey.imageset/Contents.json
  29. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/time_grey.imageset/time_grey@2x.png
  30. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/time_grey.imageset/time_grey@3x.png
  31. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/unChoose_status.imageset/Contents.json
  32. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/unChoose_status.imageset/unChoose_status@2x.png
  33. BIN
      KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/unChoose_status.imageset/unChoose_status@3x.png
  34. 53 1
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSBaseWKWebViewController.m
  35. 20 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSEmptyStatusView.h
  36. 40 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSEmptyStatusView.m
  37. 51 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSEmptyStatusView.xib
  38. 3 3
      KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.m
  39. 18 18
      KulexiuForTeacher/KulexiuForTeacher/Common/Define/KSDomain.h
  40. 13 4
      KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/AudioMerge/KSMediaMergeView.m
  41. 0 3
      KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/AudioMerge/MusicPublistAlert.m
  42. 14 0
      KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/MediaEditor/KSMediaEditor.h
  43. 66 3
      KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/MediaEditor/KSMediaEditor.m
  44. 16 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Tools/GifRefresh/KSNewGifRefreshFooter.h
  45. 150 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Tools/GifRefresh/KSNewGifRefreshFooter.m
  46. 3 0
      KulexiuForTeacher/KulexiuForTeacher/Common/Tools/UMShare/KSUMShareManager.h
  47. 169 23
      KulexiuForTeacher/KulexiuForTeacher/Common/Tools/UMShare/KSUMShareManager.m
  48. 22 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Controller/KSDraftMergeViewController.h
  49. 114 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Controller/KSDraftMergeViewController.m
  50. 23 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Controller/MineWorksViewController.h
  51. 224 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Controller/MineWorksViewController.m
  52. 47 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Model/UserMusicFormalModel.h
  53. 274 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Model/UserMusicFormalModel.m
  54. 18 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBodyView.h
  55. 447 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBodyView.m
  56. 33 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBottomView.h
  57. 57 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBottomView.m
  58. 86 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBottomView.xib
  59. 19 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksDraftsCell.h
  60. 72 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksDraftsCell.m
  61. 132 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksDraftsCell.xib
  62. 29 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksNavView.h
  63. 85 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksNavView.m
  64. 123 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksNavView.xib
  65. 19 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksOpenDisplayCell.h
  66. 67 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksOpenDisplayCell.m
  67. 151 0
      KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksOpenDisplayCell.xib

+ 129 - 17
KulexiuForTeacher/KulexiuForTeacher.xcodeproj/project.pbxproj

@@ -632,6 +632,21 @@
 		BC38C4302AF900E100ABFCC2 /* KSAudioAnimationView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C41B2AF900E100ABFCC2 /* KSAudioAnimationView.m */; };
 		BC38C4312AF900E100ABFCC2 /* KSMediaEditor.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C41D2AF900E100ABFCC2 /* KSMediaEditor.m */; };
 		BC38C4322AF900E100ABFCC2 /* kSNewPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C4212AF900E100ABFCC2 /* kSNewPlayer.m */; };
+		BC38C47C2AFA1F4B00ABFCC2 /* KSDraftMergeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C4662AFA1F4B00ABFCC2 /* KSDraftMergeViewController.m */; };
+		BC38C47D2AFA1F4B00ABFCC2 /* MineWorksViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C4692AFA1F4B00ABFCC2 /* MineWorksViewController.m */; };
+		BC38C47E2AFA1F4B00ABFCC2 /* UserMusicFormalModel.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C46C2AFA1F4B00ABFCC2 /* UserMusicFormalModel.m */; };
+		BC38C47F2AFA1F4B00ABFCC2 /* MineWorksDraftsCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC38C4702AFA1F4B00ABFCC2 /* MineWorksDraftsCell.xib */; };
+		BC38C4802AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C4742AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.m */; };
+		BC38C4812AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC38C4752AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.xib */; };
+		BC38C4822AFA1F4B00ABFCC2 /* MineWorksNavView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C4762AFA1F4B00ABFCC2 /* MineWorksNavView.m */; };
+		BC38C4832AFA1F4B00ABFCC2 /* MineWorksDraftsCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C4772AFA1F4B00ABFCC2 /* MineWorksDraftsCell.m */; };
+		BC38C4842AFA1F4B00ABFCC2 /* MineWorksNavView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC38C4782AFA1F4B00ABFCC2 /* MineWorksNavView.xib */; };
+		BC38C4852AFA1F4B00ABFCC2 /* MineWorksBodyView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C4792AFA1F4B00ABFCC2 /* MineWorksBodyView.m */; };
+		BC38C4862AFA1F4B00ABFCC2 /* MineWorksBottomView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C47A2AFA1F4B00ABFCC2 /* MineWorksBottomView.m */; };
+		BC38C4872AFA1F4B00ABFCC2 /* MineWorksBottomView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC38C47B2AFA1F4B00ABFCC2 /* MineWorksBottomView.xib */; };
+		BC38C48B2AFA207B00ABFCC2 /* KSEmptyStatusView.xib in Resources */ = {isa = PBXBuildFile; fileRef = BC38C4892AFA207A00ABFCC2 /* KSEmptyStatusView.xib */; };
+		BC38C48C2AFA207B00ABFCC2 /* KSEmptyStatusView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C48A2AFA207B00ABFCC2 /* KSEmptyStatusView.m */; };
+		BC38C48F2AFA20AB00ABFCC2 /* KSNewGifRefreshFooter.m in Sources */ = {isa = PBXBuildFile; fileRef = BC38C48E2AFA20AB00ABFCC2 /* KSNewGifRefreshFooter.m */; };
 		BC3A4EB728DAFCF7001C4428 /* MusicTagView.m in Sources */ = {isa = PBXBuildFile; fileRef = BC3A4EB628DAFCF7001C4428 /* MusicTagView.m */; };
 		BC3ACD942890D60800060E97 /* FreezeListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC3ACD932890D60800060E97 /* FreezeListViewController.m */; };
 		BC3ACD972890D61400060E97 /* NoRecordViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BC3ACD962890D61400060E97 /* NoRecordViewController.m */; };
@@ -2367,6 +2382,31 @@
 		BC38C41E2AF900E100ABFCC2 /* KSMediaEditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSMediaEditor.h; sourceTree = "<group>"; };
 		BC38C4202AF900E100ABFCC2 /* kSNewPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kSNewPlayer.h; sourceTree = "<group>"; };
 		BC38C4212AF900E100ABFCC2 /* kSNewPlayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = kSNewPlayer.m; sourceTree = "<group>"; };
+		BC38C4662AFA1F4B00ABFCC2 /* KSDraftMergeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSDraftMergeViewController.m; sourceTree = "<group>"; };
+		BC38C4672AFA1F4B00ABFCC2 /* MineWorksViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MineWorksViewController.h; sourceTree = "<group>"; };
+		BC38C4682AFA1F4B00ABFCC2 /* KSDraftMergeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSDraftMergeViewController.h; sourceTree = "<group>"; };
+		BC38C4692AFA1F4B00ABFCC2 /* MineWorksViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MineWorksViewController.m; sourceTree = "<group>"; };
+		BC38C46B2AFA1F4B00ABFCC2 /* UserMusicFormalModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserMusicFormalModel.h; sourceTree = "<group>"; };
+		BC38C46C2AFA1F4B00ABFCC2 /* UserMusicFormalModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserMusicFormalModel.m; sourceTree = "<group>"; };
+		BC38C46E2AFA1F4B00ABFCC2 /* MineWorksDraftsCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MineWorksDraftsCell.h; sourceTree = "<group>"; };
+		BC38C46F2AFA1F4B00ABFCC2 /* MineWorksNavView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MineWorksNavView.h; sourceTree = "<group>"; };
+		BC38C4702AFA1F4B00ABFCC2 /* MineWorksDraftsCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MineWorksDraftsCell.xib; sourceTree = "<group>"; };
+		BC38C4712AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MineWorksOpenDisplayCell.h; sourceTree = "<group>"; };
+		BC38C4722AFA1F4B00ABFCC2 /* MineWorksBodyView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MineWorksBodyView.h; sourceTree = "<group>"; };
+		BC38C4732AFA1F4B00ABFCC2 /* MineWorksBottomView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MineWorksBottomView.h; sourceTree = "<group>"; };
+		BC38C4742AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MineWorksOpenDisplayCell.m; sourceTree = "<group>"; };
+		BC38C4752AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MineWorksOpenDisplayCell.xib; sourceTree = "<group>"; };
+		BC38C4762AFA1F4B00ABFCC2 /* MineWorksNavView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MineWorksNavView.m; sourceTree = "<group>"; };
+		BC38C4772AFA1F4B00ABFCC2 /* MineWorksDraftsCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MineWorksDraftsCell.m; sourceTree = "<group>"; };
+		BC38C4782AFA1F4B00ABFCC2 /* MineWorksNavView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MineWorksNavView.xib; sourceTree = "<group>"; };
+		BC38C4792AFA1F4B00ABFCC2 /* MineWorksBodyView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MineWorksBodyView.m; sourceTree = "<group>"; };
+		BC38C47A2AFA1F4B00ABFCC2 /* MineWorksBottomView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MineWorksBottomView.m; sourceTree = "<group>"; };
+		BC38C47B2AFA1F4B00ABFCC2 /* MineWorksBottomView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MineWorksBottomView.xib; sourceTree = "<group>"; };
+		BC38C4882AFA207A00ABFCC2 /* KSEmptyStatusView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSEmptyStatusView.h; sourceTree = "<group>"; };
+		BC38C4892AFA207A00ABFCC2 /* KSEmptyStatusView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = KSEmptyStatusView.xib; sourceTree = "<group>"; };
+		BC38C48A2AFA207B00ABFCC2 /* KSEmptyStatusView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSEmptyStatusView.m; sourceTree = "<group>"; };
+		BC38C48D2AFA20AB00ABFCC2 /* KSNewGifRefreshFooter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KSNewGifRefreshFooter.h; sourceTree = "<group>"; };
+		BC38C48E2AFA20AB00ABFCC2 /* KSNewGifRefreshFooter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KSNewGifRefreshFooter.m; sourceTree = "<group>"; };
 		BC3A4EB528DAFCF7001C4428 /* MusicTagView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MusicTagView.h; sourceTree = "<group>"; };
 		BC3A4EB628DAFCF7001C4428 /* MusicTagView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MusicTagView.m; sourceTree = "<group>"; };
 		BC3ACD922890D60800060E97 /* FreezeListViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FreezeListViewController.h; sourceTree = "<group>"; };
@@ -3694,6 +3734,9 @@
 		2779309627E30F2D0010E277 /* Base */ = {
 			isa = PBXGroup;
 			children = (
+				BC38C4882AFA207A00ABFCC2 /* KSEmptyStatusView.h */,
+				BC38C48A2AFA207B00ABFCC2 /* KSEmptyStatusView.m */,
+				BC38C4892AFA207A00ABFCC2 /* KSEmptyStatusView.xib */,
 				BC9AA0D62ABC432400CD954D /* LoadingManager */,
 				BC28884B2A80DA530064B773 /* LoginManger */,
 				BCC583D328A9FA8100BAB4CF /* CloudLoadingSource */,
@@ -3890,6 +3933,8 @@
 				277930BE27E30FBC0010E277 /* KSGifRefreshFooter.m */,
 				277930C027E30FBC0010E277 /* KSGifRefreshHeader.h */,
 				277930BD27E30FBC0010E277 /* KSGifRefreshHeader.m */,
+				BC38C48D2AFA20AB00ABFCC2 /* KSNewGifRefreshFooter.h */,
+				BC38C48E2AFA20AB00ABFCC2 /* KSNewGifRefreshFooter.m */,
 			);
 			path = GifRefresh;
 			sourceTree = "<group>";
@@ -4615,6 +4660,7 @@
 		277935FE27E32BBF0010E277 /* Mine */ = {
 			isa = PBXGroup;
 			children = (
+				BC38C4642AFA1F4B00ABFCC2 /* Works */,
 				BC81F0DF29232BFD004106AF /* Courseware */,
 				BCB9FA502872BA6D005D766B /* LiveList */,
 				BC4BCE622823990100522C8B /* AddressList */,
@@ -5872,29 +5918,29 @@
 		BC38C4002AF900E100ABFCC2 /* AudioMerge */ = {
 			isa = PBXGroup;
 			children = (
-				BC38C4012AF900E100ABFCC2 /* KSPlayerView.m */,
-				BC38C4022AF900E100ABFCC2 /* UIView+KSCovertImage.m */,
-				BC38C4032AF900E100ABFCC2 /* KSNewAlertView.xib */,
-				BC38C4042AF900E100ABFCC2 /* MusicPublistAlert.h */,
-				BC38C4052AF900E100ABFCC2 /* KSNewAlertView.m */,
+				BC38C4102AF900E100ABFCC2 /* AudioPlayAnimationView */,
 				BC38C4062AF900E100ABFCC2 /* KSAudioAnimationView.h */,
+				BC38C41B2AF900E100ABFCC2 /* KSAudioAnimationView.m */,
+				BC38C40F2AF900E100ABFCC2 /* KSAudioAnimationView.xib */,
+				BC38C41A2AF900E100ABFCC2 /* KSMediaMergeView.h */,
 				BC38C4072AF900E100ABFCC2 /* KSMediaMergeView.m */,
 				BC38C4082AF900E100ABFCC2 /* KSMergeAudioControlView.h */,
-				BC38C4092AF900E100ABFCC2 /* KSPlayerSliderView.h */,
-				BC38C40A2AF900E100ABFCC2 /* VideoPlayerView */,
-				BC38C40D2AF900E100ABFCC2 /* MusicPublistAlert.m */,
-				BC38C40E2AF900E100ABFCC2 /* UIView+KSCovertImage.h */,
-				BC38C40F2AF900E100ABFCC2 /* KSAudioAnimationView.xib */,
-				BC38C4102AF900E100ABFCC2 /* AudioPlayAnimationView */,
-				BC38C4132AF900E100ABFCC2 /* KSPlayerView.h */,
+				BC38C4192AF900E100ABFCC2 /* KSMergeAudioControlView.m */,
 				BC38C4142AF900E100ABFCC2 /* KSMergeAudioControlView.xib */,
-				BC38C4152AF900E100ABFCC2 /* MusicPublistAlert.xib */,
 				BC38C4162AF900E100ABFCC2 /* KSNewAlertView.h */,
+				BC38C4052AF900E100ABFCC2 /* KSNewAlertView.m */,
+				BC38C4032AF900E100ABFCC2 /* KSNewAlertView.xib */,
+				BC38C4092AF900E100ABFCC2 /* KSPlayerSliderView.h */,
 				BC38C4172AF900E100ABFCC2 /* KSPlayerSliderView.m */,
 				BC38C4182AF900E100ABFCC2 /* KSPlayerSliderView.xib */,
-				BC38C4192AF900E100ABFCC2 /* KSMergeAudioControlView.m */,
-				BC38C41A2AF900E100ABFCC2 /* KSMediaMergeView.h */,
-				BC38C41B2AF900E100ABFCC2 /* KSAudioAnimationView.m */,
+				BC38C4132AF900E100ABFCC2 /* KSPlayerView.h */,
+				BC38C4012AF900E100ABFCC2 /* KSPlayerView.m */,
+				BC38C4042AF900E100ABFCC2 /* MusicPublistAlert.h */,
+				BC38C40D2AF900E100ABFCC2 /* MusicPublistAlert.m */,
+				BC38C4152AF900E100ABFCC2 /* MusicPublistAlert.xib */,
+				BC38C40E2AF900E100ABFCC2 /* UIView+KSCovertImage.h */,
+				BC38C4022AF900E100ABFCC2 /* UIView+KSCovertImage.m */,
+				BC38C40A2AF900E100ABFCC2 /* VideoPlayerView */,
 			);
 			path = AudioMerge;
 			sourceTree = "<group>";
@@ -5920,8 +5966,8 @@
 		BC38C41C2AF900E100ABFCC2 /* MediaEditor */ = {
 			isa = PBXGroup;
 			children = (
-				BC38C41D2AF900E100ABFCC2 /* KSMediaEditor.m */,
 				BC38C41E2AF900E100ABFCC2 /* KSMediaEditor.h */,
+				BC38C41D2AF900E100ABFCC2 /* KSMediaEditor.m */,
 			);
 			path = MediaEditor;
 			sourceTree = "<group>";
@@ -5935,6 +5981,57 @@
 			path = MusicPlayer;
 			sourceTree = "<group>";
 		};
+		BC38C4642AFA1F4B00ABFCC2 /* Works */ = {
+			isa = PBXGroup;
+			children = (
+				BC38C4652AFA1F4B00ABFCC2 /* Controller */,
+				BC38C46A2AFA1F4B00ABFCC2 /* Model */,
+				BC38C46D2AFA1F4B00ABFCC2 /* View */,
+			);
+			path = Works;
+			sourceTree = "<group>";
+		};
+		BC38C4652AFA1F4B00ABFCC2 /* Controller */ = {
+			isa = PBXGroup;
+			children = (
+				BC38C4662AFA1F4B00ABFCC2 /* KSDraftMergeViewController.m */,
+				BC38C4672AFA1F4B00ABFCC2 /* MineWorksViewController.h */,
+				BC38C4682AFA1F4B00ABFCC2 /* KSDraftMergeViewController.h */,
+				BC38C4692AFA1F4B00ABFCC2 /* MineWorksViewController.m */,
+			);
+			path = Controller;
+			sourceTree = "<group>";
+		};
+		BC38C46A2AFA1F4B00ABFCC2 /* Model */ = {
+			isa = PBXGroup;
+			children = (
+				BC38C46B2AFA1F4B00ABFCC2 /* UserMusicFormalModel.h */,
+				BC38C46C2AFA1F4B00ABFCC2 /* UserMusicFormalModel.m */,
+			);
+			path = Model;
+			sourceTree = "<group>";
+		};
+		BC38C46D2AFA1F4B00ABFCC2 /* View */ = {
+			isa = PBXGroup;
+			children = (
+				BC38C4722AFA1F4B00ABFCC2 /* MineWorksBodyView.h */,
+				BC38C4792AFA1F4B00ABFCC2 /* MineWorksBodyView.m */,
+				BC38C4732AFA1F4B00ABFCC2 /* MineWorksBottomView.h */,
+				BC38C47A2AFA1F4B00ABFCC2 /* MineWorksBottomView.m */,
+				BC38C47B2AFA1F4B00ABFCC2 /* MineWorksBottomView.xib */,
+				BC38C46E2AFA1F4B00ABFCC2 /* MineWorksDraftsCell.h */,
+				BC38C4772AFA1F4B00ABFCC2 /* MineWorksDraftsCell.m */,
+				BC38C4702AFA1F4B00ABFCC2 /* MineWorksDraftsCell.xib */,
+				BC38C46F2AFA1F4B00ABFCC2 /* MineWorksNavView.h */,
+				BC38C4762AFA1F4B00ABFCC2 /* MineWorksNavView.m */,
+				BC38C4782AFA1F4B00ABFCC2 /* MineWorksNavView.xib */,
+				BC38C4712AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.h */,
+				BC38C4742AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.m */,
+				BC38C4752AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.xib */,
+			);
+			path = View;
+			sourceTree = "<group>";
+		};
 		BC41103228066C0D00800BD9 /* Homework */ = {
 			isa = PBXGroup;
 			children = (
@@ -8083,6 +8180,7 @@
 				BC4058942863028C00111BC5 /* NotiferNavView.xib in Resources */,
 				BCA353CF2858A86200377661 /* MusicRoomCourseCell.xib in Resources */,
 				275E3DFC27F46B440010EC30 /* KSBeautySettingView.xib in Resources */,
+				BC38C48B2AFA207B00ABFCC2 /* KSEmptyStatusView.xib in Resources */,
 				BC48C3B5282931C000EE65C5 /* ReceiveEvaluateCell.xib in Resources */,
 				2779335627E316DD0010E277 /* WMPlayer.bundle in Resources */,
 				BC71DF0A2A89F470003F165E /* MainToolButton.xib in Resources */,
@@ -8123,6 +8221,7 @@
 				BC71D1EC2887FDD40010F14B /* img_0.png in Resources */,
 				BC71D1EA2887FDD40010F14B /* img_10.png in Resources */,
 				BC14E4972AB3105F000C4983 /* TenantCreateGroupBodyView.xib in Resources */,
+				BC38C47F2AFA1F4B00ABFCC2 /* MineWorksDraftsCell.xib in Resources */,
 				BC71D2052887FDD40010F14B /* img_27.png in Resources */,
 				BC542E3828406F8000633781 /* UserAuthBodyView.xib in Resources */,
 				27A54CEE27E9B986007309A3 /* ModifyNameBodyView.xib in Resources */,
@@ -8203,6 +8302,7 @@
 				BC71DEF32A89F470003F165E /* TXChatBottomView.xib in Resources */,
 				BC71D2072887FDD40010F14B /* img_22.png in Resources */,
 				277D433127E9A50800107DB7 /* PhoneCheckBodyView.xib in Resources */,
+				BC38C4842AFA1F4B00ABFCC2 /* MineWorksNavView.xib in Resources */,
 				BC71DEFF2A89F470003F165E /* TXMainEmtpyView.xib in Resources */,
 				BC71D2082887FDD40010F14B /* img_20.png in Resources */,
 				BC7705FF287676DC003EFA7F /* HomeActionView.xib in Resources */,
@@ -8300,6 +8400,7 @@
 				BC38C4292AF900E100ABFCC2 /* KSAudioAnimationView.xib in Resources */,
 				BC221FBB28C8687D00F99802 /* MusicSortView.xib in Resources */,
 				BC8B6E522856ED0600866917 /* UMCommonLog.bundle in Resources */,
+				BC38C4872AFA1F4B00ABFCC2 /* MineWorksBottomView.xib in Resources */,
 				BCA353EA2859A6FB00377661 /* MusicRoomHomeworkCell.xib in Resources */,
 				2755C07127EC7F21007D9070 /* ChatComplainBodyView.xib in Resources */,
 				BC1365C9280D476500EB03E2 /* NotiferMessageCell.xib in Resources */,
@@ -8342,6 +8443,7 @@
 				BC14A61928A0B04A0086395C /* MineBottomView.xib in Resources */,
 				BC8B6E5D2856ED0600866917 /* README.txt in Resources */,
 				BC38C4242AF900E100ABFCC2 /* KSNewAlertView.xib in Resources */,
+				BC38C4812AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.xib in Resources */,
 				BC7CFFBB2817E9FC00CAEB21 /* stacked_line_chart.html in Resources */,
 				BCC583FE28A9FA8100BAB4CF /* cloud_animation_24.png in Resources */,
 				27A54CFE27E9BDC5007309A3 /* AboutUsBodyView.xib in Resources */,
@@ -8740,6 +8842,7 @@
 				BC02BCEB28B324FE005CB483 /* LiveMemberSeatCell.m in Sources */,
 				BCA9CE2E27FD8A9200D558C6 /* AccompanyNavView.m in Sources */,
 				BCC9F44727F69BD200647449 /* ClassSongMessage.m in Sources */,
+				BC38C4802AFA1F4B00ABFCC2 /* MineWorksOpenDisplayCell.m in Sources */,
 				2728086A27E6C12000DB71EA /* FirstSettingBodyView.m in Sources */,
 				275FA1A827E7327500CFEA2E /* KSWebSocketManager.m in Sources */,
 				2779362627E339D20010E277 /* KSTouchCapturingWindow.m in Sources */,
@@ -8778,6 +8881,7 @@
 				277931FA27E30FC20010E277 /* CALayer+Layout.m in Sources */,
 				BC48C3B4282931C000EE65C5 /* ReceiveEvaluateCell.m in Sources */,
 				BC0A22C528475E060065C1AB /* SongListViewController.m in Sources */,
+				BC38C47D2AFA1F4B00ABFCC2 /* MineWorksViewController.m in Sources */,
 				BC71DF1B2A89F470003F165E /* IACircularSlider.m in Sources */,
 				BCE6A09A27F83E8E00C97704 /* MinePageVideoCell.m in Sources */,
 				BC106B752A8F4586000759A9 /* TXLiveMessageChatBan.m in Sources */,
@@ -8921,6 +9025,7 @@
 				BC71DEFD2A89F470003F165E /* TXClassroomMainContainer.m in Sources */,
 				BC7663092827C95200C91A1D /* KSUploadManager.m in Sources */,
 				BC3ACD972890D61400060E97 /* NoRecordViewController.m in Sources */,
+				BC38C4862AFA1F4B00ABFCC2 /* MineWorksBottomView.m in Sources */,
 				BC4BCE7A2823AB6500522C8B /* KSAddressPickerView.m in Sources */,
 				BCC9F42727F69BD200647449 /* KSWhiteboardControl.m in Sources */,
 				BC000D8A2A848468006C5A89 /* KSChatConversationViewController.m in Sources */,
@@ -9026,6 +9131,7 @@
 				2779320627E30FC30010E277 /* UIView+ValueAdd.m in Sources */,
 				BCA9CE1527FD339400D558C6 /* AuthDisplayView.m in Sources */,
 				2779329B27E30FEB0010E277 /* UIView+MSSLayout.m in Sources */,
+				BC38C4822AFA1F4B00ABFCC2 /* MineWorksNavView.m in Sources */,
 				2779322B27E30FC30010E277 /* ALCalendarConfig.m in Sources */,
 				BC5E4B18291E5E26001BBCD2 /* WidgetViewController.m in Sources */,
 				BC1365BB280D162400EB03E2 /* MyVideoSearchView.m in Sources */,
@@ -9081,6 +9187,7 @@
 				277D432227E99EAC00107DB7 /* VeriCheckView.m in Sources */,
 				277931E927E30FC20010E277 /* pinyin.c in Sources */,
 				275FA55827F30AE300EB6240 /* VideoCourseModel.m in Sources */,
+				BC38C47C2AFA1F4B00ABFCC2 /* KSDraftMergeViewController.m in Sources */,
 				275B172927EB26920081FDEF /* ChatAddressHeaderView.m in Sources */,
 				BC5E4B1F291E5E26001BBCD2 /* KSGaugeView.m in Sources */,
 				BC7CFFA22817D72200CAEB21 /* IncomeListModel.m in Sources */,
@@ -9119,6 +9226,7 @@
 				BC6BEAA4288A4C2A00022109 /* KSHomeButton.m in Sources */,
 				27A2F63027E70E57009E2380 /* UserInfo.m in Sources */,
 				BCEA751A2818D59300886A86 /* BankNameModel.m in Sources */,
+				BC38C48F2AFA20AB00ABFCC2 /* KSNewGifRefreshFooter.m in Sources */,
 				BC02BCE428B324C9005CB483 /* LiveApplyControlView.m in Sources */,
 				BC56C96A2923736200AF301F /* KSHudLoagingManager.m in Sources */,
 				BC8A2CF828476C3000122BBE /* MusicScoreViewController.m in Sources */,
@@ -9171,6 +9279,7 @@
 				2779326427E30FD80010E277 /* FSCalendarDelegationProxy.m in Sources */,
 				BC106B852A8F4586000759A9 /* TXLiveMessageCardMessage.m in Sources */,
 				277935DF27E326DA0010E277 /* KSNetTypeManager.m in Sources */,
+				BC38C4852AFA1F4B00ABFCC2 /* MineWorksBodyView.m in Sources */,
 				2755C08527ED5770007D9070 /* GroupApplyMemberCell.m in Sources */,
 				27A54CEC27E9B96F007309A3 /* ModifyNameBodyView.m in Sources */,
 				BC9070A728C71C8700237958 /* MyCreateGroupHeadView.m in Sources */,
@@ -9189,7 +9298,9 @@
 				BCB908F72850C6EF00F5FF69 /* MusicChooseCell.m in Sources */,
 				277932BA27E30FFE0010E277 /* TAPageControl.m in Sources */,
 				BCB633F627F6A18200ACFDCF /* LocalRenderManager.m in Sources */,
+				BC38C47E2AFA1F4B00ABFCC2 /* UserMusicFormalModel.m in Sources */,
 				2779329127E30FEB0010E277 /* MSSBrowseModel.m in Sources */,
+				BC38C4832AFA1F4B00ABFCC2 /* MineWorksDraftsCell.m in Sources */,
 				277931E227E30FC20010E277 /* UIViewController+zhStatusBarStyle.m in Sources */,
 				BC71DF0B2A89F470003F165E /* TXMainToolView.m in Sources */,
 				275E3DFA27F46B340010EC30 /* KSBeautySettingView.m in Sources */,
@@ -9305,6 +9416,7 @@
 				275E3DE427F467410010EC30 /* KSChatInputBarControl.m in Sources */,
 				BC2456F7286C421700D1F7C0 /* KSVideoRecordManager.m in Sources */,
 				BC71DF102A89F470003F165E /* KSMetronomeControlView.m in Sources */,
+				BC38C48C2AFA207B00ABFCC2 /* KSEmptyStatusView.m in Sources */,
 				BCC03F9E280579A500461B7C /* MyLiveCourseCell.m in Sources */,
 				27D5D5D527EDBCB900B4720C /* GroupNoticeModel.m in Sources */,
 				BC5E4B2F291E5E26001BBCD2 /* WidgetFunctionView.m in Sources */,

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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/choose_status.imageset/choose_status@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/choose_status.imageset/choose_status@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mineWorks_bg.imageset/mineWorks_bg@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mineWorks_bg.imageset/mineWorks_bg@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_musicProduct.imageset/mine_musicProduct@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_musicProduct.imageset/mine_musicProduct@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_worksTitle.imageset/mine_worksTitle@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/mine_worksTitle.imageset/mine_worksTitle@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_edit.imageset/product_edit@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_edit.imageset/product_edit@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_like.imageset/product_like@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_like.imageset/product_like@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_play.imageset/product_play@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/product_play.imageset/product_play@3x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/slider_bubble.imageset/slider_bubble@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/slider_bubble.imageset/slider_bubble@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/sure_delete_image.imageset/sure_delete_image@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/sure_delete_image.imageset/sure_delete_image@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/time_grey.imageset/time_grey@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/time_grey.imageset/time_grey@3x.png


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

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

BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/unChoose_status.imageset/unChoose_status@2x.png


BIN
KulexiuForTeacher/KulexiuForTeacher/Assets.xcassets/PlayerImage/unChoose_status.imageset/unChoose_status@3x.png


+ 53 - 1
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSBaseWKWebViewController.m

@@ -66,6 +66,7 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
 
 @property (nonatomic, strong) KSWebLoadRefreshView *errorView;
 
+@property (nonatomic, strong) KSUMShareManager *shareManager;
 
 @end
 
@@ -604,6 +605,9 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
         NSString *type = [[parm ks_dictionaryValueForKey:@"content"] ks_stringValueForKey:@"type"];
         [USER_MANAGER sendUMEvent:type];
     }
+    else if ([[parm ks_stringValueForKey:@"api"] isEqualToString:@"shareTripartite"]) { // 分享到微信
+        [self shareToWeChat:parm];
+    }
 }
 
 
@@ -723,6 +727,7 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
             break;
         }
     }
+    MJWeakSelf;
     [KSUMShareManager shareInstanceShowWithImage:shareImage showSaveLink:containCopyButton saveLinkUrl:saveLinkUrl url:videoUrl shareTitle:shareTitle descMessage:descMessage shareType:shareType showInView:self callback:^(BOOL isSuccess, NSString * _Nonnull descMessage) {
         NSMutableDictionary *responParm = [NSMutableDictionary dictionary];
         [responParm setValue:[parm ks_stringValueForKey:@"api"] forKey:@"api"];
@@ -732,10 +737,57 @@ typedef NS_ENUM(NSInteger, CHOOSETYPE) {
         BOOL status = isSuccess;
         [content setValue:[NSNumber numberWithBool:status] forKey:@"status"];
         [responParm setValue:content forKey:@"content"];
-        [self postMessage:responParm];
+        [weakSelf postMessage:responParm];
     }];
 }
 
+- (void)shareToWeChat:(NSDictionary *)parm {
+    
+    NSDictionary *content = [parm ks_dictionaryValueForKey:@"content"];
+    if ([[content ks_stringValueForKey:@"shareType"] isEqualToString:@"wechat"]) {
+        NSString *typeString = [content ks_stringValueForKey:@"type"];
+        KSSHARETYPE shareType = [typeString isEqualToString:@"image"] ? KSSHARETYPE_IMAGE : KSSHARETYPE_VODEO;
+        NSString *shareTitle = [content ks_stringValueForKey:@"title"];
+        NSString *descMessage = [content ks_stringValueForKey:@"desc"];
+        NSString *videoUrl = [content ks_stringValueForKey:@"video"];
+        NSString *imgStr = [content ks_stringValueForKey:@"image"];
+        UIImage *shareImage = [self imageWithBase64String:imgStr];
+        MJWeakSelf;
+        self.shareManager = [KSUMShareManager shareInstanceToWechatWithImage:shareImage url:videoUrl shareTitle:shareTitle descMessage:descMessage shareType:shareType callback:^(BOOL isSuccess, NSString * _Nonnull descMessage) {
+            NSMutableDictionary *responParm = [NSMutableDictionary dictionary];
+            [responParm setValue:[parm ks_stringValueForKey:@"api"] forKey:@"api"];
+            NSMutableDictionary *content = [NSMutableDictionary dictionary];
+            [content setValue:[content ks_stringValueForKey:@"UUID"] forKey:@"content"];
+            [content setValue:descMessage forKey:@"message"];
+            BOOL status = isSuccess;
+            [content setValue:[NSNumber numberWithBool:status] forKey:@"status"];
+            [responParm setValue:content forKey:@"content"];
+            [weakSelf postMessage:responParm];
+        }];
+    }
+    else if ([[content ks_stringValueForKey:@"shareType"] isEqualToString:@"wechat_circle"]) { // 微信朋友圈
+        NSString *typeString = [content ks_stringValueForKey:@"type"];
+        KSSHARETYPE shareType = [typeString isEqualToString:@"image"] ? KSSHARETYPE_IMAGE : KSSHARETYPE_VODEO;
+        NSString *shareTitle = [content ks_stringValueForKey:@"title"];
+        NSString *descMessage = [content ks_stringValueForKey:@"desc"];
+        NSString *videoUrl = [content ks_stringValueForKey:@"video"];
+        NSString *imgStr = [content ks_stringValueForKey:@"image"];
+        UIImage *shareImage = [self imageWithBase64String:imgStr];
+        MJWeakSelf;
+        self.shareManager = [KSUMShareManager shareInstanceToWechatCircleWithImage:shareImage url:videoUrl shareTitle:shareTitle descMessage:descMessage shareType:shareType callback:^(BOOL isSuccess, NSString * _Nonnull descMessage) {
+            NSMutableDictionary *responParm = [NSMutableDictionary dictionary];
+            [responParm setValue:[parm ks_stringValueForKey:@"api"] forKey:@"api"];
+            NSMutableDictionary *content = [NSMutableDictionary dictionary];
+            [content setValue:[content ks_stringValueForKey:@"UUID"] forKey:@"content"];
+            [content setValue:descMessage forKey:@"message"];
+            BOOL status = isSuccess;
+            [content setValue:[NSNumber numberWithBool:status] forKey:@"status"];
+            [responParm setValue:content forKey:@"content"];
+            [weakSelf postMessage:responParm];
+        }];
+    }
+}
+
 - (void)showAlertWithMessage:(NSString *)message type:(CHECKDEVICETYPE)deviceType {
     [KSPremissionAlert shareInstanceDisplayImage:deviceType message:message showInView:self.view cancel:^{
         

+ 20 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSEmptyStatusView.h

@@ -0,0 +1,20 @@
+//
+//  KSEmptyStatusView.h
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2023/2/24.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSEmptyStatusView : UIView
+
++ (instancetype)shareInstance;
+
+- (void)configImageName:(NSString *)imageName desc:(NSString *)desc topHeight:(NSInteger)topHeight;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 40 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSEmptyStatusView.m

@@ -0,0 +1,40 @@
+//
+//  KSEmptyStatusView.m
+//  GuanYueTeamTeacher
+//
+//  Created by 王智 on 2023/2/24.
+//
+
+#import "KSEmptyStatusView.h"
+
+@interface KSEmptyStatusView ()
+
+@property (weak, nonatomic) IBOutlet UIImageView *emptyImage;
+
+@property (weak, nonatomic) IBOutlet UILabel *descLabel;
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topSpace;
+
+@end
+
+@implementation KSEmptyStatusView
+
++ (instancetype)shareInstance {
+    KSEmptyStatusView *view = [[[NSBundle mainBundle] loadNibNamed:@"KSEmptyStatusView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)configImageName:(NSString *)imageName desc:(NSString *)desc topHeight:(NSInteger)topHeight {
+    [self.emptyImage setImage:[UIImage imageNamed:imageName]];
+    self.descLabel.text = desc;
+    self.topSpace.constant = topHeight;
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 51 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSEmptyStatusView.xib

@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
+        <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="KSEmptyStatusView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="647"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="wd_img_zwsj" translatesAutoresizingMaskIntoConstraints="NO" id="iYg-CM-bcg">
+                    <rect key="frame" x="66.666666666666686" y="134" width="260" height="230"/>
+                </imageView>
+                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="暂无作业" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wxy-hZ-W0O">
+                    <rect key="frame" x="66.666666666666686" y="382" width="260" height="18"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="18" id="03B-Ph-DqR"/>
+                    </constraints>
+                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                    <color key="textColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
+                    <nil key="highlightedColor"/>
+                </label>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstItem="Wxy-hZ-W0O" firstAttribute="top" secondItem="iYg-CM-bcg" secondAttribute="bottom" constant="18" id="E3z-mn-IAc"/>
+                <constraint firstItem="Wxy-hZ-W0O" firstAttribute="trailing" secondItem="iYg-CM-bcg" secondAttribute="trailing" id="KcT-37-U8Q"/>
+                <constraint firstItem="iYg-CM-bcg" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="TaD-Bh-qmZ"/>
+                <constraint firstItem="Wxy-hZ-W0O" firstAttribute="leading" secondItem="iYg-CM-bcg" secondAttribute="leading" id="dWe-0D-Eev"/>
+                <constraint firstItem="iYg-CM-bcg" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="134" id="ky9-kf-Dxw"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="descLabel" destination="Wxy-hZ-W0O" id="fvT-us-Pxc"/>
+                <outlet property="emptyImage" destination="iYg-CM-bcg" id="vty-o4-F7c"/>
+                <outlet property="topSpace" destination="ky9-kf-Dxw" id="QX8-B2-RgF"/>
+            </connections>
+            <point key="canvasLocation" x="78.625954198473281" y="21.47887323943662"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="wd_img_zwsj" width="260" height="230"/>
+    </resources>
+</document>

+ 3 - 3
KulexiuForTeacher/KulexiuForTeacher/Common/Base/KSNetworkingManager.m

@@ -2656,7 +2656,7 @@
 /// @param faliure 失败
 + (void)saveMusicMessage:(NSString *)post jsonConfig:(NSString *)jsonConfig img:(NSString *)img videoUrl:(NSString *)videoUrl accompanyUrl:(NSString *)accompanyUrl desc:(NSString *)desc type:(NSString *)type musicPracticeRecordId:(NSString *)musicPracticeRecordId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     [self configRequestMethodJSON];
-    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"api-teacher/userMusic/save"];
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-teacher/userMusic/save"];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
     [parm setValue:jsonConfig forKey:@"jsonConfig"];
     [parm setValue:img forKey:@"img"];
@@ -2680,7 +2680,7 @@
 /// @param faliure 失败
 + (void)userMusicPageRequest:(NSString *)post type:(NSString *)type page:(NSInteger)page rows:(NSInteger)rows success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     [self configRequestMethodJSON];
-    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"api-teacher/userMusic/page"];
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-teacher/userMusic/page"];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
     [parm setValue:@(page) forKey:@"page"];
     [parm setValue:@(rows) forKey:@"rows"];
@@ -2697,7 +2697,7 @@
 /// @param faliure 失败
 + (void)userMusicRemoveRequest:(NSString *)post musicId:(NSString *)musicId success:(void(^)(NSDictionary *dic))success faliure:(void(^)(NSError *error))faliure {
     [self configRequestMethodForm];
-    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"api-teacher/userMusic/remove"];
+    NSString *url = [NSString stringWithFormat:@"%@%@", hostURL, @"/api-teacher/userMusic/remove"];
     NSMutableDictionary *parm = [NSMutableDictionary dictionary];
     [parm setValue:musicId forKey:@"id"];
     [self request:post andWithUrl:url and:parm success:success faliure:faliure];

+ 18 - 18
KulexiuForTeacher/KulexiuForTeacher/Common/Define/KSDomain.h

@@ -13,15 +13,15 @@
 //#ifdef DEBUG
 
 // 开发环境
-//#define hostURL (@"https://dev.colexiu.com")
-//#define SEALCLASSHOST (@"https://dev.colexiu.com/api-classroom")
-//#define WEBHOST (@"https://dev.colexiu.com/teacher")
-//#define SOCKET_URL (@"wss://dev.colexiu.com/audioAnalysis")
-//#define JSPUSH_ENVIRONMENT (NO)
-//#define RCIM_KEY (@"0vnjpoad0jbdz")
-//#define SUBMIT_UUID (NO)
-//#define CONFIG_TXSDKAPPID (1400805079)
-//#define TXOfflinePushCertificateIDForAPNS (39559)
+#define hostURL (@"https://dev.colexiu.com")
+#define SEALCLASSHOST (@"https://dev.colexiu.com/api-classroom")
+#define WEBHOST (@"https://dev.colexiu.com/teacher")
+#define SOCKET_URL (@"wss://dev.colexiu.com/audioAnalysis")
+#define JSPUSH_ENVIRONMENT (NO)
+#define RCIM_KEY (@"0vnjpoad0jbdz")
+#define SUBMIT_UUID (NO)
+#define CONFIG_TXSDKAPPID (1400805079)
+#define TXOfflinePushCertificateIDForAPNS (39559)
 
 // 测试环境
 //#define hostURL (@"https://test.colexiu.com")
@@ -47,15 +47,15 @@
 
 //#else
 
-#define hostURL (@"https://online.colexiu.com")
-#define SEALCLASSHOST (@"https://online.colexiu.com/api-classroom")
-#define WEBHOST (@"https://online.colexiu.com/teacher")
-#define SOCKET_URL (@"wss://online.colexiu.com/audioAnalysis")
-#define JSPUSH_ENVIRONMENT (YES)
-#define RCIM_KEY (@"e5t4ouvpe42pa")
-#define SUBMIT_UUID (YES)
-#define CONFIG_TXSDKAPPID (1400799837)
-#define TXOfflinePushCertificateIDForAPNS (39561)
+//#define hostURL (@"https://online.colexiu.com")
+//#define SEALCLASSHOST (@"https://online.colexiu.com/api-classroom")
+//#define WEBHOST (@"https://online.colexiu.com/teacher")
+//#define SOCKET_URL (@"wss://online.colexiu.com/audioAnalysis")
+//#define JSPUSH_ENVIRONMENT (YES)
+//#define RCIM_KEY (@"e5t4ouvpe42pa")
+//#define SUBMIT_UUID (YES)
+//#define CONFIG_TXSDKAPPID (1400799837)
+//#define TXOfflinePushCertificateIDForAPNS (39561)
 
 //#endif
 

+ 13 - 4
KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/AudioMerge/KSMediaMergeView.m

@@ -671,10 +671,19 @@
             [self saveMusic:YES isFormal:NO fileUrl:self.remoteVideoUrl needBack:needBack];
         }
         else {
-            MJWeakSelf;
-            [self saveVideoURLToAsset:self.videoUrl isFormal:NO callback:^(NSString *videoUrl) {
-                // 保存草稿
-                [weakSelf saveMusic:YES isFormal:NO fileUrl:videoUrl needBack:needBack];
+            [LOADING_MANAGER showCustomLoading:@"正在上传草稿"];
+            [KSMediaEditor mixRecordVideoWithAudio:self.recordUrl recordVolume:1 videoUrlStr:self.videoUrl completion:^(NSString * _Nonnull outPath, BOOL isSuccess, NSString * _Nonnull desc) {
+                if (isSuccess) {
+                    MJWeakSelf;
+                    [self saveVideoToAsset:outPath isFormal:NO callback:^(NSString *videoUrl) {
+                        // 保存草稿
+                        [weakSelf saveMusic:YES isFormal:NO fileUrl:videoUrl needBack:needBack];
+                    }];
+                }
+                else {
+                    [LOADING_MANAGER removeCustomLoading];
+
+                }
             }];
         }
     }

+ 0 - 3
KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/AudioMerge/MusicPublistAlert.m

@@ -25,9 +25,6 @@
 - (void)awakeFromNib {
     [super awakeFromNib];
     self.textView.delegate = self;
-    
-    CAGradientLayer *titleLayer = [UIView createGradientLayerFromColor:HexRGB(0x44C9FF) startPoint:CGPointMake(0, 0.5) endColor:HexRGB(0x259CFE) endPoint:CGPointMake(1, 0.5) bounds:CGRectMake(0, 0, 220, 38)];
-    [self.sureButton.layer addSublayer:titleLayer];
     self.backView.layer.cornerRadius = 4;
     self.backView.layer.maskedCorners = kCALayerMinXMaxYCorner | kCALayerMaxXMaxYCorner;
 }

+ 14 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/MediaEditor/KSMediaEditor.h

@@ -45,6 +45,20 @@ NS_ASSUME_NONNULL_BEGIN
                     videoUrlStr:(NSURL *)videoUrl
                      completion:(void (^)(NSString *outPath,BOOL isSuccess, NSString *desc))completionHandle;
 
+
+
+
+
+/// 视频合成,设置录音文件
+/// - Parameters:
+///   - recordUrl: 录制文件地址
+///   - recordVolume: 录制文件音量 0-1
+///   - videoUrl: 视频地址
+///   - completionHandle: 完成回调
++ (void)mixRecordVideoWithAudio:(NSURL *)recordUrl
+                   recordVolume:(float)recordVolume
+                    videoUrlStr:(NSURL *)videoUrl
+                     completion:(void (^)(NSString *outPath,BOOL isSuccess, NSString *desc))completionHandle;
 @end
 
 NS_ASSUME_NONNULL_END

+ 66 - 3
KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/MediaEditor/KSMediaEditor.m

@@ -11,6 +11,8 @@
 
 @implementation KSMediaEditor
 
+
+
 /// 音频合成,录音文件添加伴奏
 /// - Parameters:
 ///   - recordUrl: 录制文件地址
@@ -47,9 +49,7 @@
     AVMutableCompositionTrack *bgAudioCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
     
     CMTime offsetCTTime = CMTimeMake(labs(offsetTime), 1000);
-    
-    CMTime duration = recordDuration > bgAudioDuration ? bgAudioAssest.duration : recordAsset.duration;
-    
+        
     
     AVAssetTrack *recordAssetTrack = [[recordAsset tracksWithMediaType:AVMediaTypeAudio] firstObject];
     AVAssetTrack *bgAudioAssetTrack = [[bgAudioAssest tracksWithMediaType:AVMediaTypeAudio] firstObject];
@@ -250,6 +250,69 @@
     
 }
 
+/// 视频合成,设置录音文件
+/// - Parameters:
+///   - recordUrl: 录制文件地址
+///   - recordVolume: 录制文件音量 0-1
+///   - videoUrl: 视频地址
+///   - completionHandle: 完成回调
++ (void)mixRecordVideoWithAudio:(NSURL *)recordUrl
+                   recordVolume:(float)recordVolume
+                    videoUrlStr:(NSURL *)videoUrl
+                     completion:(void (^)(NSString *outPath,BOOL isSuccess, NSString *desc))completionHandle {
+    if (recordUrl == nil) {
+        completionHandle(nil, NO, @"未找到录音文件");
+        return;
+    }
+    
+    //创建可变的音频视频组合
+    AVMutableComposition *mixComposition = [AVMutableComposition composition];
+    //视频采集
+    AVURLAsset* videoAsset =[[AVURLAsset alloc]initWithURL:videoUrl options:nil];
+    CMTimeRange video_timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration);
+    // 视频时长
+    float videoDuration = CMTimeGetSeconds(videoAsset.duration);
+    AVMutableCompositionTrack *a_compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo preferredTrackID:kCMPersistentTrackID_Invalid];
+    [a_compositionVideoTrack insertTimeRange:video_timeRange
+                                     ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
+                                      atTime:kCMTimeZero
+                                       error:nil];
+    
+    // 视频需要专设置transform
+    CGAffineTransform videoTransform = [[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0].preferredTransform;
+    [a_compositionVideoTrack setPreferredTransform:videoTransform];
+    
+    //创建最终混合的音频实例
+    AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
+    
+    // 录音
+    AVURLAsset *recordAsset = [AVURLAsset assetWithURL:recordUrl];
+    float recordDuration = CMTimeGetSeconds(recordAsset.duration);
+    // 音频轨道
+    AVMutableCompositionTrack *recordCompositionTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio preferredTrackID:kCMPersistentTrackID_Invalid];
+    
+    // 合成
+    AVAssetTrack *recordAssetTrack = [[recordAsset tracksWithMediaType:AVMediaTypeAudio] firstObject];
+    // 录音文件
+    [recordCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, recordAsset.duration) ofTrack:recordAssetTrack atTime:kCMTimeZero error:nil];
+    // 如果时长超过视频的时长
+    CMTime duration = recordDuration > videoDuration ? recordAsset.duration : videoAsset.duration;
+    if (recordDuration > videoDuration) {
+        duration = videoAsset.duration;
+    }
+    
+    [recordCompositionTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, duration) ofTrack:recordAssetTrack atTime:kCMTimeZero error:nil];
+    
+    AVMutableAudioMixInputParameters *newRecordInputParams = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:recordCompositionTrack];
+    [newRecordInputParams setTrackID:recordCompositionTrack.trackID];
+    [newRecordInputParams setVolume:recordVolume atTime:kCMTimeZero];
+    audioMix.inputParameters = [NSArray arrayWithObjects:newRecordInputParams,nil];
+    //导出
+    [self sessionExportAction:mixComposition outputPath:[self getVideoOutputPath] presetName:AVAssetExportPresetMediumQuality outputFileType:AVFileTypeQuickTimeMovie audioMix:audioMix completion:^(NSString *outPath, BOOL isSuccess, NSString *desc) {
+        completionHandle(outPath, isSuccess, desc);
+    }];
+}
+
 + (NSString *)getVideoOutputPath {
     NSString *documentsDirectory =[NSHomeDirectory()
                                    stringByAppendingPathComponent:@"Documents"];

+ 16 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Tools/GifRefresh/KSNewGifRefreshFooter.h

@@ -0,0 +1,16 @@
+//
+//  KSNewGifRefreshFooter.h
+//  GuanYueTeam
+//
+//  Created by 王智 on 2023/4/20.
+//
+
+#import "MJRefreshBackGifFooter.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSNewGifRefreshFooter : MJRefreshBackGifFooter
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 150 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Tools/GifRefresh/KSNewGifRefreshFooter.m

@@ -0,0 +1,150 @@
+//
+//  KSNewGifRefreshFooter.m
+//  GuanYueTeam
+//
+//  Created by 王智 on 2023/4/20.
+//
+
+#import "KSNewGifRefreshFooter.h"
+#import <Lottie/Lottie.h>
+
+@interface KSNewGifRefreshFooter ()
+
+@property(nonatomic, strong) LOTAnimationView *loadingView;
+@property(nonatomic, strong) NSString *jsonString;
+
+@end
+
+@implementation KSNewGifRefreshFooter
+- (instancetype)init {
+    if (self = [super init]) {
+        [self setJsonName:@"refresh_bottom.json"];
+        self.stateLabel.textColor = HexRGB(0x777777);
+//        self.stateLabel.font = [UIFont systemFontOfSize:12.0f];
+    }
+    return self;
+}
+
+- (void)setJsonName:(NSString *)jsonName {
+    self.jsonString = jsonName;
+    [self addSubview:self.loadingView];
+    [self.loadingView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.right.mas_equalTo(self.gifView.mas_right).offset(5);
+        make.centerY.mas_equalTo(self.stateLabel.mas_centerY);
+        make.width.height.mas_equalTo(20);
+    }];
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    if (self.gifView.constraints.count) return;
+    
+    self.gifView.frame = self.bounds;
+    if (self.stateLabel.hidden) {
+        self.gifView.contentMode = UIViewContentModeCenter;
+    } else {
+        self.gifView.contentMode = UIViewContentModeRight;
+        self.gifView.mj_w = self.mj_w * 0.5 - self.labelLeftInset - self.stateLabel.mj_textWith * 0.5;
+    }
+}
+
+- (LOTAnimationView *)loadingView {
+    if(_loadingView == nil) {
+        //1.加载本地json
+        _loadingView = [LOTAnimationView animationNamed:self.jsonString];
+        //2.加载后台给的json(url)
+        _loadingView.loopAnimation = YES;
+        _loadingView.contentMode = UIViewContentModeScaleAspectFill;
+        _loadingView.animationSpeed = 2.0;
+        _loadingView.loopAnimation = YES;
+    }
+    return _loadingView;
+}
+
+#pragma mark - innerMethod
+- (void)endRefreshing {
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+        [super endRefreshing];
+    });
+}
+
+#pragma mark - 监听控件的刷新状态
+
+- (void)setState:(MJRefreshState)state {
+    MJRefreshCheckState;
+    if(self.jsonString.length > 0) {
+        switch (state) {
+            case MJRefreshStateIdle: //普通闲置状态
+            {
+                [self.loadingView stop];
+                self.loadingView.hidden = YES;
+                break;
+            }
+            case MJRefreshStatePulling: //松开就可以进行刷新的状态
+            {
+//                self.loadingView.hidden = NO;
+//                [self.loadingView play];
+            }
+                break;
+
+            case MJRefreshStateRefreshing: //正在刷新中的状态
+            {
+                self.loadingView.hidden = NO;
+                [self.loadingView play];
+            }
+                break;
+            case MJRefreshStateNoMoreData:
+            {
+                [self.loadingView stop];
+                self.loadingView.hidden = YES;
+            }
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+#pragma mark - 实时监听控件 scrollViewContentOffset
+
+//- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change {
+//    [super scrollViewContentOffsetDidChange:change];
+//    if(self.jsonString.length > 0) {
+//        CGPoint point;
+//        id newVelue = [change valueForKey:NSKeyValueChangeNewKey];
+//        [(NSValue *)newVelue getValue:&point];
+//
+//        //id newVelue1 = [change objectForKey:NSKeyValueChangeNewKey];
+//        //CGPoint point1 = ((NSValue *)newVelue1).CGPointValue;//可以取值
+//
+//        //id newVelue2 = [change objectForKey:@"new"];
+//        //CGPoint point2 = *((__bridge CGPoint *)(newVelue2));//无法取到值
+//
+//        self.loadingView.hidden = !(self.pullingPercent);
+//        CGFloat progress = point.y / ([UIScreen mainScreen].bounds.size.height / 3.0);
+//        if(self.state != MJRefreshStateRefreshing) {
+//            self.loadingView.animationProgress = -progress;
+//        }
+//    }
+//}
+
+- (void)prepare {
+    [super prepare];
+    // 设置控件的高度
+    // 初始化文字
+    [self setTitle:@"" forState:MJRefreshStateIdle];
+    [self setTitle:@"松开加载" forState:MJRefreshStatePulling];
+    [self setTitle:@"正在加载中..." forState:MJRefreshStateRefreshing];
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterNoMoreDataText] forState:MJRefreshStateNoMoreData];
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 3 - 0
KulexiuForTeacher/KulexiuForTeacher/Common/Tools/UMShare/KSUMShareManager.h

@@ -24,6 +24,9 @@ NS_ASSUME_NONNULL_BEGIN
 
 + (instancetype)shareInstanceShowWithImage:(UIImage *)image showSaveLink:(BOOL)showSaveLink saveLinkUrl:(NSString *)saveLinkUrl url:(NSString *)url shareTitle:(NSString *)shareTitle descMessage:(NSString *)descMessage shareType:(KSSHARETYPE)type showInView:(UIViewController *)ctrl callback:(KSShareActionCallback)callback;
 
++ (instancetype)shareInstanceToWechatWithImage:(UIImage *)image url:(NSString *)url shareTitle:(NSString *)shareTitle descMessage:(NSString *)descMessage shareType:(KSSHARETYPE)type  callback:(KSShareActionCallback)callback;
+
++ (instancetype)shareInstanceToWechatCircleWithImage:(UIImage *)image url:(NSString *)url shareTitle:(NSString *)shareTitle descMessage:(NSString *)descMessage shareType:(KSSHARETYPE)type  callback:(KSShareActionCallback)callback;
 @end
 
 NS_ASSUME_NONNULL_END

+ 169 - 23
KulexiuForTeacher/KulexiuForTeacher/Common/Tools/UMShare/KSUMShareManager.m

@@ -38,14 +38,14 @@
     return manager;
 }
 
-+ (instancetype)shareInstanceWithImage:(UIImage *)image url:(NSString *)url shareTitle:(NSString *)shareTitle descMessage:(NSString *)descMessage shareType:(KSSHARETYPE)type showInView:(UIViewController *)ctrl callback:(KSShareActionCallback)callback {
++ (instancetype)shareInstanceWithImage:(UIImage *)image url:(NSString *)url shareTitle:(NSString *)shareTitle descMessage:(NSString *)descMessage shareType:(KSSHARETYPE)type showInView:(nonnull UIViewController *)ctrl callback:(KSShareActionCallback)callback {
     KSUMShareManager *manager = [[self alloc] init];
     manager.shareType = type;
     manager.shareImage = image;
     manager.shareUrl = url;
     manager.shareTitle = shareTitle;
-    manager.displayCtrl = ctrl;
     manager.shareMessage = descMessage;
+    manager.displayCtrl = ctrl;
     if (callback) {
         manager.callback = callback;
     }
@@ -76,57 +76,54 @@
     return manager;
 }
 
-
 - (void)openShareView {
+    MJWeakSelf;
     [UMSocialUIManager setShareMenuViewDelegate:self];
-
     [UMSocialUIManager showShareMenuViewInWindowWithPlatformSelectionBlock:^(UMSocialPlatformType platformType, NSDictionary *userInfo) {
         if (platformType == UMSocialPlatformType_UserDefine_Begin+1) { // 分享到群组
-            if (self.shareType == KSSHARETYPE_IMAGE) {
+            if (weakSelf.shareType == KSSHARETYPE_IMAGE) {
                 KSImageShareViewController *shareGroupCtrl = [[KSImageShareViewController alloc] init];
                 shareGroupCtrl.shareImage = self.shareImage;
-                MJWeakSelf;
                 [shareGroupCtrl shareGroupCallback:^(BOOL isSuccess, NSString *descMsg) {
-                    __strong typeof(weakSelf) strongSelf = weakSelf;
-                    if (strongSelf.callback) {
-                        strongSelf.callback(isSuccess,descMsg);
+                    if (weakSelf.callback) {
+                        weakSelf.callback(isSuccess,descMsg);
                         [LOADING_MANAGER MBShowAUTOHidingInWindow:descMsg];
                     }
                 }];
-                [self.displayCtrl.navigationController pushViewController:shareGroupCtrl animated:YES];
+                [weakSelf.displayCtrl.navigationController pushViewController:shareGroupCtrl animated:YES];
             }
             else {
-                if (self.callback) {
-                    self.callback(NO,@"仅支持图片分享到群组");
+                if (weakSelf.callback) {
+                    weakSelf.callback(NO,@"仅支持图片分享到群组");
                     [LOADING_MANAGER MBShowAUTOHidingInWindow:@"仅支持图片分享到群组"];
                 }
             }
             
         }
-        else if (platformType == UMSocialPlatformType_UserDefine_Begin+2) { // 复制链接
+        else if (platformType == UMSocialPlatformType_UserDefine_Begin+2) { // 图片保存到相册
             UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
-            pasteboard.string = self.saveLinkUrl;
+            pasteboard.string = weakSelf.saveLinkUrl;
             [LOADING_MANAGER MBShowAUTOHidingInWindow:@"复制成功"];
         }
         else {
             //创建分享消息对象
             UMSocialMessageObject *messageObject = [UMSocialMessageObject messageObject];
             NSString *shareTitle = @"";
-            if (![NSString isEmptyString:self.shareTitle]) {
-                shareTitle = self.shareTitle;
+            if (![NSString isEmptyString:weakSelf.shareTitle]) {
+                shareTitle = weakSelf.shareTitle;
             }
             NSString *descMessage = @"";
-            if (self.shareMessage) {
+            if (weakSelf.shareMessage) {
                 descMessage = self.shareMessage;
             }
             // 创建分享对象
-            if (self.shareType == KSSHARETYPE_IMAGE) {
+            if (weakSelf.shareType == KSSHARETYPE_IMAGE) {
                 UMShareImageObject *shareObj = [UMShareImageObject shareObjectWithTitle:shareTitle descr:descMessage thumImage:[UIImage imageNamed:@"shareImage"]];
                 shareObj.shareImage = self.shareImage;
                 //分享消息对象设置分享内容对象
                 messageObject.shareObject = shareObj;
             }
-            else if (self.shareType == KSSHARETYPE_VODEO) {
+            else if (weakSelf.shareType == KSSHARETYPE_VODEO) {
                 UMShareWebpageObject *shareObj = [UMShareWebpageObject shareObjectWithTitle:shareTitle descr:descMessage thumImage:[UIImage imageNamed:@"shareImage"]];
                 //            NSString *shareUrl = [self.shareUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
                 shareObj.webpageUrl = self.shareUrl;
@@ -137,8 +134,8 @@
             [[UMSocialManager defaultManager] shareToPlatform:platformType messageObject:messageObject currentViewController:nil completion:^(id data, NSError *error) {
                 if (error) {
                     NSLog(@"************分享失败 %@*********",error);
-                    if (self.callback) {
-                        self.callback(NO, @"分享失败");
+                    if (weakSelf.callback) {
+                        weakSelf.callback(NO, @"分享失败");
                         [LOADING_MANAGER MBShowAUTOHidingInWindow:@"分享失败"];
                     }
                 }else{
@@ -146,8 +143,8 @@
                         UMSocialShareResponse *resp = data;
                         //分享结果消息
                         NSLog(@"************分享成功 %@*********",resp.message);
-                        if (self.callback) {
-                            self.callback(YES,@"分享成功");
+                        if (weakSelf.callback) {
+                            weakSelf.callback(YES,@"分享成功");
                             [LOADING_MANAGER MBShowAUTOHidingInWindow:@"分享成功"];
                         }
                     }else{
@@ -160,7 +157,156 @@
     }];
 }
 
+
 - (UIView*)UMSocialParentView:(UIView*)defaultSuperView {
     return [NSObject getKeyWindow];
 }
+
++ (instancetype)shareInstanceToWechatWithImage:(UIImage *)image url:(NSString *)url shareTitle:(NSString *)shareTitle descMessage:(NSString *)descMessage shareType:(KSSHARETYPE)type  callback:(KSShareActionCallback)callback {
+    KSUMShareManager *manager = [[self alloc] init];
+    manager.shareType = type;
+    manager.shareImage = image;
+    manager.shareUrl = url;
+    manager.shareTitle = shareTitle;
+    manager.shareMessage = descMessage;
+    if (callback) {
+        manager.callback = callback;
+    }
+    [manager shareWechat];
+    return manager;
+}
+
++ (instancetype)shareInstanceToWechatCircleWithImage:(UIImage *)image url:(NSString *)url shareTitle:(NSString *)shareTitle descMessage:(NSString *)descMessage shareType:(KSSHARETYPE)type  callback:(KSShareActionCallback)callback {
+    KSUMShareManager *manager = [[self alloc] init];
+    manager.shareType = type;
+    manager.shareImage = image;
+    manager.shareUrl = url;
+    manager.shareTitle = shareTitle;
+    manager.shareMessage = descMessage;
+    if (callback) {
+        manager.callback = callback;
+    }
+    [manager shareWechatCircle];
+    return manager;
+}
+
+- (void)shareWechat {
+    
+    if (![[UMSocialManager defaultManager] isInstall:UMSocialPlatformType_WechatSession]) {
+        if (self.callback) {
+            self.callback(NO, @"请安装微信");
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:@"请安装微信"];
+        }
+        return;
+    }
+    
+    //创建分享消息对象
+    UMSocialMessageObject *messageObject = [UMSocialMessageObject messageObject];
+    NSString *shareTitle = @"";
+    if (![NSString isEmptyString:self.shareTitle]) {
+        shareTitle = self.shareTitle;
+    }
+    NSString *descMessage = @"";
+    if (self.shareMessage) {
+        descMessage = self.shareMessage;
+    }
+    // 创建分享对象
+    if (self.shareType == KSSHARETYPE_IMAGE) {
+        UMShareImageObject *shareObj = [UMShareImageObject shareObjectWithTitle:shareTitle descr:descMessage thumImage:[UIImage imageNamed:@"shareImage"]];
+        shareObj.shareImage = self.shareImage;
+        //分享消息对象设置分享内容对象
+        messageObject.shareObject = shareObj;
+    }
+    else if (self.shareType == KSSHARETYPE_VODEO) {
+        UMShareWebpageObject *shareObj = [UMShareWebpageObject shareObjectWithTitle:shareTitle descr:descMessage thumImage:[UIImage imageNamed:@"shareImage"]];
+        //            NSString *shareUrl = [self.shareUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
+        shareObj.webpageUrl = self.shareUrl;
+        //分享消息对象设置分享内容对象
+        messageObject.shareObject = shareObj;
+    }
+    MJWeakSelf;
+    //调用分享接口
+    [[UMSocialManager defaultManager] shareToPlatform:UMSocialPlatformType_WechatSession messageObject:messageObject currentViewController:nil completion:^(id data, NSError *error) {
+        if (error) {
+            NSLog(@"************分享失败 %@*********",error);
+            if (weakSelf.callback) {
+                weakSelf.callback(NO, @"分享失败");
+                [LOADING_MANAGER MBShowAUTOHidingInWindow:@"分享失败"];
+            }
+        }else{
+            if ([data isKindOfClass:[UMSocialShareResponse class]]) {
+                UMSocialShareResponse *resp = data;
+                //分享结果消息
+                NSLog(@"************分享成功 %@*********",resp.message);
+                if (weakSelf.callback) {
+                    weakSelf.callback(YES,@"分享成功");
+                    [LOADING_MANAGER MBShowAUTOHidingInWindow:@"分享成功"];
+                }
+            }else{
+                NSLog(@"response data is %@",data);
+            }
+        }
+    }];
+}
+
+- (void)shareWechatCircle {
+    
+    if (![[UMSocialManager defaultManager] isInstall:UMSocialPlatformType_WechatSession]) {
+        if (self.callback) {
+            self.callback(NO, @"请安装微信");
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:@"请安装微信"];
+        }
+        return;
+    }
+    //创建分享消息对象
+    UMSocialMessageObject *messageObject = [UMSocialMessageObject messageObject];
+    NSString *shareTitle = @"";
+    if (![NSString isEmptyString:self.shareTitle]) {
+        shareTitle = self.shareTitle;
+    }
+    NSString *descMessage = @"";
+    if (self.shareMessage) {
+        descMessage = self.shareMessage;
+    }
+    // 创建分享对象
+    if (self.shareType == KSSHARETYPE_IMAGE) {
+        UMShareImageObject *shareObj = [UMShareImageObject shareObjectWithTitle:shareTitle descr:descMessage thumImage:[UIImage imageNamed:@"shareImage"]];
+        shareObj.shareImage = self.shareImage;
+        //分享消息对象设置分享内容对象
+        messageObject.shareObject = shareObj;
+    }
+    else if (self.shareType == KSSHARETYPE_VODEO) {
+        UMShareWebpageObject *shareObj = [UMShareWebpageObject shareObjectWithTitle:shareTitle descr:descMessage thumImage:[UIImage imageNamed:@"shareImage"]];
+        //            NSString *shareUrl = [self.shareUrl stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
+        shareObj.webpageUrl = self.shareUrl;
+        //分享消息对象设置分享内容对象
+        messageObject.shareObject = shareObj;
+    }
+    //调用分享接口
+    MJWeakSelf;
+    [[UMSocialManager defaultManager] shareToPlatform:UMSocialPlatformType_WechatTimeLine messageObject:messageObject currentViewController:nil completion:^(id data, NSError *error) {
+        if (error) {
+            NSLog(@"************分享失败 %@*********",error);
+            if (weakSelf.callback) {
+                weakSelf.callback(NO, @"分享失败");
+                [LOADING_MANAGER MBShowAUTOHidingInWindow:@"分享失败"];
+            }
+        }else{
+            if ([data isKindOfClass:[UMSocialShareResponse class]]) {
+                UMSocialShareResponse *resp = data;
+                //分享结果消息
+                NSLog(@"************分享成功 %@*********",resp.message);
+                if (weakSelf.callback) {
+                    weakSelf.callback(YES,@"分享成功");
+                    [LOADING_MANAGER MBShowAUTOHidingInWindow:@"分享成功"];
+                }
+            }else{
+                NSLog(@"response data is %@",data);
+            }
+        }
+    }];
+}
+- (void)dealloc {
+    NSLog(@"-------!");
+}
 @end

+ 22 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Controller/KSDraftMergeViewController.h

@@ -0,0 +1,22 @@
+//
+//  KSDraftMergeViewController.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/11/1.
+//
+
+#import "KSBaseViewController.h"
+#import "UserMusicFormalModel.h"
+typedef void(^DraftEditCallback)(void);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface KSDraftMergeViewController : KSBaseViewController
+
+@property (nonatomic, strong) UserMusicFormalModel *sourceModel;
+
+- (void)editCallback:(DraftEditCallback)callback;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 114 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Controller/KSDraftMergeViewController.m

@@ -0,0 +1,114 @@
+//
+//  KSDraftMergeViewController.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/11/1.
+//
+
+#import "KSDraftMergeViewController.h"
+#import "KSMediaMergeView.h"
+#import "AppDelegate+AppService.h"
+#import "UIViewController+zhStatusBarStyle.h"
+#import "UIDevice+TFDevice.h"
+
+@interface KSDraftMergeViewController ()
+
+@property (nonatomic, copy) DraftEditCallback callback;
+
+@end
+
+@implementation KSDraftMergeViewController
+
+- (void)changeOrientation:(BOOL)isLandScape {
+    if (isLandScape) {
+        // 切换到横屏
+        if (IS_IPAD) {
+            self.zh_statusBarHidden = YES;
+        }
+        AppDelegate* delegate = [AppDelegate shareAppDelegate];
+        delegate.allowAutoRotate = YES;
+        [UIDevice switchNewOrientation:UIInterfaceOrientationLandscapeRight inController:self];
+    }
+    else {
+        // 切换到横屏
+        AppDelegate* delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
+        delegate.allowAutoRotate = NO;
+        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+            if (IS_IPAD) {
+                self.zh_statusBarHidden = NO;
+            }
+            [UIDevice switchNewOrientation:UIInterfaceOrientationPortrait inController:self];
+        });
+    }
+}
+
+- (void)editCallback:(DraftEditCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    self.ks_prefersNavigationBarHidden = YES;
+}
+
+- (void)configUI {
+    [self.scrollView removeFromSuperview];
+    KSMediaMergeView *mergeView = [[KSMediaMergeView alloc] init];
+    mergeView.coverImage = self.sourceModel.img;
+    mergeView.songName = self.sourceModel.musicSheetName;
+    mergeView.recordId = self.sourceModel.musicPracticeRecordId;
+    mergeView.desc = self.sourceModel.desc;
+    [self.view addSubview:mergeView];
+    [mergeView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.bottom.mas_equalTo(self.view);
+    }];
+    NSString *videoUrl = @"";
+    if ([self.sourceModel.videoUrl hasSuffix:@".mp4"]) {
+        videoUrl = self.sourceModel.videoUrl;
+    }
+    NSString *recordUrl = self.sourceModel.recordFilePath;
+    MJWeakSelf;
+    [mergeView configRemoteVideoUrl:videoUrl bgAudioUrl:self.sourceModel.accompanyUrl recordUrl:recordUrl jsonConfig:self.sourceModel.jsonConfig callback:^{
+        [weakSelf changePortraitAndBack];
+    }];
+}
+
+- (void)changePortraitAndBack {
+    // 切换到竖屏
+    [self changeOrientation:NO];
+    dispatch_delay_block(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC), ^{
+        [self backRefreh];
+    });
+}
+
+- (void)backRefreh {
+    if (self.callback) {
+        self.callback();
+    }
+    [self backAction];
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+    [super viewDidAppear:animated];
+    [self changeOrientation:YES];
+    // 切换到横屏
+    dispatch_delay_block(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC), ^{
+        [self configUI];
+    });
+}
+
+
+
+/*
+#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

+ 23 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Controller/MineWorksViewController.h

@@ -0,0 +1,23 @@
+//
+//  MineWorksViewController.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import "KSBaseViewController.h"
+#import "JXCategoryTitleView.h"
+#import "JXPagerView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MineWorksViewController : KSBaseViewController
+
+@property (nonatomic, strong) JXPagerView *pagerView;
+@property (nonatomic, strong, readonly) JXCategoryTitleView *categoryView;
+@property (nonatomic, strong) NSArray <NSString *> *titles;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 224 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Controller/MineWorksViewController.m

@@ -0,0 +1,224 @@
+//
+//  MineWorksViewController.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import "MineWorksViewController.h"
+#import "MineWorksNavView.h"
+#import "MineWorksBodyView.h"
+#import "JXCategoryView.h"
+#import "JXPagerListRefreshView.h"
+
+@interface MineWorksViewController ()<JXPagerViewDelegate, JXPagerMainTableViewGestureDelegate,JXCategoryViewDelegate>
+
+@property (nonatomic, strong) MineWorksNavView *navView;
+
+@property (nonatomic, strong) NSMutableArray *listViewArray;
+
+@property (nonatomic, assign) BOOL isEdit;
+
+@property (nonatomic, assign) NSInteger selectedIndex;
+@end
+
+@implementation MineWorksViewController
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    [self configUI];
+}
+
+- (void)configUI {
+    self.ks_prefersNavigationBarHidden = YES;
+    [self.scrollView removeFromSuperview];
+    
+    UIImage *bgImage = [UIImage imageNamed:@"mineWorks_bg"];
+    NSInteger height = (NSInteger)(bgImage.size.height / bgImage.size.width * KPortraitWidth);
+    UIImageView *imageView = [[UIImageView alloc] initWithImage:bgImage];
+    imageView.frame = CGRectMake(0, 0, KPortraitWidth, height);
+    [self.view addSubview:imageView];
+    
+    _titles = @[@"作品",@"草稿"];
+    [self.view addSubview:self.navView];
+    CGFloat navHeight = [self.navView getViewHeight];
+    [self.navView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.left.right.top.mas_equalTo(self.view);
+        make.height.mas_equalTo(navHeight);
+    }];
+    [self configCategoryUI:height];
+}
+
+- (void)configCategoryUI:(NSInteger)topHeight {
+    _categoryView = [[JXCategoryTitleView alloc] initWithFrame:CGRectMake(0, topHeight-20, KPortraitWidth, 58)];
+    UIBezierPath *maskPath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, KPortraitWidth, 58) byRoundingCorners:UIRectCornerTopLeft|UIRectCornerTopRight cornerRadii:CGSizeMake(20, 20)];
+    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
+    maskLayer.frame = _categoryView.bounds;
+    maskLayer.path = maskPath.CGPath;
+    _categoryView.layer.mask = maskLayer;
+    
+    self.categoryView.backgroundColor = HexRGB(0xF8F9FC);
+    self.categoryView.titles = self.titles;
+    self.categoryView.delegate = self;
+    self.categoryView.titleFont = [UIFont systemFontOfSize:16.0f];
+    self.categoryView.titleSelectedFont = [UIFont systemFontOfSize:18.0f weight:UIFontWeightMedium];
+    self.categoryView.titleSelectedColor = HexRGB(0x333333);
+    self.categoryView.titleColor = HexRGB(0x777777);
+    self.categoryView.titleColorGradientEnabled = YES;
+    
+    JXCategoryIndicatorLineView *lineView = [[JXCategoryIndicatorLineView alloc] init];
+    lineView.indicatorColor = HexRGB(0x2DC7AA);
+    lineView.indicatorWidth = 16;
+    lineView.height = 4;
+    lineView.verticalMargin = 5;
+    self.categoryView.indicators = @[lineView];
+    
+    _pagerView = [self preferredPagingView];
+    self.pagerView.frame = CGRectMake(0, topHeight-20, KPortraitWidth, KPortraitHeight - (topHeight-20));
+    self.pagerView.mainTableView.gestureDelegate = self;
+    [self.view addSubview:self.pagerView];
+    self.pagerView.backgroundColor = [UIColor clearColor];
+    self.pagerView.mainTableView.backgroundColor = [UIColor clearColor];
+    self.pagerView.listContainerView.backgroundColor = [UIColor clearColor];
+    self.pagerView.listContainerView.listCellBackgroundColor = [UIColor clearColor];
+
+    self.categoryView.listContainer = (id<JXCategoryViewListContainer>)self.pagerView.listContainerView;
+}
+
+- (void)viewDidAppear:(BOOL)animated {
+    [super viewDidAppear:animated];
+    self.navigationController.interactivePopGestureRecognizer.enabled = (self.categoryView.selectedIndex == 0);
+}
+
+- (JXPagerView *)preferredPagingView {
+    return [[JXPagerListRefreshView alloc] initWithDelegate:self];
+}
+
+- (void)viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
+    [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent;
+    if (self.listViewArray.count > self.categoryView.selectedIndex) {
+        id value = self.listViewArray[self.categoryView.selectedIndex];
+        if ([value isKindOfClass:[KSJXBodyView class]]) {
+            KSJXBodyView *listView = (KSJXBodyView *)value;
+            [listView beginFirstRefresh];
+        }
+    }
+}
+
+#pragma mark - JXPagerViewDelegate
+- (UIView *)tableHeaderViewInPagerView:(JXPagerView *)pagerView {
+    return [UIView new];
+}
+
+- (NSUInteger)tableHeaderViewHeightInPagerView:(JXPagerView *)pagerView {
+    return CGFLOAT_MIN;
+}
+
+- (UIView *)viewForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
+    return self.categoryView;
+}
+
+- (NSUInteger)heightForPinSectionHeaderInPagerView:(JXPagerView *)pagerView {
+    return 58;
+}
+
+- (NSInteger)numberOfListsInPagerView:(JXPagerView *)pagerView {
+    //和categoryView的item数量一致
+    return self.titles.count;
+}
+
+- (id<JXPagerViewListViewDelegate>)pagerView:(JXPagerView *)pagerView initListAtIndex:(NSInteger)index {
+    MineWorksBodyView *listView = [[MineWorksBodyView alloc] init];
+    listView.naviController = self.navigationController;
+    listView.isEdit = self.isEdit;
+    [self.listViewArray replaceObjectAtIndex:index withObject:listView];
+    if (index == 0) {
+        listView.selectIndex = 0;
+    }
+    else {
+        listView.selectIndex = 1;
+    }
+    [listView beginFirstRefresh];
+    return listView;
+}
+
+#pragma mark - JXCategoryViewDelegate
+- (void)categoryView:(JXCategoryBaseView *)categoryView didSelectedItemAtIndex:(NSInteger)index {
+    self.navigationController.interactivePopGestureRecognizer.enabled = (index == 0);
+    if (self.selectedIndex == index) {
+        return;
+    }
+    if (index == 1) {
+        self.navView.showEditButton = YES;
+    }
+    else {
+        self.navView.showEditButton = NO;
+    }
+    self.isEdit = NO;
+    self.selectedIndex = index;
+}
+
+
+
+#pragma mark - JXPagerMainTableViewGestureDelegate
+
+- (BOOL)mainTableViewGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
+    //禁止categoryView左右滑动的时候,上下和左右都可以滚动
+    if (otherGestureRecognizer == self.categoryView.collectionView.panGestureRecognizer) {
+        return NO;
+    }
+    return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];
+}
+
+#pragma mark ------ lazying
+- (NSMutableArray *)listViewArray {
+    if (!_listViewArray) {
+        _listViewArray = [NSMutableArray arrayWithArray:@[@"",@""]];
+    }
+    return _listViewArray;
+}
+- (MineWorksNavView *)navView {
+    if (!_navView) {
+        _navView = [MineWorksNavView shareInstance];
+        MJWeakSelf;
+        [_navView backViewAction:^(BOOL isBack) {
+            if (isBack) {
+                [weakSelf backAction];
+            }
+            else {
+                [weakSelf changeEditStatus];
+            }
+        }];
+
+    }
+    return _navView;
+}
+
+- (void)changeEditStatus {
+    self.isEdit = !self.isEdit;
+}
+
+
+- (void)setIsEdit:(BOOL)isEdit {
+    _isEdit = isEdit;
+    self.navView.isEdit = isEdit;
+    for (id value in self.listViewArray) {
+        if ([value isKindOfClass:[MineWorksBodyView class]]) {
+            MineWorksBodyView *listView = (MineWorksBodyView *)value;
+            listView.isEdit = isEdit;
+        }
+    }
+}
+/*
+#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

+ 47 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Model/UserMusicFormalModel.h

@@ -0,0 +1,47 @@
+//
+//  UserMusicFormalModel.h
+//
+//  Created by Steven  on 2023/11/1
+//  Copyright (c) 2023 __MyCompanyName__. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+
+@interface UserMusicFormalModel : NSObject <NSCoding, NSCopying>
+
+@property (nonatomic, strong) NSString *username;
+@property (nonatomic, assign) double currentGradeNum;
+@property (nonatomic, strong) NSString *clientType;
+@property (nonatomic, strong) NSString *img;
+@property (nonatomic, assign) double likeNum;
+@property (nonatomic, strong) NSString *videoFilePath;
+@property (nonatomic, strong) NSString *videoUrl;
+@property (nonatomic, strong) NSString *accompanyUrl;
+@property (nonatomic, strong) NSString *musicSheetId;
+@property (nonatomic, strong) NSString *subjectName;
+@property (nonatomic, assign) BOOL vipFlag;
+@property (nonatomic, strong) NSString *musicSheetSubjectId;
+@property (nonatomic, strong) NSString *type;
+@property (nonatomic, strong) NSString *internalBaseClassIdentifier;
+@property (nonatomic, strong) NSString *musicPracticeRecordId;
+@property (nonatomic, assign) double currentClass;
+@property (nonatomic, strong) NSString *subjectId;
+@property (nonatomic, strong) NSString *musicSheetName;
+@property (nonatomic, strong) NSString *jsonConfig;
+@property (nonatomic, strong) NSString *recordFilePath;
+@property (nonatomic, strong) NSString *submitTime;
+@property (nonatomic, strong) NSString *avatar;
+@property (nonatomic, strong) NSString *createTime;
+@property (nonatomic, strong) NSString *musicSheetSubjectName;
+@property (nonatomic, strong) NSString *desc;
+@property (nonatomic, strong) NSString *userId;
+
+@property (nonatomic, assign) BOOL isChoose;
+
++ (instancetype)modelObjectWithDictionary:(NSDictionary *)dict;
+- (instancetype)initWithDictionary:(NSDictionary *)dict;
+- (NSDictionary *)dictionaryRepresentation;
+
+@end

+ 274 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/Model/UserMusicFormalModel.m

@@ -0,0 +1,274 @@
+//
+//  UserMusicFormalModel.m
+//
+//  Created by Steven  on 2023/11/1
+//  Copyright (c) 2023 __MyCompanyName__. All rights reserved.
+//
+
+#import "UserMusicFormalModel.h"
+
+
+NSString *const kUserMusicFormalModelUsername = @"username";
+NSString *const kUserMusicFormalModelCurrentGradeNum = @"currentGradeNum";
+NSString *const kUserMusicFormalModelClientType = @"clientType";
+NSString *const kUserMusicFormalModelImg = @"img";
+NSString *const kUserMusicFormalModelLikeNum = @"likeNum";
+NSString *const kUserMusicFormalModelVideoFilePath = @"videoFilePath";
+NSString *const kUserMusicFormalModelVideoUrl = @"videoUrl";
+NSString *const kUserMusicFormalModelAccompanyUrl = @"accompanyUrl";
+NSString *const kUserMusicFormalModelMusicSheetId = @"musicSheetId";
+NSString *const kUserMusicFormalModelSubjectName = @"subjectName";
+NSString *const kUserMusicFormalModelVipFlag = @"vipFlag";
+NSString *const kUserMusicFormalModelMusicSheetSubjectId = @"musicSheetSubjectId";
+NSString *const kUserMusicFormalModelType = @"type";
+NSString *const kUserMusicFormalModelId = @"id";
+NSString *const kUserMusicFormalModelMusicPracticeRecordId = @"musicPracticeRecordId";
+NSString *const kUserMusicFormalModelCurrentClass = @"currentClass";
+NSString *const kUserMusicFormalModelSubjectId = @"subjectId";
+NSString *const kUserMusicFormalModelMusicSheetName = @"musicSheetName";
+NSString *const kUserMusicFormalModelJsonConfig = @"jsonConfig";
+NSString *const kUserMusicFormalModelRecordFilePath = @"recordFilePath";
+NSString *const kUserMusicFormalModelSubmitTime = @"submitTime";
+NSString *const kUserMusicFormalModelAvatar = @"avatar";
+NSString *const kUserMusicFormalModelCreateTime = @"createTime";
+NSString *const kUserMusicFormalModelMusicSheetSubjectName = @"musicSheetSubjectName";
+NSString *const kUserMusicFormalModelDesc = @"desc";
+NSString *const kUserMusicFormalModelUserId = @"userId";
+
+
+@interface UserMusicFormalModel ()
+
+- (id)objectOrNilForKey:(id)aKey fromDictionary:(NSDictionary *)dict;
+
+@end
+
+@implementation UserMusicFormalModel
+
+@synthesize username = _username;
+@synthesize currentGradeNum = _currentGradeNum;
+@synthesize clientType = _clientType;
+@synthesize img = _img;
+@synthesize likeNum = _likeNum;
+@synthesize videoFilePath = _videoFilePath;
+@synthesize videoUrl = _videoUrl;
+@synthesize accompanyUrl = _accompanyUrl;
+@synthesize musicSheetId = _musicSheetId;
+@synthesize subjectName = _subjectName;
+@synthesize vipFlag = _vipFlag;
+@synthesize musicSheetSubjectId = _musicSheetSubjectId;
+@synthesize type = _type;
+@synthesize internalBaseClassIdentifier = _internalBaseClassIdentifier;
+@synthesize musicPracticeRecordId = _musicPracticeRecordId;
+@synthesize currentClass = _currentClass;
+@synthesize subjectId = _subjectId;
+@synthesize musicSheetName = _musicSheetName;
+@synthesize jsonConfig = _jsonConfig;
+@synthesize recordFilePath = _recordFilePath;
+@synthesize submitTime = _submitTime;
+@synthesize avatar = _avatar;
+@synthesize createTime = _createTime;
+@synthesize musicSheetSubjectName = _musicSheetSubjectName;
+@synthesize desc = _desc;
+@synthesize userId = _userId;
+
+
++ (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.username = [self objectOrNilForKey:kUserMusicFormalModelUsername fromDictionary:dict];
+            self.currentGradeNum = [[self objectOrNilForKey:kUserMusicFormalModelCurrentGradeNum fromDictionary:dict] doubleValue];
+            self.clientType = [self objectOrNilForKey:kUserMusicFormalModelClientType fromDictionary:dict];
+            self.img = [self objectOrNilForKey:kUserMusicFormalModelImg fromDictionary:dict];
+            self.likeNum = [[self objectOrNilForKey:kUserMusicFormalModelLikeNum fromDictionary:dict] doubleValue];
+            self.videoFilePath = [self objectOrNilForKey:kUserMusicFormalModelVideoFilePath fromDictionary:dict];
+            self.videoUrl = [self objectOrNilForKey:kUserMusicFormalModelVideoUrl fromDictionary:dict];
+            self.accompanyUrl = [self objectOrNilForKey:kUserMusicFormalModelAccompanyUrl fromDictionary:dict];
+            self.musicSheetId = [self objectOrNilForKey:kUserMusicFormalModelMusicSheetId fromDictionary:dict];
+            self.subjectName = [self objectOrNilForKey:kUserMusicFormalModelSubjectName fromDictionary:dict];
+            self.vipFlag = [[self objectOrNilForKey:kUserMusicFormalModelVipFlag fromDictionary:dict] boolValue];
+            self.musicSheetSubjectId = [self objectOrNilForKey:kUserMusicFormalModelMusicSheetSubjectId fromDictionary:dict];
+            self.type = [self objectOrNilForKey:kUserMusicFormalModelType fromDictionary:dict];
+            self.internalBaseClassIdentifier = [self objectOrNilForKey:kUserMusicFormalModelId fromDictionary:dict];
+            self.musicPracticeRecordId = [self objectOrNilForKey:kUserMusicFormalModelMusicPracticeRecordId fromDictionary:dict];
+            self.currentClass = [[self objectOrNilForKey:kUserMusicFormalModelCurrentClass fromDictionary:dict] doubleValue];
+            self.subjectId = [self objectOrNilForKey:kUserMusicFormalModelSubjectId fromDictionary:dict];
+            self.musicSheetName = [self objectOrNilForKey:kUserMusicFormalModelMusicSheetName fromDictionary:dict];
+            self.jsonConfig = [self objectOrNilForKey:kUserMusicFormalModelJsonConfig fromDictionary:dict];
+            self.recordFilePath = [self objectOrNilForKey:kUserMusicFormalModelRecordFilePath fromDictionary:dict];
+            self.submitTime = [self objectOrNilForKey:kUserMusicFormalModelSubmitTime fromDictionary:dict];
+            self.avatar = [self objectOrNilForKey:kUserMusicFormalModelAvatar fromDictionary:dict];
+            self.createTime = [self objectOrNilForKey:kUserMusicFormalModelCreateTime fromDictionary:dict];
+            self.musicSheetSubjectName = [self objectOrNilForKey:kUserMusicFormalModelMusicSheetSubjectName fromDictionary:dict];
+            self.desc = [self objectOrNilForKey:kUserMusicFormalModelDesc fromDictionary:dict];
+            self.userId = [self objectOrNilForKey:kUserMusicFormalModelUserId fromDictionary:dict];
+
+    }
+    
+    return self;
+    
+}
+
+- (NSDictionary *)dictionaryRepresentation
+{
+    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
+    [mutableDict setValue:self.username forKey:kUserMusicFormalModelUsername];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.currentGradeNum] forKey:kUserMusicFormalModelCurrentGradeNum];
+    [mutableDict setValue:self.clientType forKey:kUserMusicFormalModelClientType];
+    [mutableDict setValue:self.img forKey:kUserMusicFormalModelImg];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.likeNum] forKey:kUserMusicFormalModelLikeNum];
+    [mutableDict setValue:self.videoFilePath forKey:kUserMusicFormalModelVideoFilePath];
+    [mutableDict setValue:self.videoUrl forKey:kUserMusicFormalModelVideoUrl];
+    [mutableDict setValue:self.accompanyUrl forKey:kUserMusicFormalModelAccompanyUrl];
+    [mutableDict setValue:self.musicSheetId forKey:kUserMusicFormalModelMusicSheetId];
+    [mutableDict setValue:self.subjectName forKey:kUserMusicFormalModelSubjectName];
+    [mutableDict setValue:[NSNumber numberWithBool:self.vipFlag] forKey:kUserMusicFormalModelVipFlag];
+    [mutableDict setValue:self.musicSheetSubjectId forKey:kUserMusicFormalModelMusicSheetSubjectId];
+    [mutableDict setValue:self.type forKey:kUserMusicFormalModelType];
+    [mutableDict setValue:self.internalBaseClassIdentifier forKey:kUserMusicFormalModelId];
+    [mutableDict setValue:self.musicPracticeRecordId forKey:kUserMusicFormalModelMusicPracticeRecordId];
+    [mutableDict setValue:[NSNumber numberWithDouble:self.currentClass] forKey:kUserMusicFormalModelCurrentClass];
+    [mutableDict setValue:self.subjectId forKey:kUserMusicFormalModelSubjectId];
+    [mutableDict setValue:self.musicSheetName forKey:kUserMusicFormalModelMusicSheetName];
+    [mutableDict setValue:self.jsonConfig forKey:kUserMusicFormalModelJsonConfig];
+    [mutableDict setValue:self.recordFilePath forKey:kUserMusicFormalModelRecordFilePath];
+    [mutableDict setValue:self.submitTime forKey:kUserMusicFormalModelSubmitTime];
+    [mutableDict setValue:self.avatar forKey:kUserMusicFormalModelAvatar];
+    [mutableDict setValue:self.createTime forKey:kUserMusicFormalModelCreateTime];
+    [mutableDict setValue:self.musicSheetSubjectName forKey:kUserMusicFormalModelMusicSheetSubjectName];
+    [mutableDict setValue:self.desc forKey:kUserMusicFormalModelDesc];
+    [mutableDict setValue:self.userId forKey:kUserMusicFormalModelUserId];
+
+    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.username = [aDecoder decodeObjectForKey:kUserMusicFormalModelUsername];
+    self.currentGradeNum = [aDecoder decodeDoubleForKey:kUserMusicFormalModelCurrentGradeNum];
+    self.clientType = [aDecoder decodeObjectForKey:kUserMusicFormalModelClientType];
+    self.img = [aDecoder decodeObjectForKey:kUserMusicFormalModelImg];
+    self.likeNum = [aDecoder decodeDoubleForKey:kUserMusicFormalModelLikeNum];
+    self.videoFilePath = [aDecoder decodeObjectForKey:kUserMusicFormalModelVideoFilePath];
+    self.videoUrl = [aDecoder decodeObjectForKey:kUserMusicFormalModelVideoUrl];
+    self.accompanyUrl = [aDecoder decodeObjectForKey:kUserMusicFormalModelAccompanyUrl];
+    self.musicSheetId = [aDecoder decodeObjectForKey:kUserMusicFormalModelMusicSheetId];
+    self.subjectName = [aDecoder decodeObjectForKey:kUserMusicFormalModelSubjectName];
+    self.vipFlag = [aDecoder decodeBoolForKey:kUserMusicFormalModelVipFlag];
+    self.musicSheetSubjectId = [aDecoder decodeObjectForKey:kUserMusicFormalModelMusicSheetSubjectId];
+    self.type = [aDecoder decodeObjectForKey:kUserMusicFormalModelType];
+    self.internalBaseClassIdentifier = [aDecoder decodeObjectForKey:kUserMusicFormalModelId];
+    self.musicPracticeRecordId = [aDecoder decodeObjectForKey:kUserMusicFormalModelMusicPracticeRecordId];
+    self.currentClass = [aDecoder decodeDoubleForKey:kUserMusicFormalModelCurrentClass];
+    self.subjectId = [aDecoder decodeObjectForKey:kUserMusicFormalModelSubjectId];
+    self.musicSheetName = [aDecoder decodeObjectForKey:kUserMusicFormalModelMusicSheetName];
+    self.jsonConfig = [aDecoder decodeObjectForKey:kUserMusicFormalModelJsonConfig];
+    self.recordFilePath = [aDecoder decodeObjectForKey:kUserMusicFormalModelRecordFilePath];
+    self.submitTime = [aDecoder decodeObjectForKey:kUserMusicFormalModelSubmitTime];
+    self.avatar = [aDecoder decodeObjectForKey:kUserMusicFormalModelAvatar];
+    self.createTime = [aDecoder decodeObjectForKey:kUserMusicFormalModelCreateTime];
+    self.musicSheetSubjectName = [aDecoder decodeObjectForKey:kUserMusicFormalModelMusicSheetSubjectName];
+    self.desc = [aDecoder decodeObjectForKey:kUserMusicFormalModelDesc];
+    self.userId = [aDecoder decodeObjectForKey:kUserMusicFormalModelUserId];
+    return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder
+{
+
+    [aCoder encodeObject:_username forKey:kUserMusicFormalModelUsername];
+    [aCoder encodeDouble:_currentGradeNum forKey:kUserMusicFormalModelCurrentGradeNum];
+    [aCoder encodeObject:_clientType forKey:kUserMusicFormalModelClientType];
+    [aCoder encodeObject:_img forKey:kUserMusicFormalModelImg];
+    [aCoder encodeDouble:_likeNum forKey:kUserMusicFormalModelLikeNum];
+    [aCoder encodeObject:_videoFilePath forKey:kUserMusicFormalModelVideoFilePath];
+    [aCoder encodeObject:_videoUrl forKey:kUserMusicFormalModelVideoUrl];
+    [aCoder encodeObject:_accompanyUrl forKey:kUserMusicFormalModelAccompanyUrl];
+    [aCoder encodeObject:_musicSheetId forKey:kUserMusicFormalModelMusicSheetId];
+    [aCoder encodeObject:_subjectName forKey:kUserMusicFormalModelSubjectName];
+    [aCoder encodeBool:_vipFlag forKey:kUserMusicFormalModelVipFlag];
+    [aCoder encodeObject:_musicSheetSubjectId forKey:kUserMusicFormalModelMusicSheetSubjectId];
+    [aCoder encodeObject:_type forKey:kUserMusicFormalModelType];
+    [aCoder encodeObject:_internalBaseClassIdentifier forKey:kUserMusicFormalModelId];
+    [aCoder encodeObject:_musicPracticeRecordId forKey:kUserMusicFormalModelMusicPracticeRecordId];
+    [aCoder encodeDouble:_currentClass forKey:kUserMusicFormalModelCurrentClass];
+    [aCoder encodeObject:_subjectId forKey:kUserMusicFormalModelSubjectId];
+    [aCoder encodeObject:_musicSheetName forKey:kUserMusicFormalModelMusicSheetName];
+    [aCoder encodeObject:_jsonConfig forKey:kUserMusicFormalModelJsonConfig];
+    [aCoder encodeObject:_recordFilePath forKey:kUserMusicFormalModelRecordFilePath];
+    [aCoder encodeObject:_submitTime forKey:kUserMusicFormalModelSubmitTime];
+    [aCoder encodeObject:_avatar forKey:kUserMusicFormalModelAvatar];
+    [aCoder encodeObject:_createTime forKey:kUserMusicFormalModelCreateTime];
+    [aCoder encodeObject:_musicSheetSubjectName forKey:kUserMusicFormalModelMusicSheetSubjectName];
+    [aCoder encodeObject:_desc forKey:kUserMusicFormalModelDesc];
+    [aCoder encodeObject:_userId forKey:kUserMusicFormalModelUserId];
+}
+
+- (id)copyWithZone:(NSZone *)zone
+{
+    UserMusicFormalModel *copy = [[UserMusicFormalModel alloc] init];
+    
+    if (copy) {
+
+        copy.username = [self.username copyWithZone:zone];
+        copy.currentGradeNum = self.currentGradeNum;
+        copy.clientType = [self.clientType copyWithZone:zone];
+        copy.img = [self.img copyWithZone:zone];
+        copy.likeNum = self.likeNum;
+        copy.videoFilePath = [self.videoFilePath copyWithZone:zone];
+        copy.videoUrl = [self.videoUrl copyWithZone:zone];
+        copy.accompanyUrl = [self.accompanyUrl copyWithZone:zone];
+        copy.musicSheetId = [self.musicSheetId copyWithZone:zone];
+        copy.subjectName = [self.subjectName copyWithZone:zone];
+        copy.vipFlag = self.vipFlag;
+        copy.musicSheetSubjectId = [self.musicSheetSubjectId copyWithZone:zone];
+        copy.type = [self.type copyWithZone:zone];
+        copy.internalBaseClassIdentifier = [self.internalBaseClassIdentifier copyWithZone:zone];
+        copy.musicPracticeRecordId = [self.musicPracticeRecordId copyWithZone:zone];
+        copy.currentClass = self.currentClass;
+        copy.subjectId = [self.subjectId copyWithZone:zone];
+        copy.musicSheetName = [self.musicSheetName copyWithZone:zone];
+        copy.jsonConfig = [self.jsonConfig copyWithZone:zone];
+        copy.recordFilePath = [self.recordFilePath copyWithZone:zone];
+        copy.submitTime = [self.submitTime copyWithZone:zone];
+        copy.avatar = [self.avatar copyWithZone:zone];
+        copy.createTime = [self.createTime copyWithZone:zone];
+        copy.musicSheetSubjectName = [self.musicSheetSubjectName copyWithZone:zone];
+        copy.desc = [self.desc copyWithZone:zone];
+        copy.userId = [self.userId copyWithZone:zone];
+    }
+    
+    return copy;
+}
+
+
+@end

+ 18 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBodyView.h

@@ -0,0 +1,18 @@
+//
+//  MineWorksBodyView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import "KSJXBodyView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MineWorksBodyView : KSJXBodyView
+
+@property (nonatomic, assign) BOOL isEdit;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 447 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBodyView.m

@@ -0,0 +1,447 @@
+//
+//  MineWorksBodyView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import "MineWorksBodyView.h"
+#import "KSEmptyStatusView.h"
+#import "MineWorksOpenDisplayCell.h"
+#import "MineWorksDraftsCell.h"
+#import "Reachability.h"
+#import "KSNewGifRefreshFooter.h"
+#import "UserMusicFormalModel.h"
+#import "KSBaseWKWebViewController.h"
+#import "MineWorksBottomView.h"
+#import "KSNewAlertView.h"
+#import "KSDraftMergeViewController.h"
+
+@interface MineWorksBodyView ()<UITableViewDelegate,UITableViewDataSource>
+
+@property (nonatomic, strong) KSEmptyStatusView *promptView;
+@property (nonatomic, strong) UIView *promptPlaceView;
+
+@property (nonatomic, assign) BOOL networkAvaiable; // 网络是否可用
+@property (nonatomic, strong) NSMutableArray *sourceArray;
+
+@property (nonatomic, strong) NSString *type;
+
+@property (nonatomic, assign) BOOL isLoadMore;
+@property (nonatomic, assign) NSInteger page;
+@property (nonatomic, assign) NSInteger rows;
+
+@property (nonatomic, strong) MineWorksBottomView *bottomView;
+
+@property (nonatomic, strong) KSNewAlertView *alertView;
+
+@property (nonatomic, assign) NSInteger chooseCount;
+
+@end
+
+@implementation MineWorksBodyView
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        self.backgroundColor = [UIColor clearColor];
+        self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
+        self.tableView.backgroundColor = [UIColor clearColor];
+        self.tableView.showsVerticalScrollIndicator = NO;
+        self.tableView.rowHeight = 100.0f;
+        self.tableView.dataSource = self;
+        self.tableView.delegate = self;
+        self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
+        if (@available(iOS 15.0, *)) {
+            self.tableView.sectionHeaderTopPadding = 0;
+        }
+        self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
+        self.tableView.estimatedSectionFooterHeight = 0;
+        self.tableView.estimatedSectionHeaderHeight = 0;
+        [self addSubview:self.tableView];
+        [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.right.top.bottom.mas_equalTo(self);
+        }];
+        UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, 10)];
+        bottomView.backgroundColor = [UIColor clearColor];
+        self.tableView.tableFooterView = bottomView;
+        
+        // cell
+        [self.tableView registerNib:[UINib nibWithNibName:@"MineWorksOpenDisplayCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"MineWorksOpenDisplayCell"];
+        [self.tableView registerNib:[UINib nibWithNibName:@"MineWorksDraftsCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"MineWorksDraftsCell"];
+        MJWeakSelf;
+        self.tableView.mj_header = [KSGifRefreshHeader headerWithRefreshingBlock:^{
+            [weakSelf resetParamenter];
+            [weakSelf requestData];
+        }];
+        self.tableView.mj_footer = [KSNewGifRefreshFooter footerWithRefreshingBlock:^{
+            if (weakSelf.isLoadMore) {
+                weakSelf.page += 1;
+                [weakSelf requestData];
+            }
+            else {
+                [weakSelf.tableView.mj_footer endRefreshingWithNoMoreData];
+            }
+        }];
+    }
+    return self;
+}
+- (void)endRefresh {
+    [self.tableView.mj_header endRefreshing];
+    [self.tableView.mj_footer endRefreshing];
+}
+
+- (void)refreshAndRequestData {
+    [self resetParamenter];
+    [self requestData];
+}
+
+- (void)resetParamenter {
+    [self setPromptString:@"暂无内容" imageName:@"wd_img_zwsj" inView:self.tableView];
+    self.isLoadMore = YES;
+    self.page = 1;
+    self.rows = 10;
+    self.sourceArray = [NSMutableArray array];
+    [self.tableView reloadData];
+}
+
+- (void)requestData {
+    if (self.selectIndex == 0) {
+        self.type = @"FORMAL";
+    }
+    else {
+        self.type = @"DRAFT";
+    }
+    [KSNetworkingManager userMusicPageRequest:KS_POST type:self.type page:self.page rows:self.rows success:^(NSDictionary * _Nonnull dic) {
+        [self endRefresh];
+        if ([dic ks_integerValueForKey:@"code"] == 200) {
+            NSArray *fileArray = [[dic ks_dictionaryValueForKey:@"data"] ks_arrayValueForKey:@"rows"];
+            for (NSDictionary *parm in fileArray) {
+                UserMusicFormalModel *model = [[UserMusicFormalModel alloc] initWithDictionary:parm];
+                [self.sourceArray addObject:model];
+            }
+            if ([[dic ks_dictionaryValueForKey:@"data"] ks_boolValueForKey:@"next"] == NO) {
+                self.isLoadMore = NO;
+            }
+        }
+        else {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+        [self countTotalChooseCount];
+        [self.tableView reloadData];
+        [self changePromptLabelStateWithArray:self.sourceArray];
+
+    } faliure:^(NSError * _Nonnull error) {
+        [self endRefresh];
+        if (self.networkAvaiable == NO) {
+            [self setPromptString:@"暂无网络" imageName:@"no_networking" inView:self.tableView];
+        }
+        [self.sourceArray removeAllObjects];
+        [self.tableView reloadData];
+        [self changePromptLabelStateWithArray:self.sourceArray];
+    }];
+}
+
+- (void)beginRefreshImmediately {
+    [self resetParamenter];
+    [self requestData];
+}
+
+- (void)selectCellAtIndexPath:(NSIndexPath *)indexPath {
+    
+    if (self.lastSelectedIndexPath == indexPath) {
+        return;
+    }
+    if (self.lastSelectedIndexPath != nil) {
+        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.lastSelectedIndexPath];
+        [cell setSelected:NO animated:NO];
+    }
+    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
+    [cell setSelected:YES animated:NO];
+    self.lastSelectedIndexPath = indexPath;
+}
+
+- (void)beginFirstRefresh {
+    if (!self.isHeaderRefreshed) {
+        [self beginRefreshImmediately];
+    }
+}
+
+
+
+#pragma mark - UITableViewDataSource, UITableViewDelegate
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    return self.sourceArray.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    if (self.selectIndex == 0) {
+        UserMusicFormalModel *model = self.sourceArray[indexPath.row];
+        MineWorksOpenDisplayCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MineWorksOpenDisplayCell"];
+        [cell configSourceWithModel:model];
+        return cell;
+    }
+    else {
+        UserMusicFormalModel *model = self.sourceArray[indexPath.row];
+        
+        MineWorksDraftsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MineWorksDraftsCell"];
+        [cell configSourceWithModel:model isEdit:self.isEdit];
+        return cell;
+    }
+}
+
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
+    if (self.selectIndex == 0) {
+        KSBaseWKWebViewController *webCtrl = [[KSBaseWKWebViewController alloc] init];
+        UserMusicFormalModel *model = self.sourceArray[indexPath.row];
+        webCtrl.url = [NSString stringWithFormat:@"%@%@?id=%@",WEBHOST, @"/#/creation", model.internalBaseClassIdentifier];
+        [self.naviController pushViewController:webCtrl animated:YES];    }
+    else {
+        UserMusicFormalModel *model = self.sourceArray[indexPath.row];
+
+        if (self.isEdit) { // 选择状态
+            model.isChoose = !model.isChoose;
+            [self countTotalChooseCount];
+            [self.tableView reloadData];
+        }
+        else { // 进入编辑页面
+            [self displayMergeView:model];
+        }
+    }
+}
+
+- (void)bottomViewCountChange {
+    self.bottomView.countLabel.text = [NSString stringWithFormat:@"全选(已选择%zd)", self.chooseCount];
+    NSString *chooseImg = @"";
+    if (self.chooseCount == self.sourceArray.count && self.chooseCount != 0) {
+        chooseImg = @"choose_status";
+    }
+    else {
+        chooseImg = @"unChoose_status";
+    }
+    [self.bottomView.statusImage setImage:[UIImage imageNamed:chooseImg]];
+}
+
+- (void)countTotalChooseCount {
+    NSInteger count = 0;
+    for (UserMusicFormalModel *model in self.sourceArray) {
+        if (model.isChoose) {
+            count++;
+        }
+    }
+    self.chooseCount = count;
+    [self bottomViewCountChange];
+}
+
+- (void)displayMergeView:(UserMusicFormalModel *)model {
+    KSDraftMergeViewController *ctrl = [[KSDraftMergeViewController alloc] init];
+    ctrl.sourceModel = model;
+    MJWeakSelf;
+    [ctrl editCallback:^{
+        [weakSelf refreshAndRequestData];
+    }];
+    [self.naviController pushViewController:ctrl animated:YES];
+}
+
+/**
+ 设置没有数据时的显示
+ 
+ @param promptString 提示语
+ @param imgName 图片名称
+ @param view 显示在什么地方
+ */
+- (void)setPromptString:(NSString *)promptString imageName:(NSString *)imgName inView:(UIView *)view {
+    if (self.promptView != nil) {
+        [self.promptView removeFromSuperview];
+    }
+    else {
+        self.promptView = [KSEmptyStatusView shareInstance];
+    }
+    _promptPlaceView = view;
+    //当请求不到数据时 ,自定义提示view 将会出现;
+    self.promptView.alpha = 0.0f;
+    [self.promptView configImageName:imgName desc:promptString topHeight:40];
+    [view addSubview:self.promptView];
+    [self.promptView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.edges.mas_equalTo(view);
+        make.width.mas_equalTo(view);
+        make.height.mas_equalTo(view);
+    }];
+}
+
+// 结束刷新后调用方法
+- (void)changePromptLabelStateWithArray:(NSMutableArray *)array {
+    NSInteger count;
+    if (array.count) {
+        count = array.count;
+    } else {
+        count = 0;
+    }
+    
+    [UIView animateWithDuration:0.1 animations:^{
+        [[self promptView] setAlpha:count ? 0.0f :1.0f ] ;
+        
+    }] ;
+    
+}
+
+- (BOOL)networkAvaiable {
+    return [self checkNetworkAvaiable];
+}
+
+- (BOOL)checkNetworkAvaiable {
+    BOOL isExistenceNetwork = YES;
+    Reachability *reach = [Reachability reachabilityWithHostName:@"www.apple.com"];
+    switch ([reach currentReachabilityStatus]) {
+        case NotReachable:
+            isExistenceNetwork = NO;
+            //NSLog(@"notReachable");
+            break;
+        case ReachableViaWiFi:
+            isExistenceNetwork = YES;
+            //NSLog(@"WIFI");
+            break;
+        case ReachableViaWWAN:
+            isExistenceNetwork = YES;
+            //NSLog(@"3G");
+            break;
+    }
+    return isExistenceNetwork;
+}
+
+- (NSMutableArray *)sourceArray {
+    if (!_sourceArray) {
+        _sourceArray = [NSMutableArray array];
+    }
+    return _sourceArray;
+}
+- (void)setIsEdit:(BOOL)isEdit {
+    _isEdit = isEdit;
+    if (self.selectIndex == 1) {
+        if (isEdit == NO) {
+            [self resetChooseStatus];
+        }
+        else {
+            [self.tableView reloadData];
+        }
+        [self countTotalChooseCount];
+        [self changeViewDisplay];
+    }
+}
+
+- (void)changeViewDisplay {
+    CGFloat bottomHeight = 10.0f;
+    if (self.isEdit) {
+        [self addSubview:self.bottomView];
+        bottomHeight = [MineWorksBottomView getViewHeight];
+        [self.bottomView mas_makeConstraints:^(MASConstraintMaker *make) {
+            make.left.right.bottom.mas_equalTo(self);
+            make.height.mas_equalTo(bottomHeight);
+        }];
+    }
+    else {
+        
+        [self.bottomView removeFromSuperview];
+    }
+    UIView *bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, KPortraitWidth, bottomHeight)];
+    bottomView.backgroundColor = [UIColor clearColor];
+    self.tableView.tableFooterView = bottomView;
+}
+
+
+- (MineWorksBottomView *)bottomView {
+    if (!_bottomView) {
+        _bottomView = [MineWorksBottomView shareInstance];
+        MJWeakSelf;
+        [_bottomView mineWorksAction:^(DRAFTS_CHOOSE type) {
+            [weakSelf bottomViewAction:type];
+        }];
+    }
+    return _bottomView;
+}
+
+- (void)resetChooseStatus {
+    for (UserMusicFormalModel *model in self.sourceArray) {
+        model.isChoose = NO;
+    }
+    self.chooseCount = 0;
+    [self.tableView reloadData];
+}
+
+- (void)chooseAll {
+    for (UserMusicFormalModel *model in self.sourceArray) {
+        model.isChoose = YES;
+    }
+    self.chooseCount = self.sourceArray.count;
+    [self.tableView reloadData];
+}
+
+- (void)bottomViewAction:(DRAFTS_CHOOSE)type {
+    switch (type) {
+        case DRAFTS_CHOOSE_SELECT:
+        {
+            if (self.chooseCount == self.sourceArray.count) { // 已全选
+                [self resetChooseStatus];
+            }
+            else { // 未全选
+                [self chooseAll];
+            }
+            [self bottomViewCountChange];
+        }
+            break;
+        case DRAFTS_CHOOSE_DELETE:
+        {
+            if (self.chooseCount) {
+                MJWeakSelf;
+                self.alertView = [KSNewAlertView shareInstance];
+                [self.alertView configTitle:@"确认删除吗?" descMessage:@"" leftButtonTitle:@"取消" rightButtonTitle:@"确认" leftButtonAction:^{
+                    
+                } rightButtonAction:^{
+                    [weakSelf removeDraft];
+                }];
+                [self.alertView showAlert];
+            }
+            else {
+                [LOADING_MANAGER MBShowAUTOHidingInWindow:@"请选择需要删除的草稿"];
+            }
+        }
+            break;
+        default:
+            break;
+    }
+}
+
+- (void)removeDraft {
+    NSMutableArray *draftArray = [NSMutableArray array];
+    
+    for (UserMusicFormalModel *model in self.sourceArray) {
+        if (model.isChoose) {
+            [draftArray addObject:model.internalBaseClassIdentifier];
+        }
+    }
+    NSString *musicId = [draftArray componentsJoinedByString:@","];
+    [LOADING_MANAGER showHUD];
+    [KSNetworkingManager userMusicRemoveRequest:KS_POST musicId:musicId success:^(NSDictionary * _Nonnull dic) {
+        [LOADING_MANAGER removeHUD];
+        if ([dic ks_integerValueForKey:@"code"] == 200) {
+            [LOADING_MANAGER KSShowMsg:@"删除成功" promptCompletion:^{
+                [self refreshAndRequestData];
+            }];
+        }
+        else {
+            [LOADING_MANAGER MBShowAUTOHidingInWindow:MESSAGEKEY];
+        }
+    } faliure:^(NSError * _Nonnull error) {
+        [LOADING_MANAGER removeHUD];
+    }];
+}
+
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 33 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBottomView.h

@@ -0,0 +1,33 @@
+//
+//  MineWorksBottomView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/11/1.
+//
+
+#import <UIKit/UIKit.h>
+
+typedef NS_ENUM(NSInteger, DRAFTS_CHOOSE) {
+    DRAFTS_CHOOSE_SELECT,   // 选择
+    DRAFTS_CHOOSE_DELETE,   // 删除
+};
+
+typedef void(^MineWorksChooseCallback)(DRAFTS_CHOOSE type);
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MineWorksBottomView : UIView
+
+@property (weak, nonatomic) IBOutlet UIImageView *statusImage;
+
+@property (weak, nonatomic) IBOutlet UILabel *countLabel;
+
++ (instancetype)shareInstance;
+
+- (void)mineWorksAction:(MineWorksChooseCallback)callback;
+
++ (CGFloat)getViewHeight;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 57 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBottomView.m

@@ -0,0 +1,57 @@
+//
+//  MineWorksBottomView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/11/1.
+//
+
+#import "MineWorksBottomView.h"
+
+@interface MineWorksBottomView ()
+
+@property (nonatomic, copy) MineWorksChooseCallback callback;
+
+@end
+
+@implementation MineWorksBottomView
+
++ (instancetype)shareInstance {
+    MineWorksBottomView *view = [[[NSBundle mainBundle] loadNibNamed:@"MineWorksBottomView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)mineWorksAction:(MineWorksChooseCallback)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+- (IBAction)chooseAllAction:(id)sender {
+    if (self.callback) {
+        self.callback(DRAFTS_CHOOSE_SELECT);
+    }
+}
+
+- (IBAction)sureDeleteAction:(id)sender {
+    if (self.callback) {
+        self.callback(DRAFTS_CHOOSE_DELETE);
+    }
+}
+
+
++ (CGFloat)getViewHeight {
+    if (IS_iPhoneX) {
+        return 60 + iPhoneXSafeBottomMargin;
+    }
+    else {
+        return 60 + 20;
+    }
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 86 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksBottomView.xib

@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="22155" 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="22131"/>
+        <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="MineWorksBottomView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="60"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bxi-KM-pUe">
+                    <rect key="frame" x="0.0" y="0.0" width="393" height="60"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="unChoose_status" translatesAutoresizingMaskIntoConstraints="NO" id="A0q-wS-bGi">
+                            <rect key="frame" x="25" y="21" width="18" height="18"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="18" id="fUV-Hb-DhD"/>
+                                <constraint firstAttribute="width" constant="18" id="wIU-B4-mf4"/>
+                            </constraints>
+                        </imageView>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="全选(已选择0)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="c1J-5D-9Pz">
+                            <rect key="frame" x="55" y="20" width="94" height="20"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="20" id="dVF-Ew-XQz"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                            <color key="textColor" red="0.46666666666666667" green="0.46666666666666667" blue="0.46666666666666667" alpha="1" colorSpace="calibratedRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kGm-Nx-2wO">
+                            <rect key="frame" x="301" y="15" width="80" height="30"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <state key="normal" image="sure_delete_image"/>
+                            <connections>
+                                <action selector="sureDeleteAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="BB6-BV-Kqv"/>
+                            </connections>
+                        </button>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="K5S-Tx-sIQ">
+                            <rect key="frame" x="25" y="13" width="124" height="34"/>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="chooseAllAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="Hb6-Hx-ITz"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="A0q-wS-bGi" firstAttribute="leading" secondItem="bxi-KM-pUe" secondAttribute="leading" constant="25" id="3mx-7s-S0V"/>
+                        <constraint firstItem="A0q-wS-bGi" firstAttribute="leading" secondItem="K5S-Tx-sIQ" secondAttribute="leading" id="60Q-WA-gi9"/>
+                        <constraint firstAttribute="trailing" secondItem="kGm-Nx-2wO" secondAttribute="trailing" constant="12" id="CI3-vo-euc"/>
+                        <constraint firstItem="c1J-5D-9Pz" firstAttribute="centerY" secondItem="A0q-wS-bGi" secondAttribute="centerY" id="Icz-3X-cCF"/>
+                        <constraint firstItem="c1J-5D-9Pz" firstAttribute="centerY" secondItem="K5S-Tx-sIQ" secondAttribute="centerY" id="Px7-s5-eIF"/>
+                        <constraint firstItem="kGm-Nx-2wO" firstAttribute="centerY" secondItem="c1J-5D-9Pz" secondAttribute="centerY" id="RgF-dI-1Xs"/>
+                        <constraint firstItem="c1J-5D-9Pz" firstAttribute="leading" secondItem="A0q-wS-bGi" secondAttribute="trailing" constant="12" id="dzN-va-vfN"/>
+                        <constraint firstItem="A0q-wS-bGi" firstAttribute="top" secondItem="bxi-KM-pUe" secondAttribute="top" constant="21" id="h92-O1-eSx"/>
+                        <constraint firstItem="c1J-5D-9Pz" firstAttribute="trailing" secondItem="K5S-Tx-sIQ" secondAttribute="trailing" id="p3Q-W6-3KT"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="bxi-KM-pUe" secondAttribute="bottom" id="3BI-cz-Cpf"/>
+                <constraint firstAttribute="trailing" secondItem="bxi-KM-pUe" secondAttribute="trailing" id="R3i-BE-bIH"/>
+                <constraint firstItem="bxi-KM-pUe" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="jHW-DQ-wPe"/>
+                <constraint firstItem="bxi-KM-pUe" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="tBL-Y7-aCh"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="countLabel" destination="c1J-5D-9Pz" id="fsL-8P-PNo"/>
+                <outlet property="statusImage" destination="A0q-wS-bGi" id="BWs-5G-w3P"/>
+            </connections>
+            <point key="canvasLocation" x="191.6030534351145" y="-40.492957746478872"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="sure_delete_image" width="80" height="30"/>
+        <image name="unChoose_status" width="18" height="18"/>
+    </resources>
+</document>

+ 19 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksDraftsCell.h

@@ -0,0 +1,19 @@
+//
+//  MineWorksDraftsCell.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import <UIKit/UIKit.h>
+#import "UserMusicFormalModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MineWorksDraftsCell : UITableViewCell
+
+- (void)configSourceWithModel:(UserMusicFormalModel *)model isEdit:(BOOL)isEditStatus;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 72 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksDraftsCell.m

@@ -0,0 +1,72 @@
+//
+//  MineWorksDraftsCell.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import "MineWorksDraftsCell.h"
+
+@interface MineWorksDraftsCell ()
+
+@property (weak, nonatomic) IBOutlet UIImageView *chooseStatusImage;
+
+@property (weak, nonatomic) IBOutlet UIImageView *musicCoverImage;
+
+@property (weak, nonatomic) IBOutlet UILabel *musicName;
+
+@property (weak, nonatomic) IBOutlet UILabel *timeLabel;
+
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *chooseImgWidth;
+
+@property (weak, nonatomic) IBOutlet NSLayoutConstraint *chooseImageLeft;
+
+@end
+
+@implementation MineWorksDraftsCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+    self.chooseImgWidth.constant = 0.0f;
+    self.chooseImageLeft.constant = 0.0f;
+    self.chooseStatusImage.hidden = YES;
+}
+
+- (void)configSourceWithModel:(UserMusicFormalModel *)model isEdit:(BOOL)isEditStatus {
+    [self.musicCoverImage sd_setImageWithURL:[NSURL URLWithString:[model.img getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:@"pub_music_placeholder"]];
+    self.musicName.text = [NSString returnNoNullStringWithString:model.musicSheetName];
+    if ([NSString isEmptyString:model.createTime]) {
+        self.timeLabel.text = @"";
+    }
+    else {
+        self.timeLabel.text = [[model.createTime componentsSeparatedByString:@" "] firstObject];
+    }
+    if (isEditStatus) {
+        self.chooseImgWidth.constant = 18.0f;
+        self.chooseImageLeft.constant = 12.0f;
+        self.chooseStatusImage.hidden = NO;
+        NSString *chooseImg = @"";
+        if (model.isChoose) {
+            chooseImg = @"choose_status";
+        }
+        else {
+            chooseImg = @"unChoose_status";
+        }
+        [self.chooseStatusImage setImage:[UIImage imageNamed:chooseImg]];
+    }
+    else {
+        self.chooseImgWidth.constant = 0.0f;
+        self.chooseImageLeft.constant = 0.0f;
+        self.chooseStatusImage.hidden = YES;
+    }
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+@end

+ 132 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksDraftsCell.xib

@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="22155" 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="22131"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="137" id="KGk-i7-Jjw" customClass="MineWorksDraftsCell">
+            <rect key="frame" x="0.0" y="0.0" width="377" height="100"/>
+            <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="377" height="100"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sbM-p5-CSI">
+                        <rect key="frame" x="13" y="12" width="351" height="88"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="music_coverBg" translatesAutoresizingMaskIntoConstraints="NO" id="1jM-kS-ueU">
+                                <rect key="frame" x="19" y="17" width="54" height="54"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="54" id="jKq-VV-rak"/>
+                                    <constraint firstAttribute="height" constant="54" id="nFv-rS-JPO"/>
+                                </constraints>
+                            </imageView>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="pub_music_placeholder" translatesAutoresizingMaskIntoConstraints="NO" id="rxQ-sS-z9K">
+                                <rect key="frame" x="12" y="16" width="56" height="56"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="56" id="Dap-6D-bpO"/>
+                                    <constraint firstAttribute="width" constant="56" id="ImP-Cf-wfa"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="4"/>
+                                    </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="r93-WW-AsM">
+                                <rect key="frame" x="85" y="23" width="147" height="22"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="22" id="ySa-KY-C1W"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
+                                <color key="textColor" red="0.074509803920000006" green="0.078431372550000003" blue="0.08235294118" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="product_play" translatesAutoresizingMaskIntoConstraints="NO" id="eCe-Xb-XFd">
+                                <rect key="frame" x="313" y="34" width="20" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="20" id="VaQ-TC-cFh"/>
+                                    <constraint firstAttribute="width" constant="20" id="sMn-lC-Vws"/>
+                                </constraints>
+                            </imageView>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="2023-04-20" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MCo-vL-Avx">
+                                <rect key="frame" x="101" y="51" width="76.333333333333314" height="16"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                <color key="textColor" red="0.66666666669999997" green="0.66666666669999997" blue="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="time_grey" translatesAutoresizingMaskIntoConstraints="NO" id="WOO-8s-BT6">
+                                <rect key="frame" x="85" y="53" width="12" height="12"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="12" id="luy-vd-w5p"/>
+                                    <constraint firstAttribute="width" constant="12" id="sgZ-Yi-B9C"/>
+                                </constraints>
+                            </imageView>
+                            <imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="unChoose_status" translatesAutoresizingMaskIntoConstraints="NO" id="Gqj-ha-fWI">
+                                <rect key="frame" x="0.0" y="35" width="0.0" height="18"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="18" id="SfZ-3o-c0G"/>
+                                    <constraint firstAttribute="width" id="cIM-pl-ep6"/>
+                                </constraints>
+                            </imageView>
+                        </subviews>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstItem="Gqj-ha-fWI" firstAttribute="leading" secondItem="sbM-p5-CSI" secondAttribute="leading" id="4AR-Vh-8JS"/>
+                            <constraint firstItem="eCe-Xb-XFd" firstAttribute="centerY" secondItem="sbM-p5-CSI" secondAttribute="centerY" id="8ga-hH-ac5"/>
+                            <constraint firstItem="rxQ-sS-z9K" firstAttribute="centerY" secondItem="sbM-p5-CSI" secondAttribute="centerY" id="Aqj-0z-BCc"/>
+                            <constraint firstItem="eCe-Xb-XFd" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="MCo-vL-Avx" secondAttribute="trailing" constant="10" id="BRx-Fv-RTk"/>
+                            <constraint firstItem="WOO-8s-BT6" firstAttribute="top" secondItem="r93-WW-AsM" secondAttribute="bottom" constant="8" id="EUI-Xl-W83"/>
+                            <constraint firstItem="rxQ-sS-z9K" firstAttribute="leading" secondItem="Gqj-ha-fWI" secondAttribute="trailing" constant="12" id="FzA-y3-tKP"/>
+                            <constraint firstItem="rxQ-sS-z9K" firstAttribute="trailing" secondItem="1jM-kS-ueU" secondAttribute="trailing" constant="-5" id="Ij2-7k-M1X"/>
+                            <constraint firstItem="1jM-kS-ueU" firstAttribute="centerY" secondItem="sbM-p5-CSI" secondAttribute="centerY" id="KBD-2t-dV3"/>
+                            <constraint firstItem="MCo-vL-Avx" firstAttribute="centerY" secondItem="WOO-8s-BT6" secondAttribute="centerY" id="KRL-Ut-jDM"/>
+                            <constraint firstItem="r93-WW-AsM" firstAttribute="top" secondItem="sbM-p5-CSI" secondAttribute="top" constant="23" id="gSD-y8-h6X"/>
+                            <constraint firstItem="MCo-vL-Avx" firstAttribute="leading" secondItem="WOO-8s-BT6" secondAttribute="trailing" constant="4" id="gWK-ze-Cac"/>
+                            <constraint firstItem="r93-WW-AsM" firstAttribute="leading" secondItem="1jM-kS-ueU" secondAttribute="trailing" constant="12" id="jtU-xR-hVE"/>
+                            <constraint firstItem="eCe-Xb-XFd" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="r93-WW-AsM" secondAttribute="trailing" constant="10" id="mnY-fn-mZe"/>
+                            <constraint firstAttribute="trailing" secondItem="eCe-Xb-XFd" secondAttribute="trailing" constant="18" id="uXA-wM-5xf"/>
+                            <constraint firstItem="WOO-8s-BT6" firstAttribute="leading" secondItem="r93-WW-AsM" secondAttribute="leading" id="whY-67-po0"/>
+                            <constraint firstItem="Gqj-ha-fWI" firstAttribute="centerY" secondItem="sbM-p5-CSI" secondAttribute="centerY" id="yvt-il-Rz2"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="16"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                </subviews>
+                <constraints>
+                    <constraint firstAttribute="bottom" secondItem="sbM-p5-CSI" secondAttribute="bottom" id="8cN-OE-pt7"/>
+                    <constraint firstItem="sbM-p5-CSI" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="13" id="aI1-xv-OmA"/>
+                    <constraint firstAttribute="trailing" secondItem="sbM-p5-CSI" secondAttribute="trailing" constant="13" id="ajT-AN-Seb"/>
+                    <constraint firstItem="sbM-p5-CSI" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="12" id="lqh-S6-Y8o"/>
+                </constraints>
+            </tableViewCellContentView>
+            <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <connections>
+                <outlet property="chooseImageLeft" destination="4AR-Vh-8JS" id="3ks-8c-Yhx"/>
+                <outlet property="chooseImgWidth" destination="cIM-pl-ep6" id="i1f-qv-Bx3"/>
+                <outlet property="chooseStatusImage" destination="Gqj-ha-fWI" id="ISp-Lu-tyA"/>
+                <outlet property="musicCoverImage" destination="rxQ-sS-z9K" id="efD-11-BDK"/>
+                <outlet property="musicName" destination="r93-WW-AsM" id="7LH-IV-lKm"/>
+                <outlet property="timeLabel" destination="MCo-vL-Avx" id="4oT-ak-gLh"/>
+            </connections>
+            <point key="canvasLocation" x="95.419847328244273" y="43.661971830985919"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="music_coverBg" width="54" height="54"/>
+        <image name="product_play" width="20" height="20"/>
+        <image name="pub_music_placeholder" width="205" height="205"/>
+        <image name="time_grey" width="12" height="12"/>
+        <image name="unChoose_status" width="18" height="18"/>
+    </resources>
+</document>

+ 29 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksNavView.h

@@ -0,0 +1,29 @@
+//
+//  MineWorksNavView.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef void(^WorksNavBack)(BOOL isBack);
+
+@interface MineWorksNavView : UIView
+
+@property (nonatomic, assign) BOOL isEdit;
+
+@property (nonatomic, assign) BOOL showEditButton;
+
++ (instancetype)shareInstance;
+
+- (void)backViewAction:(WorksNavBack)callback;
+
+- (CGFloat)getViewHeight;
+
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 85 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksNavView.m

@@ -0,0 +1,85 @@
+//
+//  MineWorksNavView.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import "MineWorksNavView.h"
+#import "UIView+KSLayer.h"
+
+@interface MineWorksNavView ()
+@property (weak, nonatomic) IBOutlet UIView *editView;
+@property (weak, nonatomic) IBOutlet UIView *titleView;
+@property (weak, nonatomic) IBOutlet UILabel *editLabel;
+
+@property (nonatomic, copy) WorksNavBack callback;
+@property (weak, nonatomic) IBOutlet UIButton *editButton;
+
+@end
+
+@implementation MineWorksNavView
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    self.editView.hidden = YES;
+    self.editButton.userInteractionEnabled = NO;
+    CAGradientLayer *titleLayer = [UIView createGradientLayerFromColor:HexRGBAlpha(0x77FFEF, 0.59) startPoint:CGPointMake(0.89, 1) endColor:HexRGB(0x42CDFF) endPoint:CGPointMake(0.19, 1) bounds:CGRectMake(0, 0, 48, 6)];
+    [self.titleView.layer addSublayer:titleLayer];
+}
++ (instancetype)shareInstance {
+    MineWorksNavView *view = [[[NSBundle mainBundle] loadNibNamed:@"MineWorksNavView" owner:nil options:nil] firstObject];
+    return view;
+}
+
+- (void)backViewAction:(WorksNavBack)callback {
+    if (callback) {
+        self.callback = callback;
+    }
+}
+
+- (IBAction)backAction:(id)sender {
+    if (self.callback) {
+        self.callback(YES);
+    }
+}
+
+- (IBAction)editAction:(id)sender {
+    if (self.callback) {
+        self.callback(NO);
+    }
+}
+
+- (CGFloat)getViewHeight {
+    return kNaviBarHeight;
+}
+
+- (void)setShowEditButton:(BOOL)showEditButton {
+    _showEditButton = showEditButton;
+    if (showEditButton) {
+        self.editView.hidden = NO;
+        self.editButton.userInteractionEnabled = YES;
+    }
+    else {
+        self.editView.hidden = YES;
+        self.editButton.userInteractionEnabled = NO;
+    }
+}
+- (void)setIsEdit:(BOOL)isEdit {
+    _isEdit = isEdit;
+    if (isEdit) {
+        self.editLabel.text = @"退出编辑";
+    }
+    else {
+        self.editLabel.text = @"编辑";
+    }
+}
+/*
+// Only override drawRect: if you perform custom drawing.
+// An empty implementation adversely affects performance during animation.
+- (void)drawRect:(CGRect)rect {
+    // Drawing code
+}
+*/
+
+@end

+ 123 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksNavView.xib

@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="22155" 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="22131"/>
+        <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="MineWorksNavView">
+            <rect key="frame" x="0.0" y="0.0" width="393" height="101"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="YPw-d9-Fo2">
+                    <rect key="frame" x="0.0" y="57" width="393" height="44"/>
+                    <subviews>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mine_worksTitle" translatesAutoresizingMaskIntoConstraints="NO" id="Cum-va-YAQ">
+                            <rect key="frame" x="50" y="12" width="78" height="20"/>
+                        </imageView>
+                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="back_black" translatesAutoresizingMaskIntoConstraints="NO" id="71W-r1-CNZ">
+                            <rect key="frame" x="18" y="12" width="12" height="20"/>
+                        </imageView>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="bO5-ys-7vL">
+                            <rect key="frame" x="0.0" y="0.0" width="44" height="44"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="44" id="xZf-G0-8G7"/>
+                            </constraints>
+                            <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
+                            <connections>
+                                <action selector="backAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="9he-fk-2xN"/>
+                            </connections>
+                        </button>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ts0-Ql-G2n">
+                            <rect key="frame" x="314.33333333333331" y="10" width="66.666666666666686" height="24"/>
+                            <subviews>
+                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="product_edit" translatesAutoresizingMaskIntoConstraints="NO" id="ntZ-0l-n9W">
+                                    <rect key="frame" x="10" y="5" width="14" height="14"/>
+                                    <constraints>
+                                        <constraint firstAttribute="height" constant="14" id="8zL-wu-s80"/>
+                                        <constraint firstAttribute="width" constant="14" id="jUh-ov-XUd"/>
+                                    </constraints>
+                                </imageView>
+                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="编辑" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="C2M-qv-DUp">
+                                    <rect key="frame" x="28" y="2" width="28.666666666666671" height="20"/>
+                                    <fontDescription key="fontDescription" type="system" pointSize="14"/>
+                                    <color key="textColor" red="0.10196078431372549" green="0.64313725490196072" blue="0.54117647058823526" alpha="1" colorSpace="calibratedRGB"/>
+                                    <nil key="highlightedColor"/>
+                                </label>
+                            </subviews>
+                            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
+                            <constraints>
+                                <constraint firstAttribute="bottom" secondItem="C2M-qv-DUp" secondAttribute="bottom" constant="2" id="0XB-Gs-6T9"/>
+                                <constraint firstItem="ntZ-0l-n9W" firstAttribute="centerY" secondItem="ts0-Ql-G2n" secondAttribute="centerY" id="5qT-M5-1qC"/>
+                                <constraint firstItem="C2M-qv-DUp" firstAttribute="top" secondItem="ts0-Ql-G2n" secondAttribute="top" constant="2" id="7hi-JJ-fft"/>
+                                <constraint firstItem="ntZ-0l-n9W" firstAttribute="leading" secondItem="ts0-Ql-G2n" secondAttribute="leading" constant="10" id="SVz-Wf-nfh"/>
+                                <constraint firstAttribute="trailing" secondItem="C2M-qv-DUp" secondAttribute="trailing" constant="10" id="SYZ-lC-1mT"/>
+                                <constraint firstItem="C2M-qv-DUp" firstAttribute="leading" secondItem="ntZ-0l-n9W" secondAttribute="trailing" constant="4" id="SgB-VG-589"/>
+                                <constraint firstAttribute="height" constant="24" id="nQB-Hq-lWZ"/>
+                            </constraints>
+                            <userDefinedRuntimeAttributes>
+                                <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                    <real key="value" value="12"/>
+                                </userDefinedRuntimeAttribute>
+                                <userDefinedRuntimeAttribute type="number" keyPath="borderWidth">
+                                    <real key="value" value="1"/>
+                                </userDefinedRuntimeAttribute>
+                                <userDefinedRuntimeAttribute type="color" keyPath="borderColor">
+                                    <color key="value" red="0.1764705882352941" green="0.7803921568627451" blue="0.66666666666666663" alpha="1" colorSpace="calibratedRGB"/>
+                                </userDefinedRuntimeAttribute>
+                            </userDefinedRuntimeAttributes>
+                        </view>
+                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenHighlighted="NO" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ENM-WF-Mzx">
+                            <rect key="frame" x="314.33333333333331" y="10" width="66.666666666666686" height="24"/>
+                            <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="n9S-c3-L7q"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                    <constraints>
+                        <constraint firstItem="71W-r1-CNZ" firstAttribute="centerY" secondItem="YPw-d9-Fo2" secondAttribute="centerY" id="0OI-xM-daZ"/>
+                        <constraint firstItem="bO5-ys-7vL" firstAttribute="top" secondItem="YPw-d9-Fo2" secondAttribute="top" id="0Wq-0Z-ESW"/>
+                        <constraint firstItem="Cum-va-YAQ" firstAttribute="centerY" secondItem="YPw-d9-Fo2" secondAttribute="centerY" id="5c0-EU-uVv"/>
+                        <constraint firstItem="Cum-va-YAQ" firstAttribute="leading" secondItem="71W-r1-CNZ" secondAttribute="trailing" constant="20" id="6pF-6L-JHO"/>
+                        <constraint firstItem="ENM-WF-Mzx" firstAttribute="bottom" secondItem="ts0-Ql-G2n" secondAttribute="bottom" id="J3e-3M-SLR"/>
+                        <constraint firstItem="bO5-ys-7vL" firstAttribute="leading" secondItem="YPw-d9-Fo2" secondAttribute="leading" id="YX4-Vs-gxk"/>
+                        <constraint firstItem="71W-r1-CNZ" firstAttribute="leading" secondItem="YPw-d9-Fo2" secondAttribute="leading" constant="18" id="dEF-TC-40s"/>
+                        <constraint firstItem="ts0-Ql-G2n" firstAttribute="centerY" secondItem="YPw-d9-Fo2" secondAttribute="centerY" id="dMe-bB-DKQ"/>
+                        <constraint firstItem="ENM-WF-Mzx" firstAttribute="leading" secondItem="ts0-Ql-G2n" secondAttribute="leading" id="lDf-0q-Kz5"/>
+                        <constraint firstAttribute="height" constant="44" id="lE6-HX-AdW"/>
+                        <constraint firstAttribute="trailing" secondItem="ts0-Ql-G2n" secondAttribute="trailing" constant="12" id="qYW-3k-hpo"/>
+                        <constraint firstItem="ENM-WF-Mzx" firstAttribute="trailing" secondItem="ts0-Ql-G2n" secondAttribute="trailing" id="rXf-oC-R77"/>
+                        <constraint firstItem="ENM-WF-Mzx" firstAttribute="top" secondItem="ts0-Ql-G2n" secondAttribute="top" id="suh-Ms-LBC"/>
+                        <constraint firstAttribute="bottom" secondItem="bO5-ys-7vL" secondAttribute="bottom" id="vYe-gB-vjw"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <constraints>
+                <constraint firstAttribute="bottom" secondItem="YPw-d9-Fo2" secondAttribute="bottom" id="EHw-jZ-xvf"/>
+                <constraint firstItem="YPw-d9-Fo2" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Jmb-44-qMa"/>
+                <constraint firstAttribute="trailing" secondItem="YPw-d9-Fo2" secondAttribute="trailing" id="PuV-I8-TPL"/>
+            </constraints>
+            <nil key="simulatedTopBarMetrics"/>
+            <nil key="simulatedBottomBarMetrics"/>
+            <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+            <connections>
+                <outlet property="editButton" destination="ENM-WF-Mzx" id="LPu-MD-8tm"/>
+                <outlet property="editLabel" destination="C2M-qv-DUp" id="Uc0-eX-7lP"/>
+                <outlet property="editView" destination="ts0-Ql-G2n" id="mAx-AK-7hI"/>
+            </connections>
+            <point key="canvasLocation" x="52.671755725190835" y="-5.2816901408450709"/>
+        </view>
+    </objects>
+    <resources>
+        <image name="back_black" width="12" height="20"/>
+        <image name="mine_worksTitle" width="78" height="20"/>
+        <image name="product_edit" width="14" height="14"/>
+    </resources>
+</document>

+ 19 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksOpenDisplayCell.h

@@ -0,0 +1,19 @@
+//
+//  MineWorksOpenDisplayCell.h
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import <UIKit/UIKit.h>
+#import "UserMusicFormalModel.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface MineWorksOpenDisplayCell : UITableViewCell
+
+- (void)configSourceWithModel:(UserMusicFormalModel *)model;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 67 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksOpenDisplayCell.m

@@ -0,0 +1,67 @@
+//
+//  MineWorksOpenDisplayCell.m
+//  KulexiuSchoolStudent
+//
+//  Created by 王智 on 2023/10/31.
+//
+
+#import "MineWorksOpenDisplayCell.h"
+#import "UIView+KSLayer.h"
+
+@interface MineWorksOpenDisplayCell ()
+
+@property (weak, nonatomic) IBOutlet UIImageView *musicCoverImg;
+
+@property (weak, nonatomic) IBOutlet UILabel *musicName;
+
+@property (weak, nonatomic) IBOutlet UILabel *publishTime; // 发布时间
+ 
+@property (weak, nonatomic) IBOutlet UILabel *likeLabel;   // like
+
+@property (weak, nonatomic) IBOutlet UIView *likeView;
+
+@end
+
+@implementation MineWorksOpenDisplayCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+}
+
+- (void)configSourceWithModel:(UserMusicFormalModel *)model {
+    [self.musicCoverImg sd_setImageWithURL:[NSURL URLWithString:[model.img getUrlEndcodeString]] placeholderImage:[UIImage imageNamed:@"pub_music_placeholder"]];
+    self.musicName.text = [NSString returnNoNullStringWithString:model.musicSheetName];
+    if ([NSString isEmptyString:model.submitTime]) {
+        self.publishTime.text = @"";
+    }
+    else {
+        self.publishTime.text = [[model.submitTime componentsSeparatedByString:@" "] firstObject];
+    }
+    NSString *countString = [NSString stringWithFormat:@"%.0f", model.likeNum];
+    self.likeLabel.text = countString;
+    // 设置渐变色
+    [self configGrandLayer:countString];
+}
+
+- (void)configGrandLayer:(NSString *)countString {
+    CGFloat width = [countString boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, 17) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f weight:UIFontWeightMedium]} context:nil].size.width+2 + (18 + 2);
+    [self removeColorLayer];
+    CAGradientLayer *titleLayer = [UIView createGradientLayerFromColor:HexRGBAlpha(0xFF0868, 0.64) startPoint:CGPointMake(0.09, 0.31) endColor:HexRGBAlpha(0xFF0303, 0.64) endPoint:CGPointMake(0.92, 0.75) bounds:CGRectMake(0, 0, width, 17)];
+    [self.likeView.layer addSublayer:titleLayer];
+}
+
+- (void)removeColorLayer {
+    for (CALayer *layer in self.likeView.layer.sublayers) {
+        [layer removeFromSuperlayer];
+    }
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
+    [super setSelected:selected animated:animated];
+
+    // Configure the view for the selected state
+}
+
+@end

+ 151 - 0
KulexiuForTeacher/KulexiuForTeacher/Module/Mine/Works/View/MineWorksOpenDisplayCell.xib

@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="22155" 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="22131"/>
+        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="100" id="KGk-i7-Jjw" customClass="MineWorksOpenDisplayCell">
+            <rect key="frame" x="0.0" y="0.0" width="388" height="100"/>
+            <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="388" height="100"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dg0-fR-1bH">
+                        <rect key="frame" x="13" y="12" width="362" height="88"/>
+                        <subviews>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="music_coverBg" translatesAutoresizingMaskIntoConstraints="NO" id="8WS-Si-IGE">
+                                <rect key="frame" x="19" y="17" width="54" height="54"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="54" id="JEa-sR-MPi"/>
+                                    <constraint firstAttribute="width" constant="54" id="qkM-ak-ksL"/>
+                                </constraints>
+                            </imageView>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="pub_music_placeholder" translatesAutoresizingMaskIntoConstraints="NO" id="Dmr-3m-MAH">
+                                <rect key="frame" x="12" y="16" width="56" height="56"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="56" id="lJD-d9-H69"/>
+                                    <constraint firstAttribute="width" constant="56" id="p1b-kL-7eU"/>
+                                </constraints>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="4"/>
+                                    </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="EaD-CA-BJf">
+                                <rect key="frame" x="83" y="20" width="147" height="22"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="22" id="Da0-04-OcQ"/>
+                                </constraints>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
+                                <color key="textColor" red="0.074509803921568626" green="0.078431372549019607" blue="0.082352941176470587" alpha="1" colorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                            <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="product_play" translatesAutoresizingMaskIntoConstraints="NO" id="DyO-nc-d96">
+                                <rect key="frame" x="324" y="34" width="20" height="20"/>
+                                <constraints>
+                                    <constraint firstAttribute="width" constant="20" id="mzX-4l-RJ2"/>
+                                    <constraint firstAttribute="height" constant="20" id="zy1-NZ-iU5"/>
+                                </constraints>
+                            </imageView>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="6oO-oK-DFO">
+                                <rect key="frame" x="83" y="49" width="42" height="17"/>
+                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <userDefinedRuntimeAttributes>
+                                    <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                        <real key="value" value="4"/>
+                                    </userDefinedRuntimeAttribute>
+                                </userDefinedRuntimeAttributes>
+                            </view>
+                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="puC-Bo-Iu5">
+                                <rect key="frame" x="83" y="49" width="42" height="17"/>
+                                <subviews>
+                                    <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="product_like" translatesAutoresizingMaskIntoConstraints="NO" id="aMR-15-5mD">
+                                        <rect key="frame" x="3" y="2" width="13" height="13"/>
+                                    </imageView>
+                                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="120" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9JC-LI-cTn">
+                                        <rect key="frame" x="18" y="0.0" width="21" height="17"/>
+                                        <fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
+                                        <color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                        <nil key="highlightedColor"/>
+                                    </label>
+                                </subviews>
+                                <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                                <constraints>
+                                    <constraint firstAttribute="height" constant="17" id="PQg-HX-kR8"/>
+                                    <constraint firstItem="aMR-15-5mD" firstAttribute="centerY" secondItem="puC-Bo-Iu5" secondAttribute="centerY" id="VwG-9h-gce"/>
+                                    <constraint firstAttribute="trailing" secondItem="9JC-LI-cTn" secondAttribute="trailing" constant="3" id="eeI-M1-hrr"/>
+                                    <constraint firstAttribute="bottom" secondItem="9JC-LI-cTn" secondAttribute="bottom" id="hFv-zb-p9Y"/>
+                                    <constraint firstItem="aMR-15-5mD" firstAttribute="leading" secondItem="puC-Bo-Iu5" secondAttribute="leading" constant="3" id="nzJ-gY-SIi"/>
+                                    <constraint firstItem="9JC-LI-cTn" firstAttribute="top" secondItem="puC-Bo-Iu5" secondAttribute="top" id="rtw-Es-G9F"/>
+                                    <constraint firstItem="9JC-LI-cTn" firstAttribute="leading" secondItem="aMR-15-5mD" secondAttribute="trailing" constant="2" id="vq0-JY-cr8"/>
+                                </constraints>
+                            </view>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="752" text="2023-04-20" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="olA-a5-JqX">
+                                <rect key="frame" x="134" y="49.666666666666664" width="76.333333333333314" height="15.999999999999993"/>
+                                <fontDescription key="fontDescription" type="system" pointSize="13"/>
+                                <color key="textColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                        </subviews>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                        <constraints>
+                            <constraint firstItem="EaD-CA-BJf" firstAttribute="leading" secondItem="8WS-Si-IGE" secondAttribute="trailing" constant="10" id="0qq-Lb-6SF"/>
+                            <constraint firstItem="8WS-Si-IGE" firstAttribute="leading" secondItem="dg0-fR-1bH" secondAttribute="leading" constant="19" id="6fs-wq-ZsT"/>
+                            <constraint firstItem="olA-a5-JqX" firstAttribute="leading" secondItem="puC-Bo-Iu5" secondAttribute="trailing" constant="9" id="DJD-o6-bed"/>
+                            <constraint firstItem="8WS-Si-IGE" firstAttribute="centerY" secondItem="dg0-fR-1bH" secondAttribute="centerY" id="G9Y-Q6-6LY"/>
+                            <constraint firstItem="DyO-nc-d96" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="olA-a5-JqX" secondAttribute="trailing" constant="10" id="OkQ-gL-GzM"/>
+                            <constraint firstItem="DyO-nc-d96" firstAttribute="centerY" secondItem="dg0-fR-1bH" secondAttribute="centerY" id="RBh-VS-w6p"/>
+                            <constraint firstItem="puC-Bo-Iu5" firstAttribute="leading" secondItem="EaD-CA-BJf" secondAttribute="leading" id="SX1-dQ-Kvd"/>
+                            <constraint firstItem="EaD-CA-BJf" firstAttribute="top" secondItem="dg0-fR-1bH" secondAttribute="top" constant="20" id="SlA-ht-9WB"/>
+                            <constraint firstItem="Dmr-3m-MAH" firstAttribute="leading" secondItem="dg0-fR-1bH" secondAttribute="leading" constant="12" id="X2z-cQ-PwW"/>
+                            <constraint firstItem="puC-Bo-Iu5" firstAttribute="leading" secondItem="6oO-oK-DFO" secondAttribute="leading" id="asf-8h-8y8"/>
+                            <constraint firstItem="puC-Bo-Iu5" firstAttribute="top" secondItem="EaD-CA-BJf" secondAttribute="bottom" constant="7" id="e3V-X8-xht"/>
+                            <constraint firstItem="Dmr-3m-MAH" firstAttribute="centerY" secondItem="dg0-fR-1bH" secondAttribute="centerY" id="fV1-Gc-kDZ"/>
+                            <constraint firstItem="DyO-nc-d96" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="EaD-CA-BJf" secondAttribute="trailing" constant="10" id="hPk-V9-Hq1"/>
+                            <constraint firstItem="puC-Bo-Iu5" firstAttribute="top" secondItem="6oO-oK-DFO" secondAttribute="top" id="lub-yj-j6z"/>
+                            <constraint firstItem="puC-Bo-Iu5" firstAttribute="trailing" secondItem="6oO-oK-DFO" secondAttribute="trailing" id="msR-70-5oX"/>
+                            <constraint firstAttribute="trailing" secondItem="DyO-nc-d96" secondAttribute="trailing" constant="18" id="oaK-yU-qfr"/>
+                            <constraint firstItem="olA-a5-JqX" firstAttribute="centerY" secondItem="puC-Bo-Iu5" secondAttribute="centerY" id="pBK-0I-Kjb"/>
+                            <constraint firstItem="puC-Bo-Iu5" firstAttribute="bottom" secondItem="6oO-oK-DFO" secondAttribute="bottom" id="vkS-6o-1Ue"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="number" keyPath="cornerRadius">
+                                <real key="value" value="16"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                </subviews>
+                <constraints>
+                    <constraint firstAttribute="bottom" secondItem="dg0-fR-1bH" secondAttribute="bottom" id="FDj-hV-kEh"/>
+                    <constraint firstItem="dg0-fR-1bH" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="13" id="MI9-SF-RaG"/>
+                    <constraint firstItem="dg0-fR-1bH" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="12" id="MMy-Vo-38a"/>
+                    <constraint firstAttribute="trailing" secondItem="dg0-fR-1bH" secondAttribute="trailing" constant="13" id="lFf-q5-f2W"/>
+                </constraints>
+            </tableViewCellContentView>
+            <viewLayoutGuide key="safeArea" id="aW0-zy-SZf"/>
+            <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+            <connections>
+                <outlet property="likeLabel" destination="9JC-LI-cTn" id="4XF-N3-n3k"/>
+                <outlet property="likeView" destination="6oO-oK-DFO" id="6TJ-VV-lAm"/>
+                <outlet property="musicCoverImg" destination="Dmr-3m-MAH" id="6Pa-PQ-dRj"/>
+                <outlet property="musicName" destination="EaD-CA-BJf" id="rUI-ik-QCe"/>
+                <outlet property="publishTime" destination="olA-a5-JqX" id="pwO-QV-m9Q"/>
+            </connections>
+            <point key="canvasLocation" x="103.81679389312977" y="12.67605633802817"/>
+        </tableViewCell>
+    </objects>
+    <resources>
+        <image name="music_coverBg" width="54" height="54"/>
+        <image name="product_like" width="13" height="13"/>
+        <image name="product_play" width="20" height="20"/>
+        <image name="pub_music_placeholder" width="205" height="205"/>
+    </resources>
+</document>