Bob 6 anni fa
parent
commit
19cf56510f
100 ha cambiato i file con 3951 aggiunte e 225 eliminazioni
  1. 107 3
      HappyJob/HappyJob.xcodeproj/project.pbxproj
  2. BIN
      HappyJob/HappyJob.xcworkspace/xcuserdata/Bob.xcuserdatad/UserInterfaceState.xcuserstate
  3. 23 0
      HappyJob/HappyJob/Assets.xcassets/Common/loading_image_blue.imageset/Contents.json
  4. BIN
      HappyJob/HappyJob/Assets.xcassets/Common/loading_image_blue.imageset/载入.png
  5. BIN
      HappyJob/HappyJob/Assets.xcassets/Common/loading_image_blue.imageset/载入@2x.png
  6. BIN
      HappyJob/HappyJob/Assets.xcassets/Common/loading_image_blue.imageset/载入@3x.png
  7. 23 0
      HappyJob/HappyJob/Assets.xcassets/Message/msg_blank.imageset/Contents.json
  8. BIN
      HappyJob/HappyJob/Assets.xcassets/Message/msg_blank.imageset/形状 13.png
  9. BIN
      HappyJob/HappyJob/Assets.xcassets/Message/msg_blank.imageset/形状 13@2x.png
  10. BIN
      HappyJob/HappyJob/Assets.xcassets/Message/msg_blank.imageset/形状 13@3x.png
  11. 19 9
      HappyJob/HappyJob/Components/CustomControl/UIView/Error_错误页面/HJErrorView.m
  12. 9 23
      HappyJob/HappyJob/Components/CustomControl/UIView/Loading_加载页面/HJLoadingView.m
  13. 1 0
      HappyJob/HappyJob/Components/CustomControl/UIView/Portrait_头像/HJPortraitView.h
  14. 1 1
      HappyJob/HappyJob/Components/CustomControl/UIView/Portrait_头像/HJPortraitView.m
  15. 17 0
      HappyJob/HappyJob/Components/CustomControl/UIView/Refresh_上拉下拉刷新/HJRefreshFooterView.h
  16. 33 0
      HappyJob/HappyJob/Components/CustomControl/UIView/Refresh_上拉下拉刷新/HJRefreshFooterView.m
  17. 17 0
      HappyJob/HappyJob/Components/CustomControl/UIView/Refresh_上拉下拉刷新/HJRefreshHeaderView.h
  18. 67 0
      HappyJob/HappyJob/Components/CustomControl/UIView/Refresh_上拉下拉刷新/HJRefreshHeaderView.m
  19. 25 0
      HappyJob/HappyJob/Components/FBKit/Category/UIColor/UIColor+FBGetRGBComponents.h
  20. 27 0
      HappyJob/HappyJob/Components/FBKit/Category/UIColor/UIColor+FBGetRGBComponents.m
  21. 24 0
      HappyJob/HappyJob/Components/FBKit/Category/UIImageView+FBRotation.h
  22. 33 0
      HappyJob/HappyJob/Components/FBKit/Category/UIImageView+FBRotation.m
  23. 31 0
      HappyJob/HappyJob/Components/FBKit/FBNavigationBar/FBNavigationBar.h
  24. 34 0
      HappyJob/HappyJob/Components/FBKit/FBNavigationBar/FBNavigationBar.m
  25. 11 0
      HappyJob/HappyJob/Components/FBKit/FBNetworking/FBBaseAPIManager.h
  26. 19 0
      HappyJob/HappyJob/Components/FBKit/XHDate/NSDate+FBBetweenDays.h
  27. 39 0
      HappyJob/HappyJob/Components/FBKit/XHDate/NSDate+FBBetweenDays.m
  28. 1 0
      HappyJob/HappyJob/Components/FBKit/XHDate/XHDate.h
  29. 14 2
      HappyJob/HappyJob/DataCenter/Model/Position/HJPositionModel.h
  30. 2 0
      HappyJob/HappyJob/DataCenter/Model/UserInfo/HJUserInfoModel.h
  31. 74 28
      HappyJob/HappyJob/Home_首页/HJHomeViewController.m
  32. 130 25
      HappyJob/HappyJob/Home_首页/JobList_工作列表信息/FullTime_全职工作/HJFullTimeViewController.m
  33. 130 25
      HappyJob/HappyJob/Home_首页/JobList_工作列表信息/PartTime_兼职工作/HJPartTimeViewController.m
  34. 2 4
      HappyJob/HappyJob/Home_首页/NavBar_头部自定义导航栏/HJNavBarView.h
  35. 4 4
      HappyJob/HappyJob/Home_首页/NavBar_头部自定义导航栏/HJNavBarView.m
  36. 17 0
      HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetFullTimePositionAPIManager.h
  37. 81 0
      HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetFullTimePositionAPIManager.m
  38. 1 1
      HappyJob/HappyJob/Home_首页/HomeAPIManager/HJGetHotPositionAPIManager.h
  39. 80 0
      HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetHotPositionAPIManager.m
  40. 0 0
      HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetPositionDetailAPIManager.h
  41. 0 0
      HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetPositionDetailAPIManager.m
  42. 0 0
      HappyJob/HappyJob/Home_首页/PositionAPIManager/HJPositionDataBox.h
  43. 54 9
      HappyJob/HappyJob/Home_首页/HomeAPIManager/HJPositionDataBox.m
  44. 0 0
      HappyJob/HappyJob/Home_首页/PositionAPIManager/HJPositionDetailDataBox.h
  45. 0 0
      HappyJob/HappyJob/Home_首页/PositionAPIManager/HJPositionDetailDataBox.m
  46. 1 0
      HappyJob/HappyJob/Main_标签栏控制器/HJBaseViewController.h
  47. 10 2
      HappyJob/HappyJob/Main_标签栏控制器/HJBaseViewController.m
  48. 64 38
      HappyJob/HappyJob/Me_我/HJMeViewController.m
  49. 2 0
      HappyJob/HappyJob/Me_我/Header_头视图/HJMeHeaderView.h
  50. 4 6
      HappyJob/HappyJob/Me_我/Header_头视图/HJMeHeaderView.m
  51. 38 30
      HappyJob/HappyJob/Me_我/Header_头视图/HJMeProfileView.m
  52. 17 0
      HappyJob/HappyJob/Me_我/MeAPIManager/HJGetUserInfoAPIManager.h
  53. 8 9
      HappyJob/HappyJob/Home_首页/HomeAPIManager/HJGetHotPositionAPIManager.m
  54. 19 0
      HappyJob/HappyJob/Me_我/MeAPIManager/HJMeDataBox.h
  55. 109 0
      HappyJob/HappyJob/Me_我/MeAPIManager/HJMeDataBox.m
  56. 2 2
      HappyJob/HappyJob/Me_我/NavBar_我的导航栏/HJMeNavBarView.h
  57. 2 0
      HappyJob/HappyJob/Me_我/NavBar_我的导航栏/HJMeNavBarView.m
  58. 16 3
      HappyJob/HappyJob/Message_消息/HJMessageViewController.m
  59. 17 0
      HappyJob/HappyJob/Message_消息/消息空白页/HJMessageBlankView.h
  60. 82 0
      HappyJob/HappyJob/Message_消息/消息空白页/HJMessageBlankView.m
  61. 2 0
      HappyJob/Podfile
  62. 11 1
      HappyJob/Podfile.lock
  63. 19 0
      HappyJob/Pods/MJRefresh/LICENSE
  64. 23 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.h
  65. 154 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.m
  66. 13 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.h
  67. 146 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.m
  68. 107 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.h
  69. 272 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.m
  70. 30 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.h
  71. 80 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.m
  72. 25 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.h
  73. 158 0
      HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.m
  74. 17 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h
  75. 116 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m
  76. 14 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h
  77. 69 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m
  78. 22 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h
  79. 92 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m
  80. 17 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h
  81. 127 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m
  82. 15 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h
  83. 123 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m
  84. 21 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h
  85. 82 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m
  86. 17 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.h
  87. 133 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.m
  88. 15 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.h
  89. 127 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.m
  90. 25 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.h
  91. 167 0
      HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.m
  92. BIN
      HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/arrow@2x.png
  93. 16 0
      HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/en.lproj/Localizable.strings
  94. BIN
      HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hans.lproj/Localizable.strings
  95. 16 0
      HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hant.lproj/Localizable.strings
  96. 14 0
      HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.h
  97. 76 0
      HappyJob/Pods/MJRefresh/MJRefresh/MJRefreshConst.h
  98. 33 0
      HappyJob/Pods/MJRefresh/MJRefresh/MJRefreshConst.m
  99. 16 0
      HappyJob/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.h
  100. 0 0
      HappyJob/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.m

+ 107 - 3
HappyJob/HappyJob.xcodeproj/project.pbxproj

@@ -47,6 +47,16 @@
 		C40F6EEB225E12D30034BEF8 /* HJBenefitViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C40F6EEA225E12D30034BEF8 /* HJBenefitViewController.m */; };
 		C40F6EEE225E13430034BEF8 /* HJBenefitDetailViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C40F6EED225E13430034BEF8 /* HJBenefitDetailViewController.m */; };
 		C40F6EF2225E25B80034BEF8 /* HJBenefitDetailHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = C40F6EF1225E25B80034BEF8 /* HJBenefitDetailHeaderView.m */; };
+		C40FA70122753B6300EB2371 /* HJGetUserInfoAPIManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA70022753B6300EB2371 /* HJGetUserInfoAPIManager.m */; };
+		C40FA70422753C6D00EB2371 /* HJMeDataBox.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA70322753C6D00EB2371 /* HJMeDataBox.m */; };
+		C40FA7082275844100EB2371 /* FBNavigationBar.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA7072275844100EB2371 /* FBNavigationBar.m */; };
+		C40FA70C227590BC00EB2371 /* UIColor+FBGetRGBComponents.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA70B227590BC00EB2371 /* UIColor+FBGetRGBComponents.m */; };
+		C40FA7102275A8E200EB2371 /* HJRefreshHeaderView.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA70F2275A8E200EB2371 /* HJRefreshHeaderView.m */; };
+		C40FA7132275CC8700EB2371 /* NSDate+FBBetweenDays.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA7122275CC8700EB2371 /* NSDate+FBBetweenDays.m */; };
+		C40FA7172275DC6400EB2371 /* HJMessageBlankView.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA7162275DC6400EB2371 /* HJMessageBlankView.m */; };
+		C40FA71A2276A46B00EB2371 /* HJRefreshFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA7192276A46B00EB2371 /* HJRefreshFooterView.m */; };
+		C40FA71D2276E37600EB2371 /* UIImageView+FBRotation.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA71C2276E37600EB2371 /* UIImageView+FBRotation.m */; };
+		C40FA7202277045800EB2371 /* HJGetFullTimePositionAPIManager.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FA71F2277045800EB2371 /* HJGetFullTimePositionAPIManager.m */; };
 		C40FF1E2223F828C008868BF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FF1E1223F828C008868BF /* AppDelegate.m */; };
 		C40FF1E5223F828C008868BF /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = C40FF1E4223F828C008868BF /* ViewController.m */; };
 		C40FF1E8223F828C008868BF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C40FF1E6223F828C008868BF /* Main.storyboard */; };
@@ -244,6 +254,26 @@
 		C40F6EED225E13430034BEF8 /* HJBenefitDetailViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HJBenefitDetailViewController.m; sourceTree = "<group>"; };
 		C40F6EF0225E25B80034BEF8 /* HJBenefitDetailHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HJBenefitDetailHeaderView.h; sourceTree = "<group>"; };
 		C40F6EF1225E25B80034BEF8 /* HJBenefitDetailHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HJBenefitDetailHeaderView.m; sourceTree = "<group>"; };
+		C40FA6FF22753B6300EB2371 /* HJGetUserInfoAPIManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HJGetUserInfoAPIManager.h; sourceTree = "<group>"; };
+		C40FA70022753B6300EB2371 /* HJGetUserInfoAPIManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HJGetUserInfoAPIManager.m; sourceTree = "<group>"; };
+		C40FA70222753C6D00EB2371 /* HJMeDataBox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HJMeDataBox.h; sourceTree = "<group>"; };
+		C40FA70322753C6D00EB2371 /* HJMeDataBox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HJMeDataBox.m; sourceTree = "<group>"; };
+		C40FA7062275844100EB2371 /* FBNavigationBar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBNavigationBar.h; sourceTree = "<group>"; };
+		C40FA7072275844100EB2371 /* FBNavigationBar.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBNavigationBar.m; sourceTree = "<group>"; };
+		C40FA70A227590BC00EB2371 /* UIColor+FBGetRGBComponents.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIColor+FBGetRGBComponents.h"; sourceTree = "<group>"; };
+		C40FA70B227590BC00EB2371 /* UIColor+FBGetRGBComponents.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIColor+FBGetRGBComponents.m"; sourceTree = "<group>"; };
+		C40FA70E2275A8E200EB2371 /* HJRefreshHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HJRefreshHeaderView.h; sourceTree = "<group>"; };
+		C40FA70F2275A8E200EB2371 /* HJRefreshHeaderView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HJRefreshHeaderView.m; sourceTree = "<group>"; };
+		C40FA7112275CC8700EB2371 /* NSDate+FBBetweenDays.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDate+FBBetweenDays.h"; sourceTree = "<group>"; };
+		C40FA7122275CC8700EB2371 /* NSDate+FBBetweenDays.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSDate+FBBetweenDays.m"; sourceTree = "<group>"; };
+		C40FA7152275DC6400EB2371 /* HJMessageBlankView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HJMessageBlankView.h; sourceTree = "<group>"; };
+		C40FA7162275DC6400EB2371 /* HJMessageBlankView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HJMessageBlankView.m; sourceTree = "<group>"; };
+		C40FA7182276A46A00EB2371 /* HJRefreshFooterView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HJRefreshFooterView.h; sourceTree = "<group>"; };
+		C40FA7192276A46B00EB2371 /* HJRefreshFooterView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HJRefreshFooterView.m; sourceTree = "<group>"; };
+		C40FA71B2276E37600EB2371 /* UIImageView+FBRotation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIImageView+FBRotation.h"; sourceTree = "<group>"; };
+		C40FA71C2276E37600EB2371 /* UIImageView+FBRotation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+FBRotation.m"; sourceTree = "<group>"; };
+		C40FA71E2277045800EB2371 /* HJGetFullTimePositionAPIManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HJGetFullTimePositionAPIManager.h; sourceTree = "<group>"; };
+		C40FA71F2277045800EB2371 /* HJGetFullTimePositionAPIManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HJGetFullTimePositionAPIManager.m; sourceTree = "<group>"; };
 		C40FF1DD223F828C008868BF /* HappyJob.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HappyJob.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		C40FF1E0223F828C008868BF /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
 		C40FF1E1223F828C008868BF /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
@@ -621,7 +651,7 @@
 			path = "Loading_加载页面";
 			sourceTree = "<group>";
 		};
-		C40E8F0D226DC13700F3900A /* HomeAPIManager */ = {
+		C40E8F0D226DC13700F3900A /* PositionAPIManager */ = {
 			isa = PBXGroup;
 			children = (
 				C40E8F0E226DC23000F3900A /* HJGetHotPositionAPIManager.h */,
@@ -632,8 +662,10 @@
 				C410F0802272DD75002A397C /* HJGetPositionDetailAPIManager.m */,
 				C410F0822272E9B1002A397C /* HJPositionDetailDataBox.h */,
 				C410F0832272E9B1002A397C /* HJPositionDetailDataBox.m */,
+				C40FA71E2277045800EB2371 /* HJGetFullTimePositionAPIManager.h */,
+				C40FA71F2277045800EB2371 /* HJGetFullTimePositionAPIManager.m */,
 			);
-			path = HomeAPIManager;
+			path = PositionAPIManager;
 			sourceTree = "<group>";
 		};
 		C40F6EE8225E10FC0034BEF8 /* Benefit_福利岗位 */ = {
@@ -649,6 +681,55 @@
 			path = "Benefit_福利岗位";
 			sourceTree = "<group>";
 		};
+		C40FA6FE22753AE200EB2371 /* MeAPIManager */ = {
+			isa = PBXGroup;
+			children = (
+				C40FA6FF22753B6300EB2371 /* HJGetUserInfoAPIManager.h */,
+				C40FA70022753B6300EB2371 /* HJGetUserInfoAPIManager.m */,
+				C40FA70222753C6D00EB2371 /* HJMeDataBox.h */,
+				C40FA70322753C6D00EB2371 /* HJMeDataBox.m */,
+			);
+			path = MeAPIManager;
+			sourceTree = "<group>";
+		};
+		C40FA705227583B300EB2371 /* FBNavigationBar */ = {
+			isa = PBXGroup;
+			children = (
+				C40FA7062275844100EB2371 /* FBNavigationBar.h */,
+				C40FA7072275844100EB2371 /* FBNavigationBar.m */,
+			);
+			path = FBNavigationBar;
+			sourceTree = "<group>";
+		};
+		C40FA7092275907800EB2371 /* UIColor */ = {
+			isa = PBXGroup;
+			children = (
+				C40FA70A227590BC00EB2371 /* UIColor+FBGetRGBComponents.h */,
+				C40FA70B227590BC00EB2371 /* UIColor+FBGetRGBComponents.m */,
+			);
+			path = UIColor;
+			sourceTree = "<group>";
+		};
+		C40FA70D2275A83B00EB2371 /* Refresh_上拉下拉刷新 */ = {
+			isa = PBXGroup;
+			children = (
+				C40FA70E2275A8E200EB2371 /* HJRefreshHeaderView.h */,
+				C40FA70F2275A8E200EB2371 /* HJRefreshHeaderView.m */,
+				C40FA7182276A46A00EB2371 /* HJRefreshFooterView.h */,
+				C40FA7192276A46B00EB2371 /* HJRefreshFooterView.m */,
+			);
+			path = "Refresh_上拉下拉刷新";
+			sourceTree = "<group>";
+		};
+		C40FA7142275DBFA00EB2371 /* 消息空白页 */ = {
+			isa = PBXGroup;
+			children = (
+				C40FA7152275DC6400EB2371 /* HJMessageBlankView.h */,
+				C40FA7162275DC6400EB2371 /* HJMessageBlankView.m */,
+			);
+			path = "消息空白页";
+			sourceTree = "<group>";
+		};
 		C40FF1D4223F828C008868BF = {
 			isa = PBXGroup;
 			children = (
@@ -696,6 +777,7 @@
 		C40FF207223F86C0008868BF /* Category */ = {
 			isa = PBXGroup;
 			children = (
+				C40FA7092275907800EB2371 /* UIColor */,
 				C4158F60225C83B300A7B1E5 /* NSString */,
 				C4F657AF224DC6E500E1E625 /* UIView */,
 				C40AEC6922426E0600A9EA23 /* UIButton */,
@@ -703,6 +785,8 @@
 				C40FF20C223F86C0008868BF /* UIDevice+FBAdd.m */,
 				C40AEC7022434E8D00A9EA23 /* UIImage+FBColorToImage.h */,
 				C40AEC7122434E8D00A9EA23 /* UIImage+FBColorToImage.m */,
+				C40FA71B2276E37600EB2371 /* UIImageView+FBRotation.h */,
+				C40FA71C2276E37600EB2371 /* UIImageView+FBRotation.m */,
 			);
 			path = Category;
 			sourceTree = "<group>";
@@ -710,6 +794,7 @@
 		C40FF214223F86F3008868BF /* Message_消息 */ = {
 			isa = PBXGroup;
 			children = (
+				C40FA7142275DBFA00EB2371 /* 消息空白页 */,
 				C40FF216223F86F3008868BF /* HJMessageViewController.h */,
 				C40FF215223F86F3008868BF /* HJMessageViewController.m */,
 				C414D8962267070F00719CE0 /* HJMessageTableViewCell.h */,
@@ -725,6 +810,7 @@
 		C40FF217223F86F3008868BF /* Me_我 */ = {
 			isa = PBXGroup;
 			children = (
+				C40FA6FE22753AE200EB2371 /* MeAPIManager */,
 				C412B22122699B6F002B0C44 /* Auth_实名认证 */,
 				C49DB94822681749000D8AFE /* Header_头视图 */,
 				C49DB94422680CCB000D8AFE /* NavBar_我的导航栏 */,
@@ -759,7 +845,7 @@
 		C40FF21D223F86F4008868BF /* Home_首页 */ = {
 			isa = PBXGroup;
 			children = (
-				C40E8F0D226DC13700F3900A /* HomeAPIManager */,
+				C40E8F0D226DC13700F3900A /* PositionAPIManager */,
 				C40FF226223F86F4008868BF /* JobList_工作列表信息 */,
 				C40AEC452240EF9D00A9EA23 /* City_城市定位 */,
 				C40FF21E223F86F4008868BF /* JobSort_分类信息 */,
@@ -889,6 +975,7 @@
 		C410F08C22730610002A397C /* FBKit */ = {
 			isa = PBXGroup;
 			children = (
+				C40FA705227583B300EB2371 /* FBNavigationBar */,
 				C410F08D227306EE002A397C /* FBLabel */,
 				C40FF207223F86C0008868BF /* Category */,
 				C4FB5CE82271BC160004010F /* XHDate */,
@@ -995,6 +1082,7 @@
 		C413FCBC22547BFA00BEE4F0 /* UIView */ = {
 			isa = PBXGroup;
 			children = (
+				C40FA70D2275A83B00EB2371 /* Refresh_上拉下拉刷新 */,
 				C4FB5CE22271B3A50004010F /* Cell_岗位列表样式 */,
 				C40E8F06226DA8FC00F3900A /* Loading_加载页面 */,
 				C40E8F05226DA88F00F3900A /* Error_错误页面 */,
@@ -1303,6 +1391,8 @@
 				C4FB5CEC2271BC160004010F /* NSString+XHDateFormat.m */,
 				C4FB5CED2271BC160004010F /* NSDate+XHCategory.h */,
 				C4FB5CEA2271BC160004010F /* NSDate+XHCategory.m */,
+				C40FA7112275CC8700EB2371 /* NSDate+FBBetweenDays.h */,
+				C40FA7122275CC8700EB2371 /* NSDate+FBBetweenDays.m */,
 			);
 			path = XHDate;
 			sourceTree = "<group>";
@@ -1408,8 +1498,10 @@
 				"${BUILT_PRODUCTS_DIR}/DDGBannerScrollView/DDGBannerScrollView.framework",
 				"${BUILT_PRODUCTS_DIR}/FCUUID/FCUUID.framework",
 				"${BUILT_PRODUCTS_DIR}/IQKeyboardManager/IQKeyboardManager.framework",
+				"${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework",
 				"${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework",
 				"${BUILT_PRODUCTS_DIR}/NSDictionary-NilSafe/NSDictionary_NilSafe.framework",
+				"${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework",
 				"${BUILT_PRODUCTS_DIR}/SGEasyButton/SGEasyButton.framework",
 				"${BUILT_PRODUCTS_DIR}/SVProgressHUD/SVProgressHUD.framework",
 				"${BUILT_PRODUCTS_DIR}/TXScrollLabelView/TXScrollLabelView.framework",
@@ -1426,8 +1518,10 @@
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DDGBannerScrollView.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FCUUID.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IQKeyboardManager.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/NSDictionary_NilSafe.framework",
+				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SGEasyButton.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SVProgressHUD.framework",
 				"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TXScrollLabelView.framework",
@@ -1477,15 +1571,19 @@
 				C40F6EE4225DF0F80034BEF8 /* HJJoinApplyingViewController.m in Sources */,
 				C40FF247223F86F4008868BF /* HJScrollView.m in Sources */,
 				C49DB95822687CC9000D8AFE /* HJMeResumeView.m in Sources */,
+				C40FA70C227590BC00EB2371 /* UIColor+FBGetRGBComponents.m in Sources */,
 				C4158F42225B269500A7B1E5 /* HJJoinAllJoinPanelViewController.m in Sources */,
 				C412B2272269AC10002B0C44 /* HJAuthSuccessViewController.m in Sources */,
+				C40FA7172275DC6400EB2371 /* HJMessageBlankView.m in Sources */,
 				C4FB5CE52271B40D0004010F /* HJPartTimeCellView.m in Sources */,
 				C4158F52225B479D00A7B1E5 /* HJJoinDetailHeaderView.m in Sources */,
 				C414D8952266F61F00719CE0 /* HJExperienceView.m in Sources */,
+				C40FA71A2276A46B00EB2371 /* HJRefreshFooterView.m in Sources */,
 				C49612D52265AB5700898E55 /* HJProfileViewController.m in Sources */,
 				C40AEC6222424A2800A9EA23 /* HJJobPickerMenuPopButton.m in Sources */,
 				C4FB5CF22271BC160004010F /* NSDateComponents+XHCategory.m in Sources */,
 				C40AEC6F224330A800A9EA23 /* HJJobPickerMenuTagButton.m in Sources */,
+				C40FA7202277045800EB2371 /* HJGetFullTimePositionAPIManager.m in Sources */,
 				C40CA4412244A35400F303A6 /* HJJobDetailForwardView.m in Sources */,
 				C40E8F04226D9AA700F3900A /* HJHomeHeaderView.m in Sources */,
 				C413FCC2225480DE00BEE4F0 /* HJClockLabel.m in Sources */,
@@ -1510,6 +1608,7 @@
 				C413FCB822545A5600BEE4F0 /* UILabel+HJWelfareTagLabel.m in Sources */,
 				C419B3A32255EB4600572A58 /* HJJoinDetailContentView.m in Sources */,
 				C40FF242223F86F4008868BF /* HJMessageViewController.m in Sources */,
+				C40FA7102275A8E200EB2371 /* HJRefreshHeaderView.m in Sources */,
 				C4158F48225B332000A7B1E5 /* HJJoinAllJoinTableViewCell.m in Sources */,
 				C40FF213223F86C0008868BF /* UIView+AZGradient.m in Sources */,
 				C40FF24F223F86F4008868BF /* HJSearchViewController.m in Sources */,
@@ -1527,6 +1626,7 @@
 				C49612BE2264955D00898E55 /* HJLabelTextFieldView.m in Sources */,
 				C4F657AE224DC4F700E1E625 /* UIView+FBProgressHUD.m in Sources */,
 				C40AEC5F2242044A00A9EA23 /* NSString+FBBoundingSize.m in Sources */,
+				C40FA70122753B6300EB2371 /* HJGetUserInfoAPIManager.m in Sources */,
 				C4129F16224B5ADA00E762D5 /* HJCityPickerHotCell.m in Sources */,
 				C40FF1F0223F828E008868BF /* main.m in Sources */,
 				C4147EE02255A58C00F13FD6 /* HJLeftRightLabelView.m in Sources */,
@@ -1577,7 +1677,9 @@
 				C49DB94722680D78000D8AFE /* HJMeNavBarView.m in Sources */,
 				C40AEC412240C0DA00A9EA23 /* HJSearchHotView.m in Sources */,
 				C4FB5CE12271A1970004010F /* HJCompanyModel.m in Sources */,
+				C40FA7082275844100EB2371 /* FBNavigationBar.m in Sources */,
 				C413FCBB22545EE500BEE4F0 /* HJMaxMoneyLabel.m in Sources */,
+				C40FA71D2276E37600EB2371 /* UIImageView+FBRotation.m in Sources */,
 				C40E8F09226DA96000F3900A /* HJErrorView.m in Sources */,
 				C4F657A4224CF57900E1E625 /* FBBaseAPIManager.m in Sources */,
 				C414D8832266B51500719CE0 /* HJResumeViewController.m in Sources */,
@@ -1603,6 +1705,7 @@
 				C410F0872272EB2B002A397C /* HJFullTimeDetailHeaderView.m in Sources */,
 				C4158F5F225C806100A7B1E5 /* HJCornerRadiusView.m in Sources */,
 				C40FF250223F86F4008868BF /* HJMainViewController.m in Sources */,
+				C40FA70422753C6D00EB2371 /* HJMeDataBox.m in Sources */,
 				C4158F6F225CAD1F00A7B1E5 /* HJJoinApplyFailedViewController.m in Sources */,
 				C40E8F16226DCFAF00F3900A /* HJLoginBindingPhoneAPIManager.m in Sources */,
 				C417DE2E225EDE95003853B7 /* HJJoinShareImageView.m in Sources */,
@@ -1614,6 +1717,7 @@
 				C40AEC582241DA9300A9EA23 /* HJBaseViewController.m in Sources */,
 				C414D8982267070F00719CE0 /* HJMessageTableViewCell.m in Sources */,
 				C414D8892266C11400719CE0 /* HJProfileView.m in Sources */,
+				C40FA7132275CC8700EB2371 /* NSDate+FBBetweenDays.m in Sources */,
 				C4158F4C225B42FF00A7B1E5 /* HJJoinApplyViewController.m in Sources */,
 				C40FF210223F86C0008868BF /* UIButton+Layout.m in Sources */,
 				C40AEC4B224116E600A9EA23 /* HJCityPickerSectionIndexListView.m in Sources */,

BIN
HappyJob/HappyJob.xcworkspace/xcuserdata/Bob.xcuserdatad/UserInterfaceState.xcuserstate


+ 23 - 0
HappyJob/HappyJob/Assets.xcassets/Common/loading_image_blue.imageset/Contents.json

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

BIN
HappyJob/HappyJob/Assets.xcassets/Common/loading_image_blue.imageset/载入.png


BIN
HappyJob/HappyJob/Assets.xcassets/Common/loading_image_blue.imageset/载入@2x.png


BIN
HappyJob/HappyJob/Assets.xcassets/Common/loading_image_blue.imageset/载入@3x.png


+ 23 - 0
HappyJob/HappyJob/Assets.xcassets/Message/msg_blank.imageset/Contents.json

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

BIN
HappyJob/HappyJob/Assets.xcassets/Message/msg_blank.imageset/形状 13.png


BIN
HappyJob/HappyJob/Assets.xcassets/Message/msg_blank.imageset/形状 13@2x.png


BIN
HappyJob/HappyJob/Assets.xcassets/Message/msg_blank.imageset/形状 13@3x.png


+ 19 - 9
HappyJob/HappyJob/Components/CustomControl/UIView/Error_错误页面/HJErrorView.m

@@ -10,6 +10,7 @@
 #import "UIImage+FBColorToImage.h"
 
 @interface HJErrorView ()
+@property (nonatomic, strong) UIView *canvasView;
 @property (nonatomic, strong) UIImageView *imageView;
 @property (nonatomic, strong) UILabel *label;
 @end
@@ -20,9 +21,10 @@
     if (self = [super init]) {
         self.backgroundColor = [UIColor whiteColor];
         
-        [self addSubview:self.imageView];
-        [self addSubview:self.label];
-        [self addSubview:self.refreshButton];
+        [self addSubview:self.canvasView];
+        [self.canvasView addSubview:self.imageView];
+        [self.canvasView addSubview:self.label];
+        [self.canvasView addSubview:self.refreshButton];
         
         [self makeConstraints];
     }
@@ -31,27 +33,35 @@
 
 - (void)makeConstraints {
     [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.top.equalTo(self);
-        make.centerX.equalTo(self);
+        make.top.equalTo(self.canvasView);
+        make.centerX.equalTo(self.canvasView);
         make.size.mas_equalTo(CGSizeMake(HJHorizontalScale(self.imageView.image.size.width), HJHorizontalScale(self.imageView.image.size.height)));
     }];
     [self.label mas_makeConstraints:^(MASConstraintMaker *make) {
         make.top.equalTo(self.imageView.mas_bottom).with.offset(50);
-        make.centerX.equalTo(self);
+        make.centerX.equalTo(self.canvasView);
     }];
     [self.refreshButton mas_makeConstraints:^(MASConstraintMaker *make) {
         make.top.equalTo(self.label.mas_bottom).with.offset(30);
-        make.centerX.equalTo(self);
+        make.centerX.equalTo(self.canvasView);
         make.size.mas_equalTo(CGSizeMake(120, 34));
     }];
-    [self mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.width.mas_equalTo(self.imageView.image.size.width);
+    [self.canvasView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.center.equalTo(self);
+        make.width.mas_equalTo(HJHorizontalScale(self.imageView.image.size.width));
         make.bottom.equalTo(self.refreshButton);
     }];
 }
 
 #pragma mark - getters and setters
 
+- (UIView *)canvasView {
+    if (_canvasView == nil) {
+        _canvasView = [[UIView alloc] init];
+    }
+    return _canvasView;
+}
+
 - (UIImageView *)imageView {
     if (_imageView == nil) {
         _imageView = [[UIImageView alloc] init];

+ 9 - 23
HappyJob/HappyJob/Components/CustomControl/UIView/Loading_加载页面/HJLoadingView.m

@@ -7,27 +7,23 @@
 //
 
 #import "HJLoadingView.h"
+#import "UIImageView+FBRotation.h"
 
 @interface HJLoadingView ()
 @property (nonatomic, strong) UIImageView *imageView;
-@property (nonatomic, assign) CGFloat angle;
 @end
 
 @implementation HJLoadingView
 
 - (instancetype)init {
     if (self = [super init]) {
-        self.backgroundColor = [UIColor colorWithRed:81/255.0 green:145/255.0 blue:211/255.0 alpha:1.0];
-        self.frame = CGRectMake(0, 0, 62, 62);
-        self.layer.cornerRadius = 31;
-        self.layer.masksToBounds = YES;
-        _angle = 0;
+        self.backgroundColor = [UIColor whiteColor];
         
         [self addSubview:self.imageView];
         [self makeConstraints];
         
         // 开始旋转
-        [self startAnimation];
+        [self.imageView fb_startAnimation];
     }
     return self;
 }
@@ -35,22 +31,7 @@
 - (void)makeConstraints {
     [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
         make.center.equalTo(self);
-        make.size.mas_equalTo(CGSizeMake(32, 32));
-    }];
-    [self mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.size.mas_equalTo(self.frame.size);
-    }];
-}
-
-#pragma mark - private methods
-
-- (void)startAnimation {
-    CGAffineTransform endAngle = CGAffineTransformMakeRotation(self.angle * (M_PI /180.0f));
-    [UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
-        self.imageView.transform = endAngle;
-    } completion:^(BOOL finished) {
-        self.angle -= 15;// 旋转速度的快慢
-        [self startAnimation];
+        make.size.mas_equalTo(self.imageView.frame.size);
     }];
 }
 
@@ -60,6 +41,11 @@
     if (_imageView == nil) {
         _imageView = [[UIImageView alloc] init];
         _imageView.image = [UIImage imageNamed:@"loading_image_white"];
+        _imageView.contentMode = UIViewContentModeCenter;
+        _imageView.backgroundColor = [UIColor colorWithRed:81/255.0 green:145/255.0 blue:211/255.0 alpha:1.0];
+        _imageView.frame = CGRectMake(0, 0, 62, 62);
+        _imageView.layer.cornerRadius = 31;
+        _imageView.layer.masksToBounds = YES;
     }
     return _imageView;
 }

+ 1 - 0
HappyJob/HappyJob/Components/CustomControl/UIView/Portrait_头像/HJPortraitView.h

@@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface HJPortraitView : UIView
 @property (nonatomic, strong) UIImage *image;
+@property (nonatomic, strong) UIImageView *imageView;
 @end
 
 NS_ASSUME_NONNULL_END

+ 1 - 1
HappyJob/HappyJob/Components/CustomControl/UIView/Portrait_头像/HJPortraitView.m

@@ -9,7 +9,7 @@
 #import "HJPortraitView.h"
 
 @interface HJPortraitView ()
-@property (nonatomic, strong) UIImageView *imageView;
+
 @end
 
 @implementation HJPortraitView

+ 17 - 0
HappyJob/HappyJob/Components/CustomControl/UIView/Refresh_上拉下拉刷新/HJRefreshFooterView.h

@@ -0,0 +1,17 @@
+//
+//  HJRefreshFooterView.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/29.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import <MJRefresh/MJRefresh.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HJRefreshFooterView : MJRefreshAutoNormalFooter
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 33 - 0
HappyJob/HappyJob/Components/CustomControl/UIView/Refresh_上拉下拉刷新/HJRefreshFooterView.m

@@ -0,0 +1,33 @@
+//
+//  HJRefreshFooterView.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/29.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "HJRefreshFooterView.h"
+
+@implementation HJRefreshFooterView
+
+- (void)setState:(MJRefreshState)state {
+    MJRefreshCheckState;
+    
+    switch (state) {
+        case MJRefreshStateIdle:
+            self.stateLabel.text = @"点击或上拉加載更多";
+            break;
+        case MJRefreshStatePulling:
+            self.stateLabel.text = @"松开立即加載更多";
+            break;
+        case MJRefreshStateRefreshing:
+            self.stateLabel.text = @"数据加载中...";
+            break;
+        case MJRefreshStateNoMoreData:
+            self.stateLabel.text = @"亲,我是有底线的哟";
+        default:
+            break;
+    }
+}
+
+@end

+ 17 - 0
HappyJob/HappyJob/Components/CustomControl/UIView/Refresh_上拉下拉刷新/HJRefreshHeaderView.h

@@ -0,0 +1,17 @@
+//
+//  HJRefreshHeaderView.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import <MJRefresh/MJRefresh.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HJRefreshHeaderView : MJRefreshHeader
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 67 - 0
HappyJob/HappyJob/Components/CustomControl/UIView/Refresh_上拉下拉刷新/HJRefreshHeaderView.m

@@ -0,0 +1,67 @@
+//
+//  HJRefreshHeaderView.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "HJRefreshHeaderView.h"
+#import "UIImageView+FBRotation.h"
+
+@interface HJRefreshHeaderView ()
+@property (nonatomic, strong) UIImageView *imageView;
+@end
+
+@implementation HJRefreshHeaderView
+
+- (instancetype)init {
+    if (self = [super init]) {
+        self.backgroundColor = [UIColor whiteColor];
+        // 设置控件的高度
+        self.mj_h = 50 + SCREEN_STATUSBAR_HEIGHT;
+        
+        [self addSubview:self.imageView];
+        [self makeConstraints];
+    }
+    return self;
+}
+
+- (void)makeConstraints {
+    [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.centerX.equalTo(self);
+        make.bottom.equalTo(self).with.offset(-10);
+        make.size.mas_equalTo(CGSizeMake(30, 30));
+    }];
+}
+
+- (void)setState:(MJRefreshState)state {
+    MJRefreshCheckState;
+    
+    switch (state) {
+        case MJRefreshStateIdle:
+            [self.imageView fb_stopAnimation];
+            break;
+        case MJRefreshStatePulling:
+            [self.imageView fb_stopAnimation];
+            break;
+        case MJRefreshStateRefreshing:
+            // 开始旋转
+            [self.imageView fb_startAnimation];
+            break;
+        default:
+            break;
+    }
+}
+
+#pragma mark - getters and setters
+
+- (UIImageView *)imageView {
+    if (_imageView == nil) {
+        _imageView = [[UIImageView alloc] init];
+        _imageView.image = [UIImage imageNamed:@"loading_image_blue"];
+    }
+    return _imageView;
+}
+
+@end

+ 25 - 0
HappyJob/HappyJob/Components/FBKit/Category/UIColor/UIColor+FBGetRGBComponents.h

@@ -0,0 +1,25 @@
+//
+//  UIColor+FBGetRGBComponents.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef struct {
+    CGFloat R;
+    CGFloat G;
+    CGFloat B;
+} FBColorStruct;
+
+@interface UIColor (FBGetRGBComponents)
+
+- (FBColorStruct)getRGB;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 27 - 0
HappyJob/HappyJob/Components/FBKit/Category/UIColor/UIColor+FBGetRGBComponents.m

@@ -0,0 +1,27 @@
+//
+//  UIColor+FBGetRGBComponents.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "UIColor+FBGetRGBComponents.h"
+
+@implementation UIColor (FBGetRGBComponents)
+
+/** CGColorGetComponents方法可以获取RGB值,但不能获取黑白以及灰色的值(他们是非RGB颜色空间,不清楚什么意思,反正亲测确实获取不了)*/
+- (FBColorStruct)getRGB {
+    FBColorStruct colorStruct;
+    
+    // 普通颜色可以通过 这个方法获取的RGBA的值
+    // 颜色空间是固定的,对应RGBA
+    const CGFloat *cmp = CGColorGetComponents(self.CGColor);
+    colorStruct.R = cmp[0];
+    colorStruct.G = cmp[1];
+    colorStruct.B = cmp[2];
+
+    return colorStruct;
+}
+
+@end

+ 24 - 0
HappyJob/HappyJob/Components/FBKit/Category/UIImageView+FBRotation.h

@@ -0,0 +1,24 @@
+//
+//  UIImageView+FBRotation.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/29.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface UIImageView (FBRotation)
+
+- (void)fb_startAnimation;
+/**
+ @param speed 旋转速度的快慢,值越大转得越快。
+ */
+- (void)fb_startAnimationWithSpeed:(CGFloat)speed;
+- (void)fb_stopAnimation;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 33 - 0
HappyJob/HappyJob/Components/FBKit/Category/UIImageView+FBRotation.m

@@ -0,0 +1,33 @@
+//
+//  UIImageView+FBRotation.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/29.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "UIImageView+FBRotation.h"
+
+@implementation UIImageView (FBRotation)
+
+- (void)fb_startAnimation {
+    CGFloat speed = 1.0;
+    [self fb_startAnimationWithSpeed:speed];
+}
+
+- (void)fb_startAnimationWithSpeed:(CGFloat)speed {
+    CABasicAnimation *rotationAnimation;
+    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
+    // 默认是逆时针效果,若将fromValue和toValue的值互换,则为顺时针效果
+    rotationAnimation.fromValue = [NSNumber numberWithFloat:M_PI*speed];
+    rotationAnimation.toValue = [NSNumber numberWithFloat:0.f];
+    rotationAnimation.duration = 1;
+    rotationAnimation.repeatCount = HUGE_VALF;
+    [self.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
+}
+
+- (void)fb_stopAnimation {
+    [self.layer removeAllAnimations];
+}
+
+@end

+ 31 - 0
HappyJob/HappyJob/Components/FBKit/FBNavigationBar/FBNavigationBar.h

@@ -0,0 +1,31 @@
+//
+//  FBNavigationBar.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface FBNavigationBar : UIView
+
+/**
+ 该方法一般和UIScrollView配合使用,根据它的contentOffset属性对导航栏做背景透明。
+ 
+ @param contentOffset UIScrollView的contentOffset属性。
+ */
+- (void)shadeBackgroundColorWithContentOffset:(CGPoint)contentOffset;
+
+/**
+ 设置导航栏背景透明。
+ 
+ @param alpha alpha的值通常是[0 - 1]的范围。
+ */
+- (void)shadeBackgroundColorWithAlpha:(CGFloat)alpha;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 34 - 0
HappyJob/HappyJob/Components/FBKit/FBNavigationBar/FBNavigationBar.m

@@ -0,0 +1,34 @@
+//
+//  FBNavigationBar.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "FBNavigationBar.h"
+#import "UIColor+FBGetRGBComponents.h"
+
+@implementation FBNavigationBar
+
+- (void)shadeBackgroundColorWithContentOffset:(CGPoint)contentOffset {
+    CGFloat contentYoffset = contentOffset.y;
+    // contentOffset在Y轴的偏移量是负数,则隐藏导航栏
+    self.hidden = (contentYoffset < 0) ? YES : NO;
+    
+    // 让导航条背景色的透明度变化 100是范围 越大渐变越慢
+    CGFloat alpha = contentYoffset / 100;
+    
+    [self shadeBackgroundColorWithAlpha:alpha];
+}
+
+- (void)shadeBackgroundColorWithAlpha:(CGFloat)alpha {
+    // alpha的值通常是[0 - 1]的范围
+    CGFloat aAlpha = fminf(1, fmaxf(alpha, 0));
+    
+    // 获取默认背景色,然后根据透明度重新设置。如果光设置alpha时,整个View就不显示了。
+    FBColorStruct colorStruct = self.backgroundColor.getRGB;
+    self.backgroundColor = [UIColor colorWithRed:colorStruct.R green:colorStruct.G blue:colorStruct.B alpha:aAlpha];
+}
+
+@end

+ 11 - 0
HappyJob/HappyJob/Components/FBKit/FBNetworking/FBBaseAPIManager.h

@@ -60,6 +60,17 @@ typedef NS_ENUM(NSInteger, FBAPIManagerRequestType) {
 
 @end
 
+@protocol FBPagableAPIManager <NSObject>
+
+@property (nonatomic, assign) NSInteger pageSize;
+@property (nonatomic, assign, readonly) NSUInteger currentPageNumber;
+@property (nonatomic, assign, readonly) BOOL isFirstPage;
+@property (nonatomic, assign, readonly) BOOL isLastPage;
+
+- (void)loadNextPage;
+
+@end
+
 @interface FBBaseAPIManager : YTKRequest
 @property (nonatomic, weak) id<FBAPIManagerDelegate> APIManagerDelegate;
 @property (nonatomic, weak) id<FBAPIManagerInterceptor> APIManagerInterceptor;

+ 19 - 0
HappyJob/HappyJob/Components/FBKit/XHDate/NSDate+FBBetweenDays.h

@@ -0,0 +1,19 @@
+//
+//  NSDate+FBBetweenDays.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface NSDate (FBBetweenDays)
+
++ (NSInteger)fb_betweenDaysWithStartDateString:(NSString *)startDateStr endDateString:(NSString *)endDateStr;
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 39 - 0
HappyJob/HappyJob/Components/FBKit/XHDate/NSDate+FBBetweenDays.m

@@ -0,0 +1,39 @@
+//
+//  NSDate+FBBetweenDays.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "NSDate+FBBetweenDays.h"
+#import "NSString+XHDateFormat.h"
+
+@implementation NSDate (FBBetweenDays)
+
++ (NSInteger)fb_betweenDaysWithStartDateString:(NSString *)startDateStr endDateString:(NSString *)endDateStr {
+    //创建两个日期
+    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+    [dateFormatter setDateFormat:@"yyyy-MM-dd"];
+    NSDate *startDate = [dateFormatter dateFromString:startDateStr.xh_format_yyyy_MM_dd];
+    NSDate *endDate = [dateFormatter dateFromString:endDateStr.xh_format_yyyy_MM_dd];
+    
+    //利用NSCalendar比较日期的差异
+    NSCalendar *calendar = [NSCalendar currentCalendar];
+    /**
+     * 要比较的时间单位,常用如下,可以同时传:
+     *    NSCalendarUnitDay : 天
+     *    NSCalendarUnitYear : 年
+     *    NSCalendarUnitMonth : 月
+     *    NSCalendarUnitHour : 时
+     *    NSCalendarUnitMinute : 分
+     *    NSCalendarUnitSecond : 秒
+     */
+    NSCalendarUnit unit = NSCalendarUnitDay;//只比较天数差异
+    //比较的结果是NSDateComponents类对象
+    NSDateComponents *delta = [calendar components:unit fromDate:startDate toDate:endDate options:0];
+    
+    return delta.day;
+}
+
+@end

+ 1 - 0
HappyJob/HappyJob/Components/FBKit/XHDate/XHDate.h

@@ -10,5 +10,6 @@
 #define XHDate_h
 
 #import "NSString+XHDateFormat.h"
+#import "NSDate+FBBetweenDays.h"
 
 #endif /* XHDate_h */

+ 14 - 2
HappyJob/HappyJob/DataCenter/Model/Position/HJPositionModel.h

@@ -22,7 +22,9 @@ typedef NS_ENUM(NSUInteger, HJPositionType) {
 };
 
 @interface HJPositionModel : HJBaseModel
+
 /************************ 全职字段 ************************/
+
 /**岗位ID*/
 @property (nonatomic, assign) NSUInteger positionID;
 /**公司*/
@@ -33,8 +35,8 @@ typedef NS_ENUM(NSUInteger, HJPositionType) {
 @property (nonatomic, copy) NSString *positionName;
 /**全职薪水*/
 @property (nonatomic, copy) NSString *totalSalary;
-/**发布时间*/
-@property (nonatomic, copy) NSString *publishTime;
+/**更新时间*/
+@property (nonatomic, copy) NSString *updateDate;
 /**入职奖励*/
 @property (nonatomic, assign) NSUInteger reward;
 /**平台返现*/
@@ -51,6 +53,11 @@ typedef NS_ENUM(NSUInteger, HJPositionType) {
 @property (nonatomic, copy) NSString *specialWelfare;
 
 /************************ 兼职字段 ************************/
+
+/**发布时间*/
+@property (nonatomic, copy) NSString *publishTime;
+/**结束时间*/
+@property (nonatomic, copy) NSString *endTime;
 /**兼职岗位的工作地址列表数组*/
 @property (nonatomic, strong) NSArray<HJPositionAddressModel *> *hpPositionAddressList;
 /**兼职的工作日*/
@@ -60,6 +67,11 @@ typedef NS_ENUM(NSUInteger, HJPositionType) {
 /**兼职薪水*/
 @property (nonatomic, copy) NSString *salary;
 
+/************************ 福利岗位字段 ************************/
+
+/**福利岗位的工作地址*/
+@property (nonatomic, copy) NSString *activityWide;
+
 /**福利集合*/
 - (NSArray *)getWelfareArray;
 @end

+ 2 - 0
HappyJob/HappyJob/DataCenter/Model/UserInfo/HJUserInfoModel.h

@@ -19,6 +19,8 @@ NS_ASSUME_NONNULL_BEGIN
 //@property (nonatomic, assign, getter=isLogin) BOOL login;
 @property (nonatomic, copy) NSString *phone;
 @property (nonatomic, copy) NSString *city;
+/**认证状态:0表示未认证,1是已认证*/
+@property (nonatomic, assign) BOOL authenticationStatus;
 
 + (instancetype)getUserInfo;
 + (void)setUserInfo:(HJUserInfoModel *)model;

+ 74 - 28
HappyJob/HappyJob/Home_首页/HJHomeViewController.m

@@ -9,8 +9,6 @@
 #import "HJHomeViewController.h"
 #import "HJHomeHeaderView.h"
 #import "HJNavBarView.h"
-#import "HJPartTimeTableViewCell.h"
-#import "HJFullTimeTableViewCell.h"
 #import "HJSearchViewController.h"
 #import "HJCityPickerViewController.h"
 #import "HJFullTimeViewController.h"
@@ -20,11 +18,15 @@
 #import "HJPositionDataBox.h"
 #import "UIView+FBProgressHUD.h"
 #import "HJFullTimeDetailViewController.h"
+#import "HJRefreshHeaderView.h"
+#import "HJRefreshFooterView.h"
 
 @interface HJHomeViewController () <UITableViewDelegate, UIScrollViewDelegate, HJNavBarViewDelegate, HJJobSortViewDelegate, FBAPIManagerDelegate, FBAPIManagerInterceptor>
 @property (nonatomic, strong) UITableView *tableView;
 @property (nonatomic, strong) HJNavBarView *navBarView;
 @property (nonatomic, strong) HJHomeHeaderView *headerView;
+@property (nonatomic, strong) HJRefreshHeaderView *refreshHeader;
+@property (nonatomic, strong) HJRefreshFooterView *refreshFooter;
 
 @property (nonatomic, strong) HJSearchViewController *searchViewController;
 @property (nonatomic, strong) HJCityPickerViewController *cityViewController;
@@ -68,38 +70,56 @@
 #pragma mark - FBAPIManagerInterceptor
 
 - (void)managerShouldStartCallAPI:(FBBaseAPIManager *)manager {
-    [self dismissErrorView];
-    [self showLoadingView];
+    if (self.isFirstLoading) {
+        [self dismissErrorView];
+        [self showLoadingView];
+    }
 }
 
 - (void)managerShouldFinishCallAPI:(FBBaseAPIManager *)manager {
-    [self dismissLoadingView];
+    if (self.isFirstLoading) {
+        [self dismissLoadingView];
+    }
+    
+    [self.refreshHeader endRefreshing];
+    [self.refreshFooter endRefreshing];
 }
 
 #pragma mark - FBAPIManagerDelegate
 
 - (void)managerCallAPIDidSuccess:(FBBaseAPIManager *)manager {
-    [self.navBarView shadeBackgroundColorWithAlpha:0];
-    id fetchData = [manager fetchDataWithBox:self.jobDataBox];
-    if ([fetchData isKindOfClass:[HJPositionDataBox class]]) {
-        self.tableView.dataSource = fetchData;
+    if (manager == self.getHotJobAPIManager) {
+        id fetchData = [manager fetchDataWithBox:self.jobDataBox];
+        if ([fetchData isKindOfClass:[HJPositionDataBox class]]) {
+            self.tableView.dataSource = fetchData;
+        }
+        
+        if (self.isFirstLoading) {
+            // 第一次请求成功显示热门岗位列表
+            [self.navBarView shadeBackgroundColorWithAlpha:0];
+            [self.view insertSubview:self.tableView belowSubview:self.navBarView];
+            [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
+                // 注意要加top
+                make.top.width.equalTo(self.tableView);
+            }];
+            [self.tableView layoutIfNeeded]; // 对tableHeaderView重新布局以后要立即调用该方法,不然会有显示bug。
+        }
+        
+        [self.tableView reloadData];
     }
-    
-    [self.view insertSubview:self.tableView belowSubview:self.navBarView];
-    [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
-        // 注意要加top
-        make.top.width.equalTo(self.tableView);
-    }];
-    [self.tableView layoutIfNeeded]; // 对tableHeaderView重新布局以后要立即调用该方法,不然会有显示bug。
-    [self.tableView reloadData];
 }
 
 - (void)managerCallAPIDidFailed:(FBBaseAPIManager *)manager {
-    [self showErrorView];
+    if (self.isFirstLoading) {
+        // 第一次请求失败显示错误页面
+        [self showErrorView];
+    }
     
-    id fetchData = [manager fetchDataWithBox:self.jobDataBox];
-    if ([fetchData isKindOfClass:[NSString class]]) {
-        [self.view fb_showFailureWithStatus:fetchData];
+    if (manager == self.getHotJobAPIManager) {
+        id fetchData = [manager fetchDataWithBox:self.jobDataBox];
+        if ([fetchData isKindOfClass:[NSString class]]) {
+            [self.view fb_showFailureWithStatus:fetchData];
+        }
     }
 }
 
@@ -126,13 +146,7 @@
 
 - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
     if (scrollView == self.tableView) {
-        CGFloat contentYoffset = scrollView.contentOffset.y;
-        // contentOffset在Y轴的偏移量是负数,则隐藏导航栏
-        self.navBarView.hidden = (contentYoffset < 0) ? YES : NO;
-
-        // 让导航条背景色的透明度变化 100是范围 越大渐变越慢
-        CGFloat alpha = contentYoffset / 100;
-        [self.navBarView shadeBackgroundColorWithAlpha:alpha];
+        [self.navBarView shadeBackgroundColorWithContentOffset:scrollView.contentOffset];
     }
 }
 
@@ -185,9 +199,24 @@
 #pragma mark - event response
 
 - (void)refreshButtonClicked:(UIButton *)sender {
+    self.firstLoading = YES;
+    [self.getHotJobAPIManager call];
+}
+
+- (void)loadNewData {
+    self.firstLoading = NO;
     [self.getHotJobAPIManager call];
 }
 
+- (void)loadMoreData {
+    if (!self.getHotJobAPIManager.isLastPage) {
+        self.firstLoading = NO;
+        [self.getHotJobAPIManager loadNextPage];
+    } else {
+        [self.refreshFooter endRefreshingWithNoMoreData];
+    }
+}
+
 #pragma mark - private methods
 
 #pragma mark - getters and setters
@@ -234,6 +263,9 @@
         // 设置行高自动计算
         _tableView.rowHeight = UITableViewAutomaticDimension;
         _tableView.tableHeaderView = self.headerView;
+        _tableView.mj_header = self.refreshHeader;
+        _tableView.mj_footer = self.refreshFooter;
+        
         // 去除顶部空白
         if (@available(iOS 11.0, *)) {
             _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
@@ -251,6 +283,20 @@
     return _tableView;
 }
 
+- (HJRefreshHeaderView *)refreshHeader {
+    if (_refreshHeader == nil) {
+        _refreshHeader = [HJRefreshHeaderView headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
+    }
+    return _refreshHeader;
+}
+
+- (HJRefreshFooterView *)refreshFooter {
+    if (_refreshFooter == nil) {
+        _refreshFooter = [HJRefreshFooterView footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
+    }
+    return _refreshFooter;
+}
+
 - (HJSearchViewController *)searchViewController {
     if (_searchViewController == nil) {
         _searchViewController = [[HJSearchViewController alloc] init];

+ 130 - 25
HappyJob/HappyJob/Home_首页/JobList_工作列表信息/FullTime_全职工作/HJFullTimeViewController.m

@@ -7,13 +7,22 @@
 //
 
 #import "HJFullTimeViewController.h"
-#import "HJFullTimeTableViewCell.h"
 #import "HJJobPickerMenuView.h"
 #import "HJFullTimeDetailViewController.h"
+#import "HJPositionDataBox.h"
+#import "HJRefreshHeaderView.h"
+#import "HJRefreshFooterView.h"
+#import "HJGetFullTimePositionAPIManager.h"
+#import "UIView+FBProgressHUD.h"
 
-@interface HJFullTimeViewController () <UITableViewDataSource, UITableViewDelegate>
+@interface HJFullTimeViewController () <UITableViewDelegate, FBAPIManagerDelegate, FBAPIManagerInterceptor>
 @property (nonatomic, strong) HJJobPickerMenuView *jobPickerMenuView;
 @property (nonatomic, strong) UITableView *tableView;
+@property (nonatomic, strong) HJRefreshHeaderView *refreshHeader;
+@property (nonatomic, strong) HJRefreshFooterView *refreshFooter;
+
+@property (nonatomic, strong) HJPositionDataBox *dataBox;
+@property (nonatomic, strong) HJGetFullTimePositionAPIManager *getPositionAPIManager;
 @end
 
 @implementation HJFullTimeViewController
@@ -28,10 +37,15 @@
 
 - (void)viewDidLoad {
     [super viewDidLoad];
-    [self.view addSubview:self.jobPickerMenuView];
-    [self.view addSubview:self.tableView];
+    // 错误页面刷新事件
+    [self.errorView.refreshButton addTarget:self
+                                     action:@selector(refreshButtonClicked:)
+                           forControlEvents:UIControlEventTouchUpInside];
     
+    [self.view addSubview:self.jobPickerMenuView];
     [self makeConstraints];
+    
+    [self.getPositionAPIManager call];
 }
 
 - (void)makeConstraints {
@@ -41,48 +55,115 @@
         make.top.equalTo(self.view);
         make.height.mas_equalTo(34);
     }];
-    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.equalTo(self.view);
-        make.right.equalTo(self.view);
-        make.top.equalTo(self.jobPickerMenuView.mas_bottom);
-        make.bottom.equalTo(self.view);
-    }];
 }
 
-#pragma mark - UITableViewDelegate
+#pragma mark - FBAPIManagerInterceptor
 
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
-    return 40;
+- (void)managerShouldStartCallAPI:(FBBaseAPIManager *)manager {
+    if (self.isFirstLoading) {
+        [self dismissErrorView];
+        [self showLoadingView];
+    }
 }
 
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-    static NSString *cellIdentifier = @"CustomCell1";
-    HJFullTimeTableViewCell *cell = (HJFullTimeTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
+- (void)managerShouldFinishCallAPI:(FBBaseAPIManager *)manager {
+    if (self.isFirstLoading) {
+        [self dismissLoadingView];
+    }
     
-    if (cell == nil) {
-        cell = [[HJFullTimeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
+    [self.refreshHeader endRefreshing];
+    // 判断数据加载是否到了最后一页,如果是最后一页了就用endRefreshingWithNoMoreData去结束动画效果,这样可以显示MJRefreshStateNoMoreData状态下的提示信息
+    if (self.getPositionAPIManager.isLastPage) {
+        [self.refreshFooter endRefreshingWithNoMoreData];
+    } else {
+        [self.refreshFooter endRefreshing];
+    }
+}
+
+#pragma mark - FBAPIManagerDelegate
+
+- (void)managerCallAPIDidSuccess:(FBBaseAPIManager *)manager {
+    if (manager == self.getPositionAPIManager) {
+        id fetchData = [manager fetchDataWithBox:self.dataBox];
+        if ([fetchData isKindOfClass:[HJPositionDataBox class]]) {
+            self.tableView.dataSource = fetchData;
+        }
+        
+        if (self.isFirstLoading) {
+            // 第一次请求成功显示岗位列表
+            [self.view insertSubview:self.tableView belowSubview:self.jobPickerMenuView];
+            [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
+                make.left.right.bottom.equalTo(self.view);
+                make.top.equalTo(self.jobPickerMenuView.mas_bottom);
+            }];
+            [self.tableView layoutIfNeeded]; // 对tableView重新布局以后要立即调用该方法,不然会有显示bug。
+        }
+        
+        [self.tableView reloadData];
     }
-    return cell;
 }
 
-- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
-    return 115;
+- (void)managerCallAPIDidFailed:(FBBaseAPIManager *)manager {
+    if (self.isFirstLoading) {
+        // 第一次请求失败显示错误页面
+        [self showErrorView];
+    }
+    
+    if (manager == self.getPositionAPIManager) {
+        id fetchData = [manager fetchDataWithBox:self.dataBox];
+        if ([fetchData isKindOfClass:[NSString class]]) {
+            [self.view fb_showFailureWithStatus:fetchData];
+        }
+    }
 }
 
+#pragma mark - UITableViewDelegate
+
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
     HJFullTimeDetailViewController *vc = [[HJFullTimeDetailViewController alloc] init];
     vc.hidesBottomBarWhenPushed = YES;
     [self.navigationController pushViewController:vc animated:YES];
 }
 
-#pragma mark - CustomDelegate
-
 #pragma mark - event response
 
-#pragma mark - private methods
+- (void)refreshButtonClicked:(UIButton *)sender {
+    self.firstLoading = YES;
+    [self.getPositionAPIManager call];
+}
+
+- (void)loadNewData {
+    self.firstLoading = NO;
+    [self.getPositionAPIManager call];
+}
+
+- (void)loadMoreData {
+    if (!self.getPositionAPIManager.isLastPage) {
+        self.firstLoading = NO;
+        [self.getPositionAPIManager loadNextPage];
+    } else {
+        [self.refreshFooter endRefreshingWithNoMoreData];
+    }
+}
 
 #pragma mark - getters and setters
 
+- (HJPositionDataBox *)dataBox {
+    if (_dataBox == nil) {
+        _dataBox = [[HJPositionDataBox alloc] init];
+    }
+    return _dataBox;
+}
+
+- (HJGetFullTimePositionAPIManager *)getPositionAPIManager {
+    if (_getPositionAPIManager == nil) {
+        _getPositionAPIManager = [[HJGetFullTimePositionAPIManager alloc] init];
+        _getPositionAPIManager.APIManagerDelegate = self;
+        _getPositionAPIManager.APIManagerInterceptor = self;
+    }
+    return _getPositionAPIManager;
+}
+
 - (HJJobPickerMenuView *)jobPickerMenuView {
     if (_jobPickerMenuView == nil) {
         _jobPickerMenuView = [[HJJobPickerMenuView alloc] initWithType:HJJobPickerMenuViewTypeFullTime];
@@ -94,9 +175,33 @@
     if (_tableView == nil) {
         _tableView = [[UITableView alloc] init];
         _tableView.delegate = self;
-        _tableView.dataSource = self;
+        // 设置预估行高
+        _tableView.estimatedRowHeight = 115;
+        // 设置行高自动计算
+        _tableView.rowHeight = UITableViewAutomaticDimension;
+        _tableView.mj_header = self.refreshHeader;
+        _tableView.mj_footer = self.refreshFooter;
+        // 修改分割线样式
+        _tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
+        _tableView.separatorInset = UIEdgeInsetsMake(0, 15, 0, 15);
+        // 在内容显示不够满屏时,去除分割线
+        _tableView.tableFooterView = [UIView new];
     }
     return _tableView;
 }
 
+- (HJRefreshHeaderView *)refreshHeader {
+    if (_refreshHeader == nil) {
+        _refreshHeader = [HJRefreshHeaderView headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
+    }
+    return _refreshHeader;
+}
+
+- (HJRefreshFooterView *)refreshFooter {
+    if (_refreshFooter == nil) {
+        _refreshFooter = [HJRefreshFooterView footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
+    }
+    return _refreshFooter;
+}
+
 @end

+ 130 - 25
HappyJob/HappyJob/Home_首页/JobList_工作列表信息/PartTime_兼职工作/HJPartTimeViewController.m

@@ -7,13 +7,22 @@
 //
 
 #import "HJPartTimeViewController.h"
-#import "HJPartTimeTableViewCell.h"
 #import "HJJobPickerMenuView.h"
 #import "HJPartTimeDetailViewController.h"
+#import "HJPositionDataBox.h"
+#import "HJRefreshHeaderView.h"
+#import "HJRefreshFooterView.h"
+#import "HJGetFullTimePositionAPIManager.h"
+#import "UIView+FBProgressHUD.h"
 
-@interface HJPartTimeViewController () <UITableViewDataSource, UITableViewDelegate>
+@interface HJPartTimeViewController () <UITableViewDelegate, FBAPIManagerDelegate, FBAPIManagerInterceptor>
 @property (nonatomic, strong) HJJobPickerMenuView *jobPickerMenuView;
 @property (nonatomic, strong) UITableView *tableView;
+@property (nonatomic, strong) HJRefreshHeaderView *refreshHeader;
+@property (nonatomic, strong) HJRefreshFooterView *refreshFooter;
+
+@property (nonatomic, strong) HJPositionDataBox *dataBox;
+@property (nonatomic, strong) HJGetFullTimePositionAPIManager *getPositionAPIManager;
 @end
 
 @implementation HJPartTimeViewController
@@ -28,10 +37,15 @@
 
 - (void)viewDidLoad {
     [super viewDidLoad];
-    [self.view addSubview:self.jobPickerMenuView];
-    [self.view insertSubview:self.tableView belowSubview:self.jobPickerMenuView];
+    // 错误页面刷新事件
+    [self.errorView.refreshButton addTarget:self
+                                     action:@selector(refreshButtonClicked:)
+                           forControlEvents:UIControlEventTouchUpInside];
     
+    [self.view addSubview:self.jobPickerMenuView];
     [self makeConstraints];
+    
+    [self.getPositionAPIManager call];
 }
 
 - (void)makeConstraints {
@@ -40,48 +54,115 @@
         make.right.equalTo(self.view);
         make.top.equalTo(self.view);
     }];
-    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.equalTo(self.view);
-        make.right.equalTo(self.view);
-        make.top.equalTo(self.jobPickerMenuView.mas_bottom);
-        make.bottom.equalTo(self.view);
-    }];
 }
 
-#pragma mark - UITableViewDelegate
+#pragma mark - FBAPIManagerInterceptor
 
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
-    return 40;
+- (void)managerShouldStartCallAPI:(FBBaseAPIManager *)manager {
+    if (self.isFirstLoading) {
+        [self dismissErrorView];
+        [self showLoadingView];
+    }
 }
 
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-    static NSString *cellIdentifier = @"CustomCell2";
-    HJPartTimeTableViewCell *cell = (HJPartTimeTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
+- (void)managerShouldFinishCallAPI:(FBBaseAPIManager *)manager {
+    if (self.isFirstLoading) {
+        [self dismissLoadingView];
+    }
     
-    if (cell == nil) {
-        cell = [[HJPartTimeTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
+    [self.refreshHeader endRefreshing];
+    // 判断数据加载是否到了最后一页,如果是最后一页了就用endRefreshingWithNoMoreData去结束动画效果,这样可以显示MJRefreshStateNoMoreData状态下的提示信息
+    if (self.getPositionAPIManager.isLastPage) {
+        [self.refreshFooter endRefreshingWithNoMoreData];
+    } else {
+        [self.refreshFooter endRefreshing];
     }
-    return cell;
 }
 
-- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
-    return 100;
+#pragma mark - FBAPIManagerDelegate
+
+- (void)managerCallAPIDidSuccess:(FBBaseAPIManager *)manager {
+    if (manager == self.getPositionAPIManager) {
+        id fetchData = [manager fetchDataWithBox:self.dataBox];
+        if ([fetchData isKindOfClass:[HJPositionDataBox class]]) {
+            self.tableView.dataSource = fetchData;
+        }
+        
+        if (self.isFirstLoading) {
+            // 第一次请求成功显示岗位列表
+            [self.view insertSubview:self.tableView belowSubview:self.jobPickerMenuView];
+            [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
+                make.left.right.bottom.equalTo(self.view);
+                make.top.equalTo(self.jobPickerMenuView.mas_bottom);
+            }];
+            [self.tableView layoutIfNeeded]; // 对tableView重新布局以后要立即调用该方法,不然会有显示bug。
+        }
+        
+        [self.tableView reloadData];
+    }
 }
 
+- (void)managerCallAPIDidFailed:(FBBaseAPIManager *)manager {
+    if (self.isFirstLoading) {
+        // 第一次请求失败显示错误页面
+        [self showErrorView];
+    }
+    
+    if (manager == self.getPositionAPIManager) {
+        id fetchData = [manager fetchDataWithBox:self.dataBox];
+        if ([fetchData isKindOfClass:[NSString class]]) {
+            [self.view fb_showFailureWithStatus:fetchData];
+        }
+    }
+}
+
+#pragma mark - UITableViewDelegate
+
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
     HJPartTimeDetailViewController *vc = [[HJPartTimeDetailViewController alloc] init];
     vc.hidesBottomBarWhenPushed = YES;
     [self.navigationController pushViewController:vc animated:YES];
 }
 
-#pragma mark - CustomDelegate
-
 #pragma mark - event response
 
-#pragma mark - private methods
+- (void)refreshButtonClicked:(UIButton *)sender {
+    self.firstLoading = YES;
+    [self.getPositionAPIManager call];
+}
+
+- (void)loadNewData {
+    self.firstLoading = NO;
+    [self.getPositionAPIManager call];
+}
+
+- (void)loadMoreData {
+    if (!self.getPositionAPIManager.isLastPage) {
+        self.firstLoading = NO;
+        [self.getPositionAPIManager loadNextPage];
+    } else {
+        [self.refreshFooter endRefreshingWithNoMoreData];
+    }
+}
 
 #pragma mark - getters and setters
 
+- (HJPositionDataBox *)dataBox {
+    if (_dataBox == nil) {
+        _dataBox = [[HJPositionDataBox alloc] init];
+    }
+    return _dataBox;
+}
+
+- (HJGetFullTimePositionAPIManager *)getPositionAPIManager {
+    if (_getPositionAPIManager == nil) {
+        _getPositionAPIManager = [[HJGetFullTimePositionAPIManager alloc] init];
+        _getPositionAPIManager.APIManagerDelegate = self;
+        _getPositionAPIManager.APIManagerInterceptor = self;
+    }
+    return _getPositionAPIManager;
+}
+
 - (HJJobPickerMenuView *)jobPickerMenuView {
     if (_jobPickerMenuView == nil) {
         _jobPickerMenuView = [[HJJobPickerMenuView alloc] initWithType:HJJobPickerMenuViewTypePartTime];
@@ -93,9 +174,33 @@
     if (_tableView == nil) {
         _tableView = [[UITableView alloc] init];
         _tableView.delegate = self;
-        _tableView.dataSource = self;
+        // 设置预估行高
+        _tableView.estimatedRowHeight = 110;
+        // 设置行高自动计算
+        _tableView.rowHeight = UITableViewAutomaticDimension;
+        _tableView.mj_header = self.refreshHeader;
+        _tableView.mj_footer = self.refreshFooter;
+        // 修改分割线样式
+        _tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
+        _tableView.separatorInset = UIEdgeInsetsMake(0, 15, 0, 15);
+        // 在内容显示不够满屏时,去除分割线
+        _tableView.tableFooterView = [UIView new];
     }
     return _tableView;
 }
 
+- (HJRefreshHeaderView *)refreshHeader {
+    if (_refreshHeader == nil) {
+        _refreshHeader = [HJRefreshHeaderView headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
+    }
+    return _refreshHeader;
+}
+
+- (HJRefreshFooterView *)refreshFooter {
+    if (_refreshFooter == nil) {
+        _refreshFooter = [HJRefreshFooterView footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
+    }
+    return _refreshFooter;
+}
+
 @end

+ 2 - 4
HappyJob/HappyJob/Home_首页/NavBar_头部自定义导航栏/HJNavBarView.h

@@ -6,7 +6,7 @@
 //  Copyright © 2019 Bob. All rights reserved.
 //
 
-#import <UIKit/UIKit.h>
+#import "FBNavigationBar.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -20,12 +20,10 @@ NS_ASSUME_NONNULL_BEGIN
 
 @end
 
-@interface HJNavBarView : UIView
+@interface HJNavBarView : FBNavigationBar
 
 @property (nonatomic, weak) id<HJNavBarViewDelegate> delegate;
 
-- (void)shadeBackgroundColorWithAlpha:(CGFloat)alpha;
-
 @end
 
 NS_ASSUME_NONNULL_END

+ 4 - 4
HappyJob/HappyJob/Home_首页/NavBar_头部自定义导航栏/HJNavBarView.m

@@ -17,6 +17,8 @@
 
 - (instancetype)init {
     if (self = [super init]) {
+        self.backgroundColor = [UIColor colorWithRed:81/255.0 green:145/255.0 blue:211/255.0 alpha:1];
+        
         [self addSubview:self.cityButton];
         [self addSubview:self.searchButton];
         
@@ -26,10 +28,8 @@
 }
 
 - (void)shadeBackgroundColorWithAlpha:(CGFloat)alpha {
-    // alpha的值通常是[0 - 1]的范围
-    CGFloat aAlpha = fminf(1, fmaxf(alpha, 0));
-    self.backgroundColor = [UIColor colorWithRed:81/255.0 green:145/255.0 blue:211/255.0 alpha:aAlpha];
-    if (aAlpha < 0.7) {
+    [super shadeBackgroundColorWithAlpha:alpha];
+    if (self.alpha < 0.7) {
         [self.cityButton setTitleColor:[UIColor colorWithRed:34/255.0 green:34/255.0 blue:34/255.0 alpha:1.0] forState:UIControlStateNormal];
         [self.cityButton setImage:[UIImage imageNamed:@"navbar_location_blue"] forState:UIControlStateNormal];
     } else {

+ 17 - 0
HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetFullTimePositionAPIManager.h

@@ -0,0 +1,17 @@
+//
+//  HJGetFullTimePositionAPIManager.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/29.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "FBBaseAPIManager.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HJGetFullTimePositionAPIManager : FBBaseAPIManager <FBPagableAPIManager>
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 81 - 0
HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetFullTimePositionAPIManager.m

@@ -0,0 +1,81 @@
+//
+//  HJGetFullTimePositionAPIManager.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/29.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "HJGetFullTimePositionAPIManager.h"
+#import "HJUserInfoModel.h"
+
+@interface HJGetFullTimePositionAPIManager () <FBAPIManagerProtocol>
+@property (nonatomic, copy) NSString *userID;
+@property (nonatomic, copy) NSString *userToken;
+@end
+
+@implementation HJGetFullTimePositionAPIManager
+
+@synthesize pageSize = _pageSize;
+@synthesize currentPageNumber = _currentPageNumber;
+@synthesize isFirstPage = _isFirstPage;
+@synthesize isLastPage = _isLastPage;
+
+- (instancetype)init {
+    if (self = [super init]) {
+        _userID = [HJUserInfoModel getUserInfo].userID;
+        _userToken = [HJUserInfoModel getUserInfo].userToken;
+        _isFirstPage = YES;
+        _isLastPage = YES;
+        _currentPageNumber = 1;
+    }
+    return self;
+}
+
+- (FBAPIManagerErrorType)validWithCallBackData:(NSDictionary *)data {
+    if ([[data objectForKey:@"errcode"] integerValue] == 0) {
+        _isLastPage = [[data valueForKeyPath:@"data.isLast"] boolValue];
+        _currentPageNumber = [[data valueForKeyPath:@"data.pageNo"] integerValue];
+        
+        return FBAPIManagerErrorTypeNoError;
+    } else {
+        return FBAPIManagerErrorTypeNoContent;
+    }
+}
+
+- (NSString *)methodName {
+    return @"f/api/hpposition/fullPosition";
+}
+
+- (NSDictionary *)parameters {
+    NSDictionary *params = @{
+                             @"user_id": self.userID,
+                             @"user_token": self.userToken,
+                             @"pageNo": @(self.currentPageNumber)
+                             };
+    
+    return params;
+}
+
+- (FBAPIManagerRequestType)requestType {
+    return FBAPIManagerRequestTypeGet;
+}
+
+- (void)call {
+    _isFirstPage = YES;
+    _currentPageNumber = 1;
+    
+    [super call];
+}
+
+#pragma mark - FBPagableAPIManager
+
+- (void)loadNextPage {
+    _isFirstPage = NO;
+    _currentPageNumber ++;
+    
+    [super call];
+}
+
+@end
+

+ 1 - 1
HappyJob/HappyJob/Home_首页/HomeAPIManager/HJGetHotPositionAPIManager.h

@@ -10,7 +10,7 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface HJGetHotPositionAPIManager : FBBaseAPIManager
+@interface HJGetHotPositionAPIManager : FBBaseAPIManager <FBPagableAPIManager>
 
 @end
 

+ 80 - 0
HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetHotPositionAPIManager.m

@@ -0,0 +1,80 @@
+//
+//  HJGetHotPositionAPIManager.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/22.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "HJGetHotPositionAPIManager.h"
+#import "HJUserInfoModel.h"
+
+@interface HJGetHotPositionAPIManager () <FBAPIManagerProtocol>
+@property (nonatomic, copy) NSString *userID;
+@property (nonatomic, copy) NSString *userToken;
+@end
+
+@implementation HJGetHotPositionAPIManager
+
+@synthesize pageSize = _pageSize;
+@synthesize currentPageNumber = _currentPageNumber;
+@synthesize isFirstPage = _isFirstPage;
+@synthesize isLastPage = _isLastPage;
+
+- (instancetype)init {
+    if (self = [super init]) {
+        _userID = [HJUserInfoModel getUserInfo].userID;
+        _userToken = [HJUserInfoModel getUserInfo].userToken;
+        _isFirstPage = YES;
+        _isLastPage = YES;
+        _currentPageNumber = 1;
+    }
+    return self;
+}
+
+- (FBAPIManagerErrorType)validWithCallBackData:(NSDictionary *)data {
+    if ([[data objectForKey:@"errcode"] integerValue] == 0) {
+        _isLastPage = [[data valueForKeyPath:@"data.isLast"] boolValue];
+        _currentPageNumber = [[data valueForKeyPath:@"data.pageNo"] integerValue];
+        
+        return FBAPIManagerErrorTypeNoError;
+    } else {
+        return FBAPIManagerErrorTypeNoContent;
+    }
+}
+
+- (NSString *)methodName {
+    return @"f/api/hpposition/hotPosition";
+}
+
+- (NSDictionary *)parameters {
+    NSDictionary *params = @{
+        @"user_id": self.userID,
+        @"user_token": self.userToken,
+        @"pageNo": @(self.currentPageNumber)
+    };
+    
+    return params;
+}
+
+- (FBAPIManagerRequestType)requestType {
+    return FBAPIManagerRequestTypeGet;
+}
+
+- (void)call {
+    _isFirstPage = YES;
+    _currentPageNumber = 1;
+    
+    [super call];
+}
+
+#pragma mark - FBPagableAPIManager
+
+- (void)loadNextPage {
+    _isFirstPage = NO;
+    _currentPageNumber ++;
+
+    [super call];
+}
+
+@end

HappyJob/HappyJob/Home_首页/HomeAPIManager/HJGetPositionDetailAPIManager.h → HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetPositionDetailAPIManager.h


HappyJob/HappyJob/Home_首页/HomeAPIManager/HJGetPositionDetailAPIManager.m → HappyJob/HappyJob/Home_首页/PositionAPIManager/HJGetPositionDetailAPIManager.m


HappyJob/HappyJob/Home_首页/HomeAPIManager/HJPositionDataBox.h → HappyJob/HappyJob/Home_首页/PositionAPIManager/HJPositionDataBox.h


+ 54 - 9
HappyJob/HappyJob/Home_首页/HomeAPIManager/HJPositionDataBox.m

@@ -8,6 +8,7 @@
 
 #import "HJPositionDataBox.h"
 #import "HJGetHotPositionAPIManager.h"
+#import "HJGetFullTimePositionAPIManager.h"
 #import "HJPartTimeTableViewCell.h"
 #import "HJFullTimeTableViewCell.h"
 #import "XHDate.h"
@@ -17,7 +18,7 @@ static NSString * const HJFullTimeTableViewCellIdentifier = @"HJFullTimeTableVie
 static NSString * const HJPartTimeTableViewCellIdentifier = @"HJPartTimeTableViewCell";
 
 @interface HJPositionDataBox ()
-@property (nonatomic, strong) NSArray *dataSource;
+@property (nonatomic, strong) NSMutableArray *dataSource;
 @end
 
 @implementation HJPositionDataBox
@@ -25,8 +26,32 @@ static NSString * const HJPartTimeTableViewCellIdentifier = @"HJPartTimeTableVie
 - (id)manager:(FBBaseAPIManager *)manager boxingData:(NSDictionary *)data {
     FBAPIManagerErrorType type = manager.errorType;
     if (type == FBAPIManagerErrorTypeNoError) {
+        // 配置热门岗位数据
         if ([manager isKindOfClass:[HJGetHotPositionAPIManager class]]) {
-            self.dataSource = [data valueForKeyPath:@"data.hotPosition"];
+            NSArray *hpArray = [data valueForKeyPath:@"data.hotPosition"];
+            
+            HJGetHotPositionAPIManager *getHotPositionAPIManager = (HJGetHotPositionAPIManager *)manager;
+            if (getHotPositionAPIManager.isFirstPage) {
+                // 如果请求返回的数据是第一页,就重新加载数据源
+                _dataSource = [NSMutableArray arrayWithArray:hpArray];
+            } else {
+                [self.dataSource addObjectsFromArray:hpArray];
+            }
+            
+            return self;
+        }
+        // 配置全职岗位数据
+        if ([manager isKindOfClass:[HJGetFullTimePositionAPIManager class]]) {
+            NSArray *hpArray = [data valueForKeyPath:@"data.fullPosition"];
+            
+            HJGetFullTimePositionAPIManager *getFullTimePositionAPIManager = (HJGetFullTimePositionAPIManager *)manager;
+            if (getFullTimePositionAPIManager.isFirstPage) {
+                // 如果请求返回的数据是第一页,就重新加载数据源
+                _dataSource = [NSMutableArray arrayWithArray:hpArray];
+            } else {
+                [self.dataSource addObjectsFromArray:hpArray];
+            }
+            
             return self;
         }
     } else if (type == FBAPIManagerErrorTypeNoContent) {
@@ -65,7 +90,7 @@ static NSString * const HJPartTimeTableViewCellIdentifier = @"HJPartTimeTableVie
         cell.baseView.moneyLabel.text = [NSString stringWithFormat:@"%@ 元", model.totalSalary];
         cell.baseView.companyLabel.text = model.hpCompany.companyName;
         cell.baseView.addressLabel.text = model.hpCompany.adname;
-        cell.baseView.dateLabel.text = model.publishTime.xh_format_yyyy_MM_dd;
+        cell.baseView.dateLabel.text = model.updateDate.xh_format_yyyy_MM_dd;
         // 当入职最高奖励的两个金额其中一个有值就显示控件,否则就不显示
         NSInteger money1 = model.reward;
         NSInteger money2 = model.platformAllowance;
@@ -91,13 +116,24 @@ static NSString * const HJPartTimeTableViewCellIdentifier = @"HJPartTimeTableVie
         cell.baseView.titleLabel.text = model.positionName;
         cell.baseView.moneyLabel.text = [NSString stringWithFormat:@"%@ 元/日", model.salary];
         cell.baseView.moneyTagLabel.text = model.settlementMethod;
-        cell.baseView.addressLabel.text = ((HJPositionAddressModel *)[model.hpPositionAddressList firstObject]).address;
         cell.baseView.dateLabel.text = model.publishTime.xh_format_yyyy_MM_dd;
-        // 工作日格式化
-        NSArray *array = [model.workDay componentsSeparatedByString:@", "];
-        NSString *startDay = [array firstObject];
-        NSString *endDay = [array lastObject];
-        cell.baseView.taskTimeLabel.text = [NSString stringWithFormat:@"%@-%@(共计%@天)", startDay.xh_formatYueRi, endDay.xh_formatYueRi, @(array.count)];
+        
+        if (type == HJPositionTypePartTime) {
+            // 兼职岗位的工作日格式化
+            NSArray *array = [model.workDay componentsSeparatedByString:@", "];
+            NSString *startDay = [array firstObject];
+            NSString *endDay = [array lastObject];
+            cell.baseView.taskTimeLabel.text = [NSString stringWithFormat:@"%@-%@(共计%@天)", startDay.xh_formatYueRi, endDay.xh_formatYueRi, @(array.count)];
+            
+            cell.baseView.addressLabel.text = ((HJPositionAddressModel *)[model.hpPositionAddressList firstObject]).address;
+        } else {
+            NSString *startDay = model.publishTime;
+            NSString *endDay = model.endTime;
+            NSInteger days = [NSDate fb_betweenDaysWithStartDateString:startDay endDateString:endDay];
+            cell.baseView.taskTimeLabel.text = [NSString stringWithFormat:@"%@-%@(共计%@天)", startDay.xh_formatYueRi, endDay.xh_formatYueRi, @(days)];
+            
+            cell.baseView.addressLabel.text = model.activityWide;
+        }
         
         return cell;
     } else {
@@ -109,4 +145,13 @@ static NSString * const HJPartTimeTableViewCellIdentifier = @"HJPartTimeTableVie
     }
 }
 
+#pragma mark - getters and setters
+
+- (NSMutableArray *)dataSource {
+    if (_dataSource == nil) {
+        _dataSource = [NSMutableArray array];
+    }
+    return _dataSource;
+}
+
 @end

HappyJob/HappyJob/Home_首页/HomeAPIManager/HJPositionDetailDataBox.h → HappyJob/HappyJob/Home_首页/PositionAPIManager/HJPositionDetailDataBox.h


HappyJob/HappyJob/Home_首页/HomeAPIManager/HJPositionDetailDataBox.m → HappyJob/HappyJob/Home_首页/PositionAPIManager/HJPositionDetailDataBox.m


+ 1 - 0
HappyJob/HappyJob/Main_标签栏控制器/HJBaseViewController.h

@@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
 @interface HJBaseViewController : UIViewController
 
 @property (nonatomic, strong) HJErrorView *errorView;
+@property (nonatomic, assign, getter=isFirstLoading) BOOL firstLoading;
 
 - (void)showErrorView;
 - (void)dismissErrorView;

+ 10 - 2
HappyJob/HappyJob/Main_标签栏控制器/HJBaseViewController.m

@@ -36,12 +36,17 @@
 
 - (void)viewDidLoad {
     [super viewDidLoad];
+    
+    _firstLoading = YES;
 }
 
 - (void)showErrorView {
     [self.view addSubview:self.errorView];
+    [self.view sendSubviewToBack:self.errorView]; // 始终在视图最底层显示
     [self.errorView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.center.equalTo(self.view);
+        make.top.equalTo(self.mas_topLayoutGuide);
+        make.bottom.equalTo(self.mas_bottomLayoutGuide);
+        make.left.right.equalTo(self.view);
     }];
 }
 
@@ -51,8 +56,11 @@
 
 - (void)showLoadingView {
     [self.view addSubview:self.loadingView];
+    [self.view sendSubviewToBack:self.loadingView]; // 始终在视图最底层显示
     [self.loadingView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.center.equalTo(self.view);
+        make.top.equalTo(self.mas_topLayoutGuide);
+        make.bottom.equalTo(self.mas_bottomLayoutGuide);
+        make.left.right.equalTo(self.view);
     }];
 }
 

+ 64 - 38
HappyJob/HappyJob/Me_我/HJMeViewController.m

@@ -8,23 +8,22 @@
 
 #import "HJMeViewController.h"
 #import "HJMeNavBarView.h"
-#import "HJMeHeaderView.h"
 #import "HJJobIntentionViewController.h"
 #import "HJProfileViewController.h"
 #import "HJExperienceViewController.h"
 #import "HJResumeViewController.h"
 #import "HJAuthViewController.h"
+#import "HJMeDataBox.h"
+#import "HJGetUserInfoAPIManager.h"
+#import "HJRefreshHeaderView.h"
 
-static NSString * const kHJTableViewCellIcon = @"kHJTableViewCellIcon";
-static NSString * const kHJTableViewCellTitle = @"kHJTableViewCellTitle";
-
-static NSString * const HJMeCellIdentifier = @"HJMeCustomCell";
-
-@interface HJMeViewController () <UITableViewDelegate, UITableViewDataSource, HJMeProfileViewDelegate>
+@interface HJMeViewController () <UITableViewDelegate, UIScrollViewDelegate, HJMeProfileViewDelegate, FBAPIManagerInterceptor, FBAPIManagerDelegate>
 @property (nonatomic, strong) HJMeNavBarView *navBarView;
 @property (nonatomic, strong) UITableView *tableView;
-@property (nonatomic, strong) HJMeHeaderView *headerView;
-@property (nonatomic, copy) NSArray *dataSource;
+@property (nonatomic, strong) HJRefreshHeaderView *refreshHeader;
+
+@property (nonatomic, strong) HJMeDataBox *dataBox;
+@property (nonatomic, strong) HJGetUserInfoAPIManager *getUserInfoAPIManager;
 @end
 
 @implementation HJMeViewController
@@ -52,37 +51,49 @@ static NSString * const HJMeCellIdentifier = @"HJMeCustomCell";
         make.top.left.right.equalTo(self.view);
         make.height.mas_equalTo(HJNavBarDefaultHeight);
     }];
-    [self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
+    [self.dataBox.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
         // 注意要加top
         make.top.width.equalTo(self.tableView);
     }];
     [self.tableView layoutIfNeeded]; // 对tableHeaderView重新布局以后要立即调用该方法,不然会有显示bug。
 }
 
-#pragma mark - UITableViewDelegate
+#pragma mark - FBAPIManagerInterceptor
 
-- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
-    return self.dataSource.count;
+- (void)managerShouldStartCallAPI:(FBBaseAPIManager *)manager {
+    
 }
 
-- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
-    NSDictionary *data = self.dataSource[indexPath.row];
-    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:HJMeCellIdentifier];
-    if (cell == nil) {
-        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:HJMeCellIdentifier];
-    }
-    cell.imageView.image = [UIImage imageNamed:data[kHJTableViewCellIcon]];
-    cell.textLabel.text = data[kHJTableViewCellTitle];
-    cell.textLabel.textColor = [UIColor colorWithRed:34/255.0 green:34/255.0 blue:34/255.0 alpha:1.0];
-    cell.textLabel.font = [UIFont systemFontOfSize:13];
-    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
-    return cell;
+- (void)managerShouldFinishCallAPI:(FBBaseAPIManager *)manager {
+    
+}
+
+#pragma mark - FBAPIManagerDelegate
+
+- (void)managerCallAPIDidSuccess:(FBBaseAPIManager *)manager {
+    // 不需要根据返回值来处理视图,在DataBox类中做了封装
+    [manager fetchDataWithBox:self.dataBox];
+    [self.refreshHeader endRefreshing];
+}
+
+- (void)managerCallAPIDidFailed:(FBBaseAPIManager *)manager {
+    
 }
 
+#pragma mark - UITableViewDelegate
+
 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
     
 }
 
+#pragma mark - UIScrollViewDelegate
+
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+    if (scrollView == self.tableView) {
+        [self.navBarView shadeBackgroundColorWithContentOffset:scrollView.contentOffset];
+    }
+}
+
 #pragma mark - HJMeProfileViewDelegate
 
 - (void)meProfileViewDidTextForward:(HJMeProfileView *)meProfileView {
@@ -97,23 +108,29 @@ static NSString * const HJMeCellIdentifier = @"HJMeCustomCell";
     
 }
 
+- (void)loadNewData {
+    [self.refreshHeader beginRefreshing];
+    
+    [self.getUserInfoAPIManager call];
+}
+
 #pragma mark - getters and setters
 
-- (NSArray *)dataSource {
-    if (_dataSource == nil) {
-        _dataSource = @[@{kHJTableViewCellIcon: @"me_salary", kHJTableViewCellTitle: @"薪资查询"},
-                        @{kHJTableViewCellIcon: @"me_opinion", kHJTableViewCellTitle: @"意见反馈"},
-                        @{kHJTableViewCellIcon: @"me_business", kHJTableViewCellTitle: @"商务合作"}];
+- (HJMeDataBox *)dataBox {
+    if (_dataBox == nil) {
+        _dataBox = [[HJMeDataBox alloc] init];
+        _dataBox.headerView.profileView.delegate = self;
     }
-    return _dataSource;
+    return _dataBox;
 }
 
-- (HJMeHeaderView *)headerView {
-    if (_headerView == nil) {
-        _headerView = [[HJMeHeaderView alloc] init];
-        _headerView.profileView.delegate = self;
+- (HJGetUserInfoAPIManager *)getUserInfoAPIManager {
+    if (_getUserInfoAPIManager == nil) {
+        _getUserInfoAPIManager = [[HJGetUserInfoAPIManager alloc] init];
+        _getUserInfoAPIManager.APIManagerDelegate = self;
+        _getUserInfoAPIManager.APIManagerInterceptor = self;
     }
-    return _headerView;
+    return _getUserInfoAPIManager;
 }
 
 - (HJMeNavBarView *)navBarView {
@@ -129,8 +146,10 @@ static NSString * const HJMeCellIdentifier = @"HJMeCustomCell";
     if (_tableView == nil) {
         _tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped];
         _tableView.delegate = self;
-        _tableView.dataSource = self;
-        _tableView.tableHeaderView = self.headerView;
+        _tableView.dataSource = self.dataBox;
+        _tableView.tableHeaderView = self.dataBox.headerView;
+        _tableView.mj_header = self.refreshHeader;
+        
         // 去除顶部空白
         if (@available(iOS 11.0, *)) {
             _tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
@@ -149,4 +168,11 @@ static NSString * const HJMeCellIdentifier = @"HJMeCustomCell";
     return _tableView;
 }
 
+- (HJRefreshHeaderView *)refreshHeader {
+    if (_refreshHeader == nil) {
+        _refreshHeader = [HJRefreshHeaderView headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
+    }
+    return _refreshHeader;
+}
+
 @end

+ 2 - 0
HappyJob/HappyJob/Me_我/Header_头视图/HJMeHeaderView.h

@@ -8,11 +8,13 @@
 
 #import <UIKit/UIKit.h>
 #import "HJMeProfileView.h"
+#import "HJMeResumeView.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
 @interface HJMeHeaderView : UIView
 @property (nonatomic, strong) HJMeProfileView *profileView;
+@property (nonatomic, strong) HJMeResumeView *resumeView;
 @end
 
 NS_ASSUME_NONNULL_END

+ 4 - 6
HappyJob/HappyJob/Me_我/Header_头视图/HJMeHeaderView.m

@@ -8,12 +8,10 @@
 
 #import "HJMeHeaderView.h"
 #import "HJMeDistributeView.h"
-#import "HJMeResumeView.h"
 
 @interface HJMeHeaderView ()
 @property (nonatomic, strong) HJMeDistributeView *distributeView;
 @property (nonatomic, strong) UIView *lineH;
-@property (nonatomic, strong) HJMeResumeView *resumeView;
 @end
 
 @implementation HJMeHeaderView
@@ -60,9 +58,9 @@
 - (HJMeProfileView *)profileView {
     if (_profileView == nil) {
         _profileView = [[HJMeProfileView alloc] init];
-        _profileView.nameLabel.text = @"孟璐6166";
-        _profileView.phoneLabel.text = @"132****4659";
-        _profileView.portraitView.image = [UIImage imageNamed:@"test_scroll_img2"];
+        //_profileView.nameLabel.text = @"孟璐6166";
+        //_profileView.phoneLabel.text = @"132****4659";
+        //_profileView.portraitView.image = [UIImage imageNamed:@"test_scroll_img2"];
         //_profileView.auth = NO;
     }
     return _profileView;
@@ -86,7 +84,7 @@
 - (HJMeResumeView *)resumeView {
     if (_resumeView == nil) {
         _resumeView = [[HJMeResumeView alloc] init];
-        _resumeView.name = @"孟璐6166";
+        //_resumeView.name = @"孟璐6166";
         //_resumeView.percent = 60;
     }
     return _resumeView;

+ 38 - 30
HappyJob/HappyJob/Me_我/Header_头视图/HJMeProfileView.m

@@ -13,7 +13,7 @@
 @property (nonatomic, strong) UIImageView *bgImageView;
 @property (nonatomic, strong) UILabel *tagLabel;
 @property (nonatomic, strong) UIImageView *forwardImageView;
-@property (nonatomic, strong) UIView *containerView;
+@property (nonatomic, strong) UIView *textContainerView;
 @property (nonatomic, strong) UILabel *authLabel;
 @end
 
@@ -26,12 +26,12 @@
         
         [self addSubview:self.bgImageView];
         [self addSubview:self.portraitView];
-        [self addSubview:self.containerView];
+        [self addSubview:self.textContainerView];
         [self addSubview:self.authLabel];
-        [self.containerView addSubview:self.nameLabel];
-        [self.containerView addSubview:self.phoneLabel];
-        [self.containerView addSubview:self.tagLabel];
-        [self.containerView addSubview:self.forwardImageView];
+        [self.textContainerView addSubview:self.nameLabel];
+        [self.textContainerView addSubview:self.phoneLabel];
+        [self.textContainerView addSubview:self.tagLabel];
+        [self.textContainerView addSubview:self.forwardImageView];
         
         [self makeConstraints];
         
@@ -51,22 +51,22 @@
         make.bottom.equalTo(self.bgImageView).with.offset(-30);
         make.size.mas_equalTo(self.portraitView.frame.size);
     }];
-    [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
+    [self.textContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
         make.left.equalTo(self.portraitView.mas_right).with.offset(15);
         make.right.equalTo(self);
         make.centerY.equalTo(self.portraitView);
         make.height.mas_equalTo(40);
     }];
     [self.forwardImageView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.right.equalTo(self.containerView).with.offset(-17);
-        make.centerY.equalTo(self.containerView);
+        make.right.equalTo(self.textContainerView).with.offset(-17);
+        make.centerY.equalTo(self.textContainerView);
         make.size.mas_equalTo(self.forwardImageView.image.size);
     }];
     [self.nameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.top.left.equalTo(self.containerView);
+        make.top.left.equalTo(self.textContainerView);
     }];
     [self.phoneLabel mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.left.bottom.equalTo(self.containerView);
+        make.left.bottom.equalTo(self.textContainerView);
     }];
     [self.tagLabel mas_makeConstraints:^(MASConstraintMaker *make) {
         make.left.equalTo(self.nameLabel.mas_right).with.offset(8);
@@ -79,6 +79,20 @@
     }];
 }
 
+- (void)layoutSubviews {
+    [super layoutSubviews];
+    
+    if (self.auth) {
+        [self mas_updateConstraints:^(MASConstraintMaker *make) {
+            make.bottom.equalTo(self.bgImageView);
+        }];
+    } else {
+        [self mas_updateConstraints:^(MASConstraintMaker *make) {
+            make.bottom.equalTo(self.authLabel);
+        }];
+    }
+}
+
 #pragma mark - event response
 
 - (void)textContainerViewTapAction:(id)sender {
@@ -94,24 +108,13 @@
     
     if (auth) {
         self.tagLabel.text = @"已认证";
-        // 设置背景色渐变
-        [self.tagLabel az_setGradientBackgroundWithColors:@[[UIColor colorWithRed:255/255.0 green:199/255.0 blue:107/255.0 alpha:1.0],
-                                                            [UIColor colorWithRed:255/255.0 green:177/255.0 blue:107/255.0 alpha:1.0]]
-                                                locations:@[@(0.0),@(1.0f)]
-                                               startPoint:CGPointMake(0, 0)
-                                                 endPoint:CGPointMake(1, 1)];
-        
-        [self mas_remakeConstraints:^(MASConstraintMaker *make) {
-            make.bottom.equalTo(self.bgImageView);
-        }];
+        self.tagLabel.backgroundColor = [UIColor clearColor];
     } else {
         self.tagLabel.text = @"未认证";
         self.tagLabel.backgroundColor = [UIColor colorWithRed:204/255.0 green:204/255.0 blue:204/255.0 alpha:1.0];
-        
-        [self mas_remakeConstraints:^(MASConstraintMaker *make) {
-            make.bottom.equalTo(self.authLabel);
-        }];
     }
+    
+    [self setNeedsLayout];
 }
 
 - (UILabel *)authLabel {
@@ -167,6 +170,11 @@
         _tagLabel.textAlignment = NSTextAlignmentCenter;
         _tagLabel.layer.cornerRadius = 3;
         _tagLabel.layer.masksToBounds = YES;
+        [_tagLabel az_setGradientBackgroundWithColors:@[[UIColor colorWithRed:255/255.0 green:199/255.0 blue:107/255.0 alpha:1.0],
+                                                        [UIColor colorWithRed:255/255.0 green:177/255.0 blue:107/255.0 alpha:1.0]]
+                                            locations:@[@(0.0),@(1.0f)]
+                                           startPoint:CGPointMake(0, 0)
+                                             endPoint:CGPointMake(1, 1)];
     }
     return _tagLabel;
 }
@@ -187,14 +195,14 @@
     return _bgImageView;
 }
 
-- (UIView *)containerView {
-    if (_containerView == nil) {
-        _containerView = [[UIView alloc] init];
+- (UIView *)textContainerView {
+    if (_textContainerView == nil) {
+        _textContainerView = [[UIView alloc] init];
         UITapGestureRecognizer *tapGesturRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                               action:@selector(textContainerViewTapAction:)];
-        [_containerView addGestureRecognizer:tapGesturRecognizer];
+        [_textContainerView addGestureRecognizer:tapGesturRecognizer];
     }
-    return _containerView;
+    return _textContainerView;
 }
 
 @end

+ 17 - 0
HappyJob/HappyJob/Me_我/MeAPIManager/HJGetUserInfoAPIManager.h

@@ -0,0 +1,17 @@
+//
+//  HJGetUserInfoAPIManager.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "FBBaseAPIManager.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HJGetUserInfoAPIManager : FBBaseAPIManager
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 8 - 9
HappyJob/HappyJob/Home_首页/HomeAPIManager/HJGetHotPositionAPIManager.m

@@ -1,20 +1,20 @@
 //
-//  HJGetHotPositionAPIManager.m
+//  HJGetUserInfoAPIManager.m
 //  HappyJob
 //
-//  Created by Bob on 2019/4/22.
+//  Created by Bob on 2019/4/28.
 //  Copyright © 2019 Bob. All rights reserved.
 //
 
-#import "HJGetHotPositionAPIManager.h"
+#import "HJGetUserInfoAPIManager.h"
 #import "HJUserInfoModel.h"
 
-@interface HJGetHotPositionAPIManager () <FBAPIManagerProtocol>
+@interface HJGetUserInfoAPIManager () <FBAPIManagerProtocol>
 @property (nonatomic, copy) NSString *userID;
 @property (nonatomic, copy) NSString *userToken;
 @end
 
-@implementation HJGetHotPositionAPIManager
+@implementation HJGetUserInfoAPIManager
 
 - (instancetype)init {
     if (self = [super init]) {
@@ -33,19 +33,18 @@
 }
 
 - (NSString *)methodName {
-    return @"f/api/hpposition/hotPosition";
+    return @"f/api/login/getUserInfo";
 }
 
 - (NSDictionary *)parameters {
     return @{
         @"user_id": self.userID,
-        @"user_token": self.userToken,
-        @"pageNo": @(1)
+        @"user_token": self.userToken
     };
 }
 
 - (FBAPIManagerRequestType)requestType {
-    return FBAPIManagerRequestTypeGet;
+    return FBAPIManagerRequestTypePost;
 }
 
 @end

+ 19 - 0
HappyJob/HappyJob/Me_我/MeAPIManager/HJMeDataBox.h

@@ -0,0 +1,19 @@
+//
+//  HJMeDataBox.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "FBAPIManagerDataBox.h"
+#import "HJMeHeaderView.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HJMeDataBox : NSObject <FBAPIManagerDataBox, UITableViewDataSource>
+@property (nonatomic, strong) HJMeHeaderView *headerView;
+@end
+
+NS_ASSUME_NONNULL_END

+ 109 - 0
HappyJob/HappyJob/Me_我/MeAPIManager/HJMeDataBox.m

@@ -0,0 +1,109 @@
+//
+//  HJMeDataBox.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "HJMeDataBox.h"
+#import "HJUserInfoModel.h"
+#import "HJGetUserInfoAPIManager.h"
+#import <SDWebImage/SDWebImage.h>
+#import "UIImage+FBColorToImage.h"
+
+static NSString * const kHJTableViewCellIcon = @"kHJTableViewCellIcon";
+static NSString * const kHJTableViewCellTitle = @"kHJTableViewCellTitle";
+
+static NSString * const HJMeCellIdentifier = @"HJMeCustomCell";
+
+@interface HJMeDataBox ()
+@property (nonatomic, copy) NSArray *dataSource;
+@end
+
+@implementation HJMeDataBox
+
+- (id)manager:(FBBaseAPIManager *)manager boxingData:(NSDictionary *)data {
+    FBAPIManagerErrorType type = manager.errorType;
+    if (type == FBAPIManagerErrorTypeNoError) {
+        if ([manager isKindOfClass:[HJGetUserInfoAPIManager class]]) {
+            [self saveUserInfo:data];
+            [self updateUserInfoView];
+            return @(YES);
+        }
+    } else if (type == FBAPIManagerErrorTypeNoContent) {
+        return [data valueForKey:@"errmsg"];
+    } else {
+        return manager.errorMessage;
+    }
+    
+    return data;
+}
+
+#pragma mark - UITableViewDataSource
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
+    return self.dataSource.count;
+}
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    NSDictionary *data = self.dataSource[indexPath.row];
+    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:HJMeCellIdentifier];
+    if (cell == nil) {
+        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:HJMeCellIdentifier];
+    }
+    cell.imageView.image = [UIImage imageNamed:data[kHJTableViewCellIcon]];
+    cell.textLabel.text = data[kHJTableViewCellTitle];
+    cell.textLabel.textColor = [UIColor colorWithRed:34/255.0 green:34/255.0 blue:34/255.0 alpha:1.0];
+    cell.textLabel.font = [UIFont systemFontOfSize:13];
+    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+    return cell;
+}
+
+#pragma mark - private methods
+
+- (NSString *)formatPhone:(NSString *)phone {
+    NSString *str = [phone stringByReplacingCharactersInRange:NSMakeRange(3, 4) withString:@"****"];
+    return str;
+}
+
+- (void)saveUserInfo:(id)data {
+    // 存储用户信息
+    HJUserInfoModel *userInfo = [HJUserInfoModel yy_modelWithJSON:[data valueForKeyPath:@"data.hpUser"]];
+    [HJUserInfoModel setUserInfo:userInfo];
+}
+
+- (void)updateUserInfoView {
+    HJUserInfoModel *userInfo = [HJUserInfoModel getUserInfo];
+    self.headerView.profileView.nameLabel.text = userInfo.nickName;
+    self.headerView.profileView.phoneLabel.text = [self formatPhone:userInfo.phone];
+    NSURL *imgURL = [NSURL URLWithString:userInfo.avatarURL];
+    UIImage *placeholderImage = [UIImage fb_imageWithColor:[UIColor whiteColor]];
+    [self.headerView.profileView.portraitView.imageView sd_setImageWithURL:imgURL
+                                                          placeholderImage:placeholderImage];
+    self.headerView.profileView.auth = userInfo.authenticationStatus;
+    
+    self.headerView.resumeView.name = userInfo.nickName;
+}
+
+#pragma mark - getters and setters
+
+- (NSArray *)dataSource {
+    if (_dataSource == nil) {
+        _dataSource = @[@{kHJTableViewCellIcon: @"me_salary", kHJTableViewCellTitle: @"薪资查询"},
+                        @{kHJTableViewCellIcon: @"me_opinion", kHJTableViewCellTitle: @"意见反馈"},
+                        @{kHJTableViewCellIcon: @"me_business", kHJTableViewCellTitle: @"商务合作"}];
+    }
+    return _dataSource;
+}
+
+- (HJMeHeaderView *)headerView {
+    if (_headerView == nil) {
+        _headerView = [[HJMeHeaderView alloc] init];
+        // 数据初始化
+        [self updateUserInfoView];
+    }
+    return _headerView;
+}
+
+@end

+ 2 - 2
HappyJob/HappyJob/Me_我/NavBar_我的导航栏/HJMeNavBarView.h

@@ -6,11 +6,11 @@
 //  Copyright © 2019 Bob. All rights reserved.
 //
 
-#import <UIKit/UIKit.h>
+#import "FBNavigationBar.h"
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface HJMeNavBarView : UIView
+@interface HJMeNavBarView : FBNavigationBar
 @property (nonatomic, strong) UILabel *titleLabel;
 @property (nonatomic, strong) UIButton *setingButton;
 @end

+ 2 - 0
HappyJob/HappyJob/Me_我/NavBar_我的导航栏/HJMeNavBarView.m

@@ -16,6 +16,8 @@
 
 - (instancetype)init {
     if (self = [super init]) {
+        self.backgroundColor = [UIColor colorWithRed:81/255.0 green:145/255.0 blue:211/255.0 alpha:0];
+        
         [self addSubview:self.titleLabel];
         [self addSubview:self.setingButton];
         

+ 16 - 3
HappyJob/HappyJob/Message_消息/HJMessageViewController.m

@@ -11,8 +11,10 @@
 #import "HJMessageDateTableViewCell.h"
 #import "UIViewController+HJNavBarRightButtonItems.h"
 #import "HJMessageDelPanelViewController.h"
+#import "HJMessageBlankView.h"
 
 @interface HJMessageViewController () <UITableViewDelegate, UITableViewDataSource>
+@property (nonatomic, strong) HJMessageBlankView *blankView;
 @property (nonatomic, strong) UITableView *tableView;
 @property (nonatomic, strong) UIButton *delButton;
 @end
@@ -25,15 +27,19 @@
     [super viewDidLoad];
     [self hj_setupNavBarRightButtonItems:@[self.delButton]];
     
-    [self.view addSubview:self.tableView];
+    [self.view addSubview:self.blankView];
+    //[self.view addSubview:self.tableView];
     
     [self makeConstraints];
 }
 
 - (void)makeConstraints {
-    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
-        make.edges.equalTo(self.view);
+    [self.blankView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.center.equalTo(self.view);
     }];
+//    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
+//        make.edges.equalTo(self.view);
+//    }];
 }
 
 #pragma mark - UITableViewDelegate
@@ -106,4 +112,11 @@
     return _delButton;
 }
 
+- (HJMessageBlankView *)blankView {
+    if (_blankView == nil) {
+        _blankView = [[HJMessageBlankView alloc] init];
+    }
+    return _blankView;
+}
+
 @end

+ 17 - 0
HappyJob/HappyJob/Message_消息/消息空白页/HJMessageBlankView.h

@@ -0,0 +1,17 @@
+//
+//  HJMessageBlankView.h
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface HJMessageBlankView : UIView
+
+@end
+
+NS_ASSUME_NONNULL_END

+ 82 - 0
HappyJob/HappyJob/Message_消息/消息空白页/HJMessageBlankView.m

@@ -0,0 +1,82 @@
+//
+//  HJMessageBlankView.m
+//  HappyJob
+//
+//  Created by Bob on 2019/4/28.
+//  Copyright © 2019 Bob. All rights reserved.
+//
+
+#import "HJMessageBlankView.h"
+
+@interface HJMessageBlankView ()
+@property (nonatomic, strong) UIImageView *imageView;
+@property (nonatomic, strong) UILabel *label1;
+@property (nonatomic, strong) UILabel *label2;
+@end
+
+@implementation HJMessageBlankView
+
+- (instancetype)init {
+    if (self = [super init]) {
+        [self addSubview:self.imageView];
+        [self addSubview:self.label1];
+        [self addSubview:self.label2];
+        
+        [self makeConstraints];
+    }
+    return self;
+}
+
+- (void)makeConstraints {
+    [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.top.centerX.equalTo(self);
+        make.size.mas_equalTo(self.imageView.image.size);
+    }];
+    [self.label1 mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.top.equalTo(self.imageView.mas_bottom).with.offset(25);
+        make.centerX.equalTo(self);
+    }];
+    [self.label2 mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.top.equalTo(self.label1.mas_bottom).with.offset(10);
+        make.centerX.equalTo(self);
+    }];
+    [self mas_makeConstraints:^(MASConstraintMaker *make) {
+        make.top.equalTo(self.imageView);
+        make.left.right.equalTo(self.label1);
+        make.bottom.equalTo(self.label2);
+    }];
+}
+
+#pragma mark - getters and setters
+
+- (UIImageView *)imageView {
+    if (_imageView == nil) {
+        _imageView = [[UIImageView alloc] init];
+        _imageView.image = [UIImage imageNamed:@"msg_blank"];
+    }
+    return _imageView;
+}
+
+- (UILabel *)label1 {
+    if (_label1 == nil) {
+        _label1 = [[UILabel alloc] init];
+        _label1.text = @"你和系统失联了?";
+        _label1.textColor = [UIColor colorWithRed:204/255.0 green:204/255.0 blue:204/255.0 alpha:1.0];
+        _label1.font = [UIFont systemFontOfSize:16];
+        _label1.textAlignment = NSTextAlignmentCenter;
+    }
+    return _label1;
+}
+
+- (UILabel *)label2 {
+    if (_label2 == nil) {
+        _label2 = [[UILabel alloc] init];
+        _label2.text = @"记得常回来看看";
+        _label2.textColor = [UIColor colorWithRed:204/255.0 green:204/255.0 blue:204/255.0 alpha:1.0];
+        _label2.font = [UIFont systemFontOfSize:16];
+        _label2.textAlignment = NSTextAlignmentCenter;
+    }
+    return _label2;
+}
+
+@end

+ 2 - 0
HappyJob/Podfile

@@ -17,5 +17,7 @@ target 'HappyJob' do
   pod 'FCUUID', '~> 1.3.1'
   pod 'WechatOpenSDK', '~> 1.8.4'
   pod 'YYModel', '~> 1.0.4'
+  pod 'SDWebImage', '~> 5.0.0-beta6'
   pod 'NSDictionary-NilSafe', '~> 0.2.0'
+  pod 'MJRefresh', '~> 3.1.15.7'
 end

+ 11 - 1
HappyJob/Podfile.lock

@@ -22,7 +22,11 @@ PODS:
     - UICKeyChainStore (~> 2.1.0)
   - IQKeyboardManager (6.2.0)
   - Masonry (1.1.0)
+  - MJRefresh (3.1.15.7)
   - NSDictionary-NilSafe (0.2.0)
+  - SDWebImage (5.0.0-beta6):
+    - SDWebImage/Core (= 5.0.0-beta6)
+  - SDWebImage/Core (5.0.0-beta6)
   - SGEasyButton (0.0.6)
   - SVProgressHUD (2.2.5)
   - TXScrollLabelView (1.3.2)
@@ -39,7 +43,9 @@ DEPENDENCIES:
   - FCUUID (~> 1.3.1)
   - IQKeyboardManager (~> 6.2.0)
   - Masonry (~> 1.1.0)
+  - MJRefresh (~> 3.1.15.7)
   - NSDictionary-NilSafe (~> 0.2.0)
+  - SDWebImage (~> 5.0.0-beta6)
   - SGEasyButton (~> 0.0.6)
   - SVProgressHUD (~> 2.2.5)
   - TXScrollLabelView (~> 1.3.2)
@@ -55,7 +61,9 @@ SPEC REPOS:
     - FCUUID
     - IQKeyboardManager
     - Masonry
+    - MJRefresh
     - NSDictionary-NilSafe
+    - SDWebImage
     - SGEasyButton
     - SVProgressHUD
     - TXScrollLabelView
@@ -71,7 +79,9 @@ SPEC CHECKSUMS:
   FCUUID: bb054fc90cd7cd99320f9f6ff8e130fe607fba05
   IQKeyboardManager: 6194101620b73af5e67900b8f89707a99de0b804
   Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
+  MJRefresh: 697f8ec75ebdbe9207767bb682cf0f51b0d8a41f
   NSDictionary-NilSafe: 3df5056bf920974cb9822ed24bfc41af44225201
+  SDWebImage: 2840a50a41156efccf460df67218b32029177897
   SGEasyButton: 988365a76be60c569fda5ee4b6bb225cedf659b4
   SVProgressHUD: 1428aafac632c1f86f62aa4243ec12008d7a51d6
   TXScrollLabelView: 0e1650caf61198bf5dc0938ea6493254aeb80f90
@@ -80,6 +90,6 @@ SPEC CHECKSUMS:
   YTKNetwork: df8a7a5597bda1664a4efaa7ef871a818a887fe0
   YYModel: 2a7fdd96aaa4b86a824e26d0c517de8928c04b30
 
-PODFILE CHECKSUM: 1f0b9b7d18d715394c7a274394b8c08cf0e773fe
+PODFILE CHECKSUM: 389439acad4bb4a225119c585da2b4eb7235c077
 
 COCOAPODS: 1.6.1

+ 19 - 0
HappyJob/Pods/MJRefresh/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2013-2015 MJRefresh (https://github.com/CoderMJLee/MJRefresh)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 23 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.h

@@ -0,0 +1,23 @@
+//
+//  MJRefreshAutoFooter.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshFooter.h"
+
+@interface MJRefreshAutoFooter : MJRefreshFooter
+/** 是否自动刷新(默认为YES) */
+@property (assign, nonatomic, getter=isAutomaticallyRefresh) BOOL automaticallyRefresh;
+
+/** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */
+@property (assign, nonatomic) CGFloat appearencePercentTriggerAutoRefresh MJRefreshDeprecated("请使用triggerAutomaticallyRefreshPercent属性");
+
+/** 当底部控件出现多少时就自动刷新(默认为1.0,也就是底部控件完全出现时,才会自动刷新) */
+@property (assign, nonatomic) CGFloat triggerAutomaticallyRefreshPercent;
+
+/** 是否每一次拖拽只发一次请求 */
+@property (assign, nonatomic, getter=isOnlyRefreshPerDrag) BOOL onlyRefreshPerDrag;
+@end

+ 154 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshAutoFooter.m

@@ -0,0 +1,154 @@
+//
+//  MJRefreshAutoFooter.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshAutoFooter.h"
+
+@interface MJRefreshAutoFooter()
+/** 一个新的拖拽 */
+@property (assign, nonatomic, getter=isOneNewPan) BOOL oneNewPan;
+@end
+
+@implementation MJRefreshAutoFooter
+
+#pragma mark - 初始化
+- (void)willMoveToSuperview:(UIView *)newSuperview
+{
+    [super willMoveToSuperview:newSuperview];
+    
+    if (newSuperview) { // 新的父控件
+        if (self.hidden == NO) {
+            self.scrollView.mj_insetB += self.mj_h;
+        }
+        
+        // 设置位置
+        self.mj_y = _scrollView.mj_contentH;
+    } else { // 被移除了
+        if (self.hidden == NO) {
+            self.scrollView.mj_insetB -= self.mj_h;
+        }
+    }
+}
+
+#pragma mark - 过期方法
+- (void)setAppearencePercentTriggerAutoRefresh:(CGFloat)appearencePercentTriggerAutoRefresh
+{
+    self.triggerAutomaticallyRefreshPercent = appearencePercentTriggerAutoRefresh;
+}
+
+- (CGFloat)appearencePercentTriggerAutoRefresh
+{
+    return self.triggerAutomaticallyRefreshPercent;
+}
+
+#pragma mark - 实现父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    // 默认底部控件100%出现时才会自动刷新
+    self.triggerAutomaticallyRefreshPercent = 1.0;
+    
+    // 设置为默认状态
+    self.automaticallyRefresh = YES;
+    
+    // 默认是当offset达到条件就发送请求(可连续)
+    self.onlyRefreshPerDrag = NO;
+}
+
+- (void)scrollViewContentSizeDidChange:(NSDictionary *)change
+{
+    [super scrollViewContentSizeDidChange:change];
+    
+    // 设置位置
+    self.mj_y = self.scrollView.mj_contentH;
+}
+
+- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
+{
+    [super scrollViewContentOffsetDidChange:change];
+    
+    if (self.state != MJRefreshStateIdle || !self.automaticallyRefresh || self.mj_y == 0) return;
+    
+    if (_scrollView.mj_insetT + _scrollView.mj_contentH > _scrollView.mj_h) { // 内容超过一个屏幕
+        // 这里的_scrollView.mj_contentH替换掉self.mj_y更为合理
+        if (_scrollView.mj_offsetY >= _scrollView.mj_contentH - _scrollView.mj_h + self.mj_h * self.triggerAutomaticallyRefreshPercent + _scrollView.mj_insetB - self.mj_h) {
+            // 防止手松开时连续调用
+            CGPoint old = [change[@"old"] CGPointValue];
+            CGPoint new = [change[@"new"] CGPointValue];
+            if (new.y <= old.y) return;
+            
+            // 当底部刷新控件完全出现时,才刷新
+            [self beginRefreshing];
+        }
+    }
+}
+
+- (void)scrollViewPanStateDidChange:(NSDictionary *)change
+{
+    [super scrollViewPanStateDidChange:change];
+    
+    if (self.state != MJRefreshStateIdle) return;
+    
+    UIGestureRecognizerState panState = _scrollView.panGestureRecognizer.state;
+    if (panState == UIGestureRecognizerStateEnded) {// 手松开
+        if (_scrollView.mj_insetT + _scrollView.mj_contentH <= _scrollView.mj_h) {  // 不够一个屏幕
+            if (_scrollView.mj_offsetY >= - _scrollView.mj_insetT) { // 向上拽
+                [self beginRefreshing];
+            }
+        } else { // 超出一个屏幕
+            if (_scrollView.mj_offsetY >= _scrollView.mj_contentH + _scrollView.mj_insetB - _scrollView.mj_h) {
+                [self beginRefreshing];
+            }
+        }
+    } else if (panState == UIGestureRecognizerStateBegan) {
+        self.oneNewPan = YES;
+    }
+}
+
+- (void)beginRefreshing
+{
+    if (!self.isOneNewPan && self.isOnlyRefreshPerDrag) return;
+    
+    [super beginRefreshing];
+    
+    self.oneNewPan = NO;
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    if (state == MJRefreshStateRefreshing) {
+        [self executeRefreshingCallback];
+    } else if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) {
+        if (MJRefreshStateRefreshing == oldState) {
+            if (self.endRefreshingCompletionBlock) {
+                self.endRefreshingCompletionBlock();
+            }
+        }
+    }
+}
+
+- (void)setHidden:(BOOL)hidden
+{
+    BOOL lastHidden = self.isHidden;
+    
+    [super setHidden:hidden];
+    
+    if (!lastHidden && hidden) {
+        self.state = MJRefreshStateIdle;
+        
+        self.scrollView.mj_insetB -= self.mj_h;
+    } else if (lastHidden && !hidden) {
+        self.scrollView.mj_insetB += self.mj_h;
+        
+        // 设置位置
+        self.mj_y = _scrollView.mj_contentH;
+    }
+}
+@end

+ 13 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.h

@@ -0,0 +1,13 @@
+//
+//  MJRefreshBackFooter.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshFooter.h"
+
+@interface MJRefreshBackFooter : MJRefreshFooter
+
+@end

+ 146 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshBackFooter.m

@@ -0,0 +1,146 @@
+//
+//  MJRefreshBackFooter.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshBackFooter.h"
+
+@interface MJRefreshBackFooter()
+@property (assign, nonatomic) NSInteger lastRefreshCount;
+@property (assign, nonatomic) CGFloat lastBottomDelta;
+@end
+
+@implementation MJRefreshBackFooter
+
+#pragma mark - 初始化
+- (void)willMoveToSuperview:(UIView *)newSuperview
+{
+    [super willMoveToSuperview:newSuperview];
+    
+    [self scrollViewContentSizeDidChange:nil];
+}
+
+#pragma mark - 实现父类的方法
+- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
+{
+    [super scrollViewContentOffsetDidChange:change];
+    
+    // 如果正在刷新,直接返回
+    if (self.state == MJRefreshStateRefreshing) return;
+    
+    _scrollViewOriginalInset = self.scrollView.mj_inset;
+    
+    // 当前的contentOffset
+    CGFloat currentOffsetY = self.scrollView.mj_offsetY;
+    // 尾部控件刚好出现的offsetY
+    CGFloat happenOffsetY = [self happenOffsetY];
+    // 如果是向下滚动到看不见尾部控件,直接返回
+    if (currentOffsetY <= happenOffsetY) return;
+    
+    CGFloat pullingPercent = (currentOffsetY - happenOffsetY) / self.mj_h;
+    
+    // 如果已全部加载,仅设置pullingPercent,然后返回
+    if (self.state == MJRefreshStateNoMoreData) {
+        self.pullingPercent = pullingPercent;
+        return;
+    }
+    
+    if (self.scrollView.isDragging) {
+        self.pullingPercent = pullingPercent;
+        // 普通 和 即将刷新 的临界点
+        CGFloat normal2pullingOffsetY = happenOffsetY + self.mj_h;
+        
+        if (self.state == MJRefreshStateIdle && currentOffsetY > normal2pullingOffsetY) {
+            // 转为即将刷新状态
+            self.state = MJRefreshStatePulling;
+        } else if (self.state == MJRefreshStatePulling && currentOffsetY <= normal2pullingOffsetY) {
+            // 转为普通状态
+            self.state = MJRefreshStateIdle;
+        }
+    } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开
+        // 开始刷新
+        [self beginRefreshing];
+    } else if (pullingPercent < 1) {
+        self.pullingPercent = pullingPercent;
+    }
+}
+
+- (void)scrollViewContentSizeDidChange:(NSDictionary *)change
+{
+    [super scrollViewContentSizeDidChange:change];
+    
+    // 内容的高度
+    CGFloat contentHeight = self.scrollView.mj_contentH + self.ignoredScrollViewContentInsetBottom;
+    // 表格的高度
+    CGFloat scrollHeight = self.scrollView.mj_h - self.scrollViewOriginalInset.top - self.scrollViewOriginalInset.bottom + self.ignoredScrollViewContentInsetBottom;
+    // 设置位置和尺寸
+    self.mj_y = MAX(contentHeight, scrollHeight);
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 根据状态来设置属性
+    if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) {
+        // 刷新完毕
+        if (MJRefreshStateRefreshing == oldState) {
+            [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
+                self.scrollView.mj_insetB -= self.lastBottomDelta;
+                
+                // 自动调整透明度
+                if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0;
+            } completion:^(BOOL finished) {
+                self.pullingPercent = 0.0;
+                
+                if (self.endRefreshingCompletionBlock) {
+                    self.endRefreshingCompletionBlock();
+                }
+            }];
+        }
+        
+        CGFloat deltaH = [self heightForContentBreakView];
+        // 刚刷新完毕
+        if (MJRefreshStateRefreshing == oldState && deltaH > 0 && self.scrollView.mj_totalDataCount != self.lastRefreshCount) {
+            self.scrollView.mj_offsetY = self.scrollView.mj_offsetY;
+        }
+    } else if (state == MJRefreshStateRefreshing) {
+        // 记录刷新前的数量
+        self.lastRefreshCount = self.scrollView.mj_totalDataCount;
+        
+        [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+            CGFloat bottom = self.mj_h + self.scrollViewOriginalInset.bottom;
+            CGFloat deltaH = [self heightForContentBreakView];
+            if (deltaH < 0) { // 如果内容高度小于view的高度
+                bottom -= deltaH;
+            }
+            self.lastBottomDelta = bottom - self.scrollView.mj_insetB;
+            self.scrollView.mj_insetB = bottom;
+            self.scrollView.mj_offsetY = [self happenOffsetY] + self.mj_h;
+        } completion:^(BOOL finished) {
+            [self executeRefreshingCallback];
+        }];
+    }
+}
+#pragma mark - 私有方法
+#pragma mark 获得scrollView的内容 超出 view 的高度
+- (CGFloat)heightForContentBreakView
+{
+    CGFloat h = self.scrollView.frame.size.height - self.scrollViewOriginalInset.bottom - self.scrollViewOriginalInset.top;
+    return self.scrollView.contentSize.height - h;
+}
+
+#pragma mark 刚好看到上拉刷新控件时的contentOffset.y
+- (CGFloat)happenOffsetY
+{
+    CGFloat deltaH = [self heightForContentBreakView];
+    if (deltaH > 0) {
+        return deltaH - self.scrollViewOriginalInset.top;
+    } else {
+        return - self.scrollViewOriginalInset.top;
+    }
+}
+@end

+ 107 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.h

@@ -0,0 +1,107 @@
+//  代码地址: https://github.com/CoderMJLee/MJRefresh
+//  代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
+//  MJRefreshComponent.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/3/4.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//  刷新控件的基类
+
+#import <UIKit/UIKit.h>
+#import "MJRefreshConst.h"
+#import "UIView+MJExtension.h"
+#import "UIScrollView+MJExtension.h"
+#import "UIScrollView+MJRefresh.h"
+#import "NSBundle+MJRefresh.h"
+
+/** 刷新控件的状态 */
+typedef NS_ENUM(NSInteger, MJRefreshState) {
+    /** 普通闲置状态 */
+    MJRefreshStateIdle = 1,
+    /** 松开就可以进行刷新的状态 */
+    MJRefreshStatePulling,
+    /** 正在刷新中的状态 */
+    MJRefreshStateRefreshing,
+    /** 即将刷新的状态 */
+    MJRefreshStateWillRefresh,
+    /** 所有数据加载完毕,没有更多的数据了 */
+    MJRefreshStateNoMoreData
+};
+
+/** 进入刷新状态的回调 */
+typedef void (^MJRefreshComponentRefreshingBlock)(void);
+/** 开始刷新后的回调(进入刷新状态后的回调) */
+typedef void (^MJRefreshComponentbeginRefreshingCompletionBlock)(void);
+/** 结束刷新后的回调 */
+typedef void (^MJRefreshComponentEndRefreshingCompletionBlock)(void);
+
+/** 刷新控件的基类 */
+@interface MJRefreshComponent : UIView
+{
+    /** 记录scrollView刚开始的inset */
+    UIEdgeInsets _scrollViewOriginalInset;
+    /** 父控件 */
+    __weak UIScrollView *_scrollView;
+}
+#pragma mark - 刷新回调
+/** 正在刷新的回调 */
+@property (copy, nonatomic) MJRefreshComponentRefreshingBlock refreshingBlock;
+/** 设置回调对象和回调方法 */
+- (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action;
+
+/** 回调对象 */
+@property (weak, nonatomic) id refreshingTarget;
+/** 回调方法 */
+@property (assign, nonatomic) SEL refreshingAction;
+/** 触发回调(交给子类去调用) */
+- (void)executeRefreshingCallback;
+
+#pragma mark - 刷新状态控制
+/** 进入刷新状态 */
+- (void)beginRefreshing;
+- (void)beginRefreshingWithCompletionBlock:(void (^)(void))completionBlock;
+/** 开始刷新后的回调(进入刷新状态后的回调) */
+@property (copy, nonatomic) MJRefreshComponentbeginRefreshingCompletionBlock beginRefreshingCompletionBlock;
+/** 结束刷新的回调 */
+@property (copy, nonatomic) MJRefreshComponentEndRefreshingCompletionBlock endRefreshingCompletionBlock;
+/** 结束刷新状态 */
+- (void)endRefreshing;
+- (void)endRefreshingWithCompletionBlock:(void (^)(void))completionBlock;
+/** 是否正在刷新 */
+@property (assign, nonatomic, readonly, getter=isRefreshing) BOOL refreshing;
+//- (BOOL)isRefreshing;
+/** 刷新状态 一般交给子类内部实现 */
+@property (assign, nonatomic) MJRefreshState state;
+
+#pragma mark - 交给子类去访问
+/** 记录scrollView刚开始的inset */
+@property (assign, nonatomic, readonly) UIEdgeInsets scrollViewOriginalInset;
+/** 父控件 */
+@property (weak, nonatomic, readonly) UIScrollView *scrollView;
+
+#pragma mark - 交给子类们去实现
+/** 初始化 */
+- (void)prepare NS_REQUIRES_SUPER;
+/** 摆放子控件frame */
+- (void)placeSubviews NS_REQUIRES_SUPER;
+/** 当scrollView的contentOffset发生改变的时候调用 */
+- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change NS_REQUIRES_SUPER;
+/** 当scrollView的contentSize发生改变的时候调用 */
+- (void)scrollViewContentSizeDidChange:(NSDictionary *)change NS_REQUIRES_SUPER;
+/** 当scrollView的拖拽状态发生改变的时候调用 */
+- (void)scrollViewPanStateDidChange:(NSDictionary *)change NS_REQUIRES_SUPER;
+
+
+#pragma mark - 其他
+/** 拉拽的百分比(交给子类重写) */
+@property (assign, nonatomic) CGFloat pullingPercent;
+/** 根据拖拽比例自动切换透明度 */
+@property (assign, nonatomic, getter=isAutoChangeAlpha) BOOL autoChangeAlpha MJRefreshDeprecated("请使用automaticallyChangeAlpha属性");
+/** 根据拖拽比例自动切换透明度 */
+@property (assign, nonatomic, getter=isAutomaticallyChangeAlpha) BOOL automaticallyChangeAlpha;
+@end
+
+@interface UILabel(MJRefresh)
++ (instancetype)mj_label;
+- (CGFloat)mj_textWith;
+@end

+ 272 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshComponent.m

@@ -0,0 +1,272 @@
+//  代码地址: https://github.com/CoderMJLee/MJRefresh
+//  代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
+//  MJRefreshComponent.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/3/4.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshComponent.h"
+#import "MJRefreshConst.h"
+
+@interface MJRefreshComponent()
+@property (strong, nonatomic) UIPanGestureRecognizer *pan;
+@end
+
+@implementation MJRefreshComponent
+#pragma mark - 初始化
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    if (self = [super initWithFrame:frame]) {
+        // 准备工作
+        [self prepare];
+        
+        // 默认是普通状态
+        self.state = MJRefreshStateIdle;
+    }
+    return self;
+}
+
+- (void)prepare
+{
+    // 基本属性
+    self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+    self.backgroundColor = [UIColor clearColor];
+}
+
+- (void)layoutSubviews
+{
+    [self placeSubviews];
+    
+    [super layoutSubviews];
+}
+
+- (void)placeSubviews{}
+
+- (void)willMoveToSuperview:(UIView *)newSuperview
+{
+    [super willMoveToSuperview:newSuperview];
+    
+    // 如果不是UIScrollView,不做任何事情
+    if (newSuperview && ![newSuperview isKindOfClass:[UIScrollView class]]) return;
+    
+    // 旧的父控件移除监听
+    [self removeObservers];
+    
+    if (newSuperview) { // 新的父控件
+        // 设置宽度
+        self.mj_w = newSuperview.mj_w;
+        // 设置位置
+        self.mj_x = -_scrollView.mj_insetL;
+        
+        // 记录UIScrollView
+        _scrollView = (UIScrollView *)newSuperview;
+        // 设置永远支持垂直弹簧效果
+        _scrollView.alwaysBounceVertical = YES;
+        // 记录UIScrollView最开始的contentInset
+        _scrollViewOriginalInset = _scrollView.mj_inset;
+        
+        // 添加监听
+        [self addObservers];
+    }
+}
+
+- (void)drawRect:(CGRect)rect
+{
+    [super drawRect:rect];
+    
+    if (self.state == MJRefreshStateWillRefresh) {
+        // 预防view还没显示出来就调用了beginRefreshing
+        self.state = MJRefreshStateRefreshing;
+    }
+}
+
+#pragma mark - KVO监听
+- (void)addObservers
+{
+    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
+    [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentOffset options:options context:nil];
+    [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentSize options:options context:nil];
+    self.pan = self.scrollView.panGestureRecognizer;
+    [self.pan addObserver:self forKeyPath:MJRefreshKeyPathPanState options:options context:nil];
+}
+
+- (void)removeObservers
+{
+    [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentOffset];
+    [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentSize];
+    [self.pan removeObserver:self forKeyPath:MJRefreshKeyPathPanState];
+    self.pan = nil;
+}
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+    // 遇到这些情况就直接返回
+    if (!self.userInteractionEnabled) return;
+    
+    // 这个就算看不见也需要处理
+    if ([keyPath isEqualToString:MJRefreshKeyPathContentSize]) {
+        [self scrollViewContentSizeDidChange:change];
+    }
+    
+    // 看不见
+    if (self.hidden) return;
+    if ([keyPath isEqualToString:MJRefreshKeyPathContentOffset]) {
+        [self scrollViewContentOffsetDidChange:change];
+    } else if ([keyPath isEqualToString:MJRefreshKeyPathPanState]) {
+        [self scrollViewPanStateDidChange:change];
+    }
+}
+
+- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change{}
+- (void)scrollViewContentSizeDidChange:(NSDictionary *)change{}
+- (void)scrollViewPanStateDidChange:(NSDictionary *)change{}
+
+#pragma mark - 公共方法
+#pragma mark 设置回调对象和回调方法
+- (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action
+{
+    self.refreshingTarget = target;
+    self.refreshingAction = action;
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    _state = state;
+    
+    // 加入主队列的目的是等setState:方法调用完毕、设置完文字后再去布局子控件
+    MJRefreshDispatchAsyncOnMainQueue([self setNeedsLayout];)
+}
+
+#pragma mark 进入刷新状态
+- (void)beginRefreshing
+{
+    [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+        self.alpha = 1.0;
+    }];
+    self.pullingPercent = 1.0;
+    // 只要正在刷新,就完全显示
+    if (self.window) {
+        self.state = MJRefreshStateRefreshing;
+    } else {
+        // 预防正在刷新中时,调用本方法使得header inset回置失败
+        if (self.state != MJRefreshStateRefreshing) {
+            self.state = MJRefreshStateWillRefresh;
+            // 刷新(预防从另一个控制器回到这个控制器的情况,回来要重新刷新一下)
+            [self setNeedsDisplay];
+        }
+    }
+}
+
+- (void)beginRefreshingWithCompletionBlock:(void (^)(void))completionBlock
+{
+    self.beginRefreshingCompletionBlock = completionBlock;
+    
+    [self beginRefreshing];
+}
+
+#pragma mark 结束刷新状态
+- (void)endRefreshing
+{
+    MJRefreshDispatchAsyncOnMainQueue(self.state = MJRefreshStateIdle;)
+}
+
+- (void)endRefreshingWithCompletionBlock:(void (^)(void))completionBlock
+{
+    self.endRefreshingCompletionBlock = completionBlock;
+    
+    [self endRefreshing];
+}
+
+#pragma mark 是否正在刷新
+- (BOOL)isRefreshing
+{
+    return self.state == MJRefreshStateRefreshing || self.state == MJRefreshStateWillRefresh;
+}
+
+#pragma mark 自动切换透明度
+- (void)setAutoChangeAlpha:(BOOL)autoChangeAlpha
+{
+    self.automaticallyChangeAlpha = autoChangeAlpha;
+}
+
+- (BOOL)isAutoChangeAlpha
+{
+    return self.isAutomaticallyChangeAlpha;
+}
+
+- (void)setAutomaticallyChangeAlpha:(BOOL)automaticallyChangeAlpha
+{
+    _automaticallyChangeAlpha = automaticallyChangeAlpha;
+    
+    if (self.isRefreshing) return;
+    
+    if (automaticallyChangeAlpha) {
+        self.alpha = self.pullingPercent;
+    } else {
+        self.alpha = 1.0;
+    }
+}
+
+#pragma mark 根据拖拽进度设置透明度
+- (void)setPullingPercent:(CGFloat)pullingPercent
+{
+    _pullingPercent = pullingPercent;
+    
+    if (self.isRefreshing) return;
+    
+    if (self.isAutomaticallyChangeAlpha) {
+        self.alpha = pullingPercent;
+    }
+}
+
+#pragma mark - 内部方法
+- (void)executeRefreshingCallback
+{
+    MJRefreshDispatchAsyncOnMainQueue({
+        if (self.refreshingBlock) {
+            self.refreshingBlock();
+        }
+        if ([self.refreshingTarget respondsToSelector:self.refreshingAction]) {
+            MJRefreshMsgSend(MJRefreshMsgTarget(self.refreshingTarget), self.refreshingAction, self);
+        }
+        if (self.beginRefreshingCompletionBlock) {
+            self.beginRefreshingCompletionBlock();
+        }
+    })
+}
+@end
+
+@implementation UILabel(MJRefresh)
++ (instancetype)mj_label
+{
+    UILabel *label = [[self alloc] init];
+    label.font = MJRefreshLabelFont;
+    label.textColor = MJRefreshLabelTextColor;
+    label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
+    label.textAlignment = NSTextAlignmentCenter;
+    label.backgroundColor = [UIColor clearColor];
+    return label;
+}
+
+- (CGFloat)mj_textWith {
+    CGFloat stringWidth = 0;
+    CGSize size = CGSizeMake(MAXFLOAT, MAXFLOAT);
+    if (self.text.length > 0) {
+#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
+        stringWidth =[self.text
+                      boundingRectWithSize:size
+                      options:NSStringDrawingUsesLineFragmentOrigin
+                      attributes:@{NSFontAttributeName:self.font}
+                      context:nil].size.width;
+#else
+        
+        stringWidth = [self.text sizeWithFont:self.font
+                            constrainedToSize:size
+                                lineBreakMode:NSLineBreakByCharWrapping].width;
+#endif
+    }
+    return stringWidth;
+}
+@end

+ 30 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.h

@@ -0,0 +1,30 @@
+//  代码地址: https://github.com/CoderMJLee/MJRefresh
+//  代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
+//  MJRefreshFooter.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/3/5.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//  上拉刷新控件
+
+#import "MJRefreshComponent.h"
+
+@interface MJRefreshFooter : MJRefreshComponent
+/** 创建footer */
++ (instancetype)footerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock;
+/** 创建footer */
++ (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
+
+/** 提示没有更多的数据 */
+- (void)endRefreshingWithNoMoreData;
+- (void)noticeNoMoreData MJRefreshDeprecated("使用endRefreshingWithNoMoreData");
+
+/** 重置没有更多的数据(消除没有更多数据的状态) */
+- (void)resetNoMoreData;
+
+/** 忽略多少scrollView的contentInset的bottom */
+@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetBottom;
+
+/** 自动根据有无数据来显示和隐藏(有数据就显示,没有数据隐藏。默认是NO) */
+@property (assign, nonatomic, getter=isAutomaticallyHidden) BOOL automaticallyHidden MJRefreshDeprecated("不建议使用此属性,开发者请自行控制footer的显示和隐藏。基于安全考虑,在未来的某些版本此属性可能作废");
+@end

+ 80 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshFooter.m

@@ -0,0 +1,80 @@
+//  代码地址: https://github.com/CoderMJLee/MJRefresh
+//  代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
+//  MJRefreshFooter.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/3/5.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshFooter.h"
+#include "UIScrollView+MJRefresh.h"
+
+@interface MJRefreshFooter()
+
+@end
+
+@implementation MJRefreshFooter
+#pragma mark - 构造方法
++ (instancetype)footerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock
+{
+    MJRefreshFooter *cmp = [[self alloc] init];
+    cmp.refreshingBlock = refreshingBlock;
+    return cmp;
+}
++ (instancetype)footerWithRefreshingTarget:(id)target refreshingAction:(SEL)action
+{
+    MJRefreshFooter *cmp = [[self alloc] init];
+    [cmp setRefreshingTarget:target refreshingAction:action];
+    return cmp;
+}
+
+#pragma mark - 重写父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    // 设置自己的高度
+    self.mj_h = MJRefreshFooterHeight;
+    
+    // 默认不会自动隐藏
+    self.automaticallyHidden = NO;
+}
+
+- (void)willMoveToSuperview:(UIView *)newSuperview
+{
+    [super willMoveToSuperview:newSuperview];
+    
+    if (newSuperview) {
+        // 监听scrollView数据的变化
+        if ([self.scrollView isKindOfClass:[UITableView class]] || [self.scrollView isKindOfClass:[UICollectionView class]]) {
+            [self.scrollView setMj_reloadDataBlock:^(NSInteger totalDataCount) {
+                if (self.isAutomaticallyHidden) {
+                    self.hidden = (totalDataCount == 0);
+                }
+            }];
+        }
+    }
+}
+
+#pragma mark - 公共方法
+- (void)endRefreshingWithNoMoreData
+{
+    MJRefreshDispatchAsyncOnMainQueue(self.state = MJRefreshStateNoMoreData;)
+}
+
+- (void)noticeNoMoreData
+{
+    [self endRefreshingWithNoMoreData];
+}
+
+- (void)resetNoMoreData
+{
+    MJRefreshDispatchAsyncOnMainQueue(self.state = MJRefreshStateIdle;)
+}
+
+- (void)setAutomaticallyHidden:(BOOL)automaticallyHidden
+{
+    _automaticallyHidden = automaticallyHidden;
+}
+@end

+ 25 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.h

@@ -0,0 +1,25 @@
+//  代码地址: https://github.com/CoderMJLee/MJRefresh
+//  代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
+//  MJRefreshHeader.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/3/4.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//  下拉刷新控件:负责监控用户下拉的状态
+
+#import "MJRefreshComponent.h"
+
+@interface MJRefreshHeader : MJRefreshComponent
+/** 创建header */
++ (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock;
+/** 创建header */
++ (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action;
+
+/** 这个key用来存储上一次下拉刷新成功的时间 */
+@property (copy, nonatomic) NSString *lastUpdatedTimeKey;
+/** 上一次下拉刷新成功的时间 */
+@property (strong, nonatomic, readonly) NSDate *lastUpdatedTime;
+
+/** 忽略多少scrollView的contentInset的top */
+@property (assign, nonatomic) CGFloat ignoredScrollViewContentInsetTop;
+@end

+ 158 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Base/MJRefreshHeader.m

@@ -0,0 +1,158 @@
+//  代码地址: https://github.com/CoderMJLee/MJRefresh
+//  代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
+//  MJRefreshHeader.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/3/4.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshHeader.h"
+
+@interface MJRefreshHeader()
+@property (assign, nonatomic) CGFloat insetTDelta;
+@end
+
+@implementation MJRefreshHeader
+#pragma mark - 构造方法
++ (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock
+{
+    MJRefreshHeader *cmp = [[self alloc] init];
+    cmp.refreshingBlock = refreshingBlock;
+    return cmp;
+}
++ (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action
+{
+    MJRefreshHeader *cmp = [[self alloc] init];
+    [cmp setRefreshingTarget:target refreshingAction:action];
+    return cmp;
+}
+
+#pragma mark - 覆盖父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    // 设置key
+    self.lastUpdatedTimeKey = MJRefreshHeaderLastUpdatedTimeKey;
+    
+    // 设置高度
+    self.mj_h = MJRefreshHeaderHeight;
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    // 设置y值(当自己的高度发生改变了,肯定要重新调整Y值,所以放到placeSubviews方法中设置y值)
+    self.mj_y = - self.mj_h - self.ignoredScrollViewContentInsetTop;
+}
+
+- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
+{
+    [super scrollViewContentOffsetDidChange:change];
+    
+    // 在刷新的refreshing状态
+    if (self.state == MJRefreshStateRefreshing) {
+        // 暂时保留
+        if (self.window == nil) return;
+        
+        // sectionheader停留解决
+        CGFloat insetT = - self.scrollView.mj_offsetY > _scrollViewOriginalInset.top ? - self.scrollView.mj_offsetY : _scrollViewOriginalInset.top;
+        insetT = insetT > self.mj_h + _scrollViewOriginalInset.top ? self.mj_h + _scrollViewOriginalInset.top : insetT;
+        self.scrollView.mj_insetT = insetT;
+        
+        self.insetTDelta = _scrollViewOriginalInset.top - insetT;
+        return;
+    }
+    
+    // 跳转到下一个控制器时,contentInset可能会变
+    _scrollViewOriginalInset = self.scrollView.mj_inset;
+    
+    // 当前的contentOffset
+    CGFloat offsetY = self.scrollView.mj_offsetY;
+    // 头部控件刚好出现的offsetY
+    CGFloat happenOffsetY = - self.scrollViewOriginalInset.top;
+    
+    // 如果是向上滚动到看不见头部控件,直接返回
+    // >= -> >
+    if (offsetY > happenOffsetY) return;
+    
+    // 普通 和 即将刷新 的临界点
+    CGFloat normal2pullingOffsetY = happenOffsetY - self.mj_h;
+    CGFloat pullingPercent = (happenOffsetY - offsetY) / self.mj_h;
+    
+    if (self.scrollView.isDragging) { // 如果正在拖拽
+        self.pullingPercent = pullingPercent;
+        if (self.state == MJRefreshStateIdle && offsetY < normal2pullingOffsetY) {
+            // 转为即将刷新状态
+            self.state = MJRefreshStatePulling;
+        } else if (self.state == MJRefreshStatePulling && offsetY >= normal2pullingOffsetY) {
+            // 转为普通状态
+            self.state = MJRefreshStateIdle;
+        }
+    } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开
+        // 开始刷新
+        [self beginRefreshing];
+    } else if (pullingPercent < 1) {
+        self.pullingPercent = pullingPercent;
+    }
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 根据状态做事情
+    if (state == MJRefreshStateIdle) {
+        if (oldState != MJRefreshStateRefreshing) return;
+        
+        // 保存刷新时间
+        [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:self.lastUpdatedTimeKey];
+        [[NSUserDefaults standardUserDefaults] synchronize];
+        
+        // 恢复inset和offset
+        [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
+            self.scrollView.mj_insetT += self.insetTDelta;
+            
+            // 自动调整透明度
+            if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0;
+        } completion:^(BOOL finished) {
+            self.pullingPercent = 0.0;
+            
+            if (self.endRefreshingCompletionBlock) {
+                self.endRefreshingCompletionBlock();
+            }
+        }];
+    } else if (state == MJRefreshStateRefreshing) {
+        MJRefreshDispatchAsyncOnMainQueue({
+            [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+                if (self.scrollView.panGestureRecognizer.state != UIGestureRecognizerStateCancelled) {
+                    CGFloat top = self.scrollViewOriginalInset.top + self.mj_h;
+                    // 增加滚动区域top
+                    self.scrollView.mj_insetT = top;
+                    // 设置滚动位置
+                    CGPoint offset = self.scrollView.contentOffset;
+                    offset.y = -top;
+                    [self.scrollView setContentOffset:offset animated:NO];
+                }
+            } completion:^(BOOL finished) {
+                [self executeRefreshingCallback];
+            }];
+        })
+    }
+}
+
+#pragma mark - 公共方法
+- (NSDate *)lastUpdatedTime
+{
+    return [[NSUserDefaults standardUserDefaults] objectForKey:self.lastUpdatedTimeKey];
+}
+
+- (void)setIgnoredScrollViewContentInsetTop:(CGFloat)ignoredScrollViewContentInsetTop {
+    _ignoredScrollViewContentInsetTop = ignoredScrollViewContentInsetTop;
+    
+    self.mj_y = - self.mj_h - _ignoredScrollViewContentInsetTop;
+}
+
+@end

+ 17 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.h

@@ -0,0 +1,17 @@
+//
+//  MJRefreshAutoGifFooter.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshAutoStateFooter.h"
+
+@interface MJRefreshAutoGifFooter : MJRefreshAutoStateFooter
+@property (weak, nonatomic, readonly) UIImageView *gifView;
+
+/** 设置state状态下的动画图片images 动画持续时间duration*/
+- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state;
+- (void)setImages:(NSArray *)images forState:(MJRefreshState)state;
+@end

+ 116 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoGifFooter.m

@@ -0,0 +1,116 @@
+//
+//  MJRefreshAutoGifFooter.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshAutoGifFooter.h"
+
+@interface MJRefreshAutoGifFooter()
+{
+    __unsafe_unretained UIImageView *_gifView;
+}
+/** 所有状态对应的动画图片 */
+@property (strong, nonatomic) NSMutableDictionary *stateImages;
+/** 所有状态对应的动画时间 */
+@property (strong, nonatomic) NSMutableDictionary *stateDurations;
+@end
+
+@implementation MJRefreshAutoGifFooter
+#pragma mark - 懒加载
+- (UIImageView *)gifView
+{
+    if (!_gifView) {
+        UIImageView *gifView = [[UIImageView alloc] init];
+        [self addSubview:_gifView = gifView];
+    }
+    return _gifView;
+}
+
+- (NSMutableDictionary *)stateImages
+{
+    if (!_stateImages) {
+        self.stateImages = [NSMutableDictionary dictionary];
+    }
+    return _stateImages;
+}
+
+- (NSMutableDictionary *)stateDurations
+{
+    if (!_stateDurations) {
+        self.stateDurations = [NSMutableDictionary dictionary];
+    }
+    return _stateDurations;
+}
+
+#pragma mark - 公共方法
+- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state
+{
+    if (images == nil) return;
+    
+    self.stateImages[@(state)] = images;
+    self.stateDurations[@(state)] = @(duration);
+    
+    /* 根据图片设置控件的高度 */
+    UIImage *image = [images firstObject];
+    if (image.size.height > self.mj_h) {
+        self.mj_h = image.size.height;
+    }
+}
+
+- (void)setImages:(NSArray *)images forState:(MJRefreshState)state
+{
+    [self setImages:images duration:images.count * 0.1 forState:state];
+}
+
+#pragma mark - 实现父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    // 初始化间距
+    self.labelLeftInset = 20;
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    if (self.gifView.constraints.count) return;
+    
+    self.gifView.frame = self.bounds;
+    if (self.isRefreshingTitleHidden) {
+        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;
+    }
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 根据状态做事情
+    if (state == MJRefreshStateRefreshing) {
+        NSArray *images = self.stateImages[@(state)];
+        if (images.count == 0) return;
+        [self.gifView stopAnimating];
+        
+        self.gifView.hidden = NO;
+        if (images.count == 1) { // 单张图片
+            self.gifView.image = [images lastObject];
+        } else { // 多张图片
+            self.gifView.animationImages = images;
+            self.gifView.animationDuration = [self.stateDurations[@(state)] doubleValue];
+            [self.gifView startAnimating];
+        }
+    } else if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) {
+        [self.gifView stopAnimating];
+        self.gifView.hidden = YES;
+    }
+}
+@end
+

+ 14 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.h

@@ -0,0 +1,14 @@
+//
+//  MJRefreshAutoNormalFooter.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshAutoStateFooter.h"
+
+@interface MJRefreshAutoNormalFooter : MJRefreshAutoStateFooter
+/** 菊花的样式 */
+@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle;
+@end

+ 69 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoNormalFooter.m

@@ -0,0 +1,69 @@
+//
+//  MJRefreshAutoNormalFooter.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshAutoNormalFooter.h"
+
+@interface MJRefreshAutoNormalFooter()
+@property (weak, nonatomic) UIActivityIndicatorView *loadingView;
+@end
+
+@implementation MJRefreshAutoNormalFooter
+#pragma mark - 懒加载子控件
+- (UIActivityIndicatorView *)loadingView
+{
+    if (!_loadingView) {
+        UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:self.activityIndicatorViewStyle];
+        loadingView.hidesWhenStopped = YES;
+        [self addSubview:_loadingView = loadingView];
+    }
+    return _loadingView;
+}
+
+- (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle
+{
+    _activityIndicatorViewStyle = activityIndicatorViewStyle;
+    
+    self.loadingView = nil;
+    [self setNeedsLayout];
+}
+#pragma mark - 重写父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    if (self.loadingView.constraints.count) return;
+    
+    // 圈圈
+    CGFloat loadingCenterX = self.mj_w * 0.5;
+    if (!self.isRefreshingTitleHidden) {
+        loadingCenterX -= self.stateLabel.mj_textWith * 0.5 + self.labelLeftInset;
+    }
+    CGFloat loadingCenterY = self.mj_h * 0.5;
+    self.loadingView.center = CGPointMake(loadingCenterX, loadingCenterY);
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 根据状态做事情
+    if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) {
+        [self.loadingView stopAnimating];
+    } else if (state == MJRefreshStateRefreshing) {
+        [self.loadingView startAnimating];
+    }
+}
+
+@end

+ 22 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.h

@@ -0,0 +1,22 @@
+//
+//  MJRefreshAutoStateFooter.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/6/13.
+//  Copyright © 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshAutoFooter.h"
+
+@interface MJRefreshAutoStateFooter : MJRefreshAutoFooter
+/** 文字距离圈圈、箭头的距离 */
+@property (assign, nonatomic) CGFloat labelLeftInset;
+/** 显示刷新状态的label */
+@property (weak, nonatomic, readonly) UILabel *stateLabel;
+
+/** 设置state状态下的文字 */
+- (void)setTitle:(NSString *)title forState:(MJRefreshState)state;
+
+/** 隐藏刷新状态的文字 */
+@property (assign, nonatomic, getter=isRefreshingTitleHidden) BOOL refreshingTitleHidden;
+@end

+ 92 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Auto/MJRefreshAutoStateFooter.m

@@ -0,0 +1,92 @@
+//
+//  MJRefreshAutoStateFooter.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/6/13.
+//  Copyright © 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshAutoStateFooter.h"
+
+@interface MJRefreshAutoStateFooter()
+{
+    /** 显示刷新状态的label */
+    __unsafe_unretained UILabel *_stateLabel;
+}
+/** 所有状态对应的文字 */
+@property (strong, nonatomic) NSMutableDictionary *stateTitles;
+@end
+
+@implementation MJRefreshAutoStateFooter
+#pragma mark - 懒加载
+- (NSMutableDictionary *)stateTitles
+{
+    if (!_stateTitles) {
+        self.stateTitles = [NSMutableDictionary dictionary];
+    }
+    return _stateTitles;
+}
+
+- (UILabel *)stateLabel
+{
+    if (!_stateLabel) {
+        [self addSubview:_stateLabel = [UILabel mj_label]];
+    }
+    return _stateLabel;
+}
+
+#pragma mark - 公共方法
+- (void)setTitle:(NSString *)title forState:(MJRefreshState)state
+{
+    if (title == nil) return;
+    self.stateTitles[@(state)] = title;
+    self.stateLabel.text = self.stateTitles[@(self.state)];
+}
+
+#pragma mark - 私有方法
+- (void)stateLabelClick
+{
+    if (self.state == MJRefreshStateIdle) {
+        [self beginRefreshing];
+    }
+}
+
+#pragma mark - 重写父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    // 初始化间距
+    self.labelLeftInset = MJRefreshLabelLeftInset;
+    
+    // 初始化文字
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterIdleText] forState:MJRefreshStateIdle];
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterRefreshingText] forState:MJRefreshStateRefreshing];
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshAutoFooterNoMoreDataText] forState:MJRefreshStateNoMoreData];
+    
+    // 监听label
+    self.stateLabel.userInteractionEnabled = YES;
+    [self.stateLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(stateLabelClick)]];
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    if (self.stateLabel.constraints.count) return;
+    
+    // 状态标签
+    self.stateLabel.frame = self.bounds;
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    if (self.isRefreshingTitleHidden && state == MJRefreshStateRefreshing) {
+        self.stateLabel.text = nil;
+    } else {
+        self.stateLabel.text = self.stateTitles[@(state)];
+    }
+}
+@end

+ 17 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.h

@@ -0,0 +1,17 @@
+//
+//  MJRefreshBackGifFooter.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshBackStateFooter.h"
+
+@interface MJRefreshBackGifFooter : MJRefreshBackStateFooter
+@property (weak, nonatomic, readonly) UIImageView *gifView;
+
+/** 设置state状态下的动画图片images 动画持续时间duration*/
+- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state;
+- (void)setImages:(NSArray *)images forState:(MJRefreshState)state;
+@end

+ 127 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackGifFooter.m

@@ -0,0 +1,127 @@
+//
+//  MJRefreshBackGifFooter.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshBackGifFooter.h"
+
+@interface MJRefreshBackGifFooter()
+{
+    __unsafe_unretained UIImageView *_gifView;
+}
+/** 所有状态对应的动画图片 */
+@property (strong, nonatomic) NSMutableDictionary *stateImages;
+/** 所有状态对应的动画时间 */
+@property (strong, nonatomic) NSMutableDictionary *stateDurations;
+@end
+
+@implementation MJRefreshBackGifFooter
+#pragma mark - 懒加载
+- (UIImageView *)gifView
+{
+    if (!_gifView) {
+        UIImageView *gifView = [[UIImageView alloc] init];
+        [self addSubview:_gifView = gifView];
+    }
+    return _gifView;
+}
+
+- (NSMutableDictionary *)stateImages
+{
+    if (!_stateImages) {
+        self.stateImages = [NSMutableDictionary dictionary];
+    }
+    return _stateImages;
+}
+
+- (NSMutableDictionary *)stateDurations
+{
+    if (!_stateDurations) {
+        self.stateDurations = [NSMutableDictionary dictionary];
+    }
+    return _stateDurations;
+}
+
+#pragma mark - 公共方法
+- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state
+{
+    if (images == nil) return;
+    
+    self.stateImages[@(state)] = images;
+    self.stateDurations[@(state)] = @(duration);
+    
+    /* 根据图片设置控件的高度 */
+    UIImage *image = [images firstObject];
+    if (image.size.height > self.mj_h) {
+        self.mj_h = image.size.height;
+    }
+}
+
+- (void)setImages:(NSArray *)images forState:(MJRefreshState)state
+{
+    [self setImages:images duration:images.count * 0.1 forState:state];
+}
+
+#pragma mark - 实现父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    // 初始化间距
+    self.labelLeftInset = 20;
+}
+
+- (void)setPullingPercent:(CGFloat)pullingPercent
+{
+    [super setPullingPercent:pullingPercent];
+    NSArray *images = self.stateImages[@(MJRefreshStateIdle)];
+    if (self.state != MJRefreshStateIdle || images.count == 0) return;
+    [self.gifView stopAnimating];
+    NSUInteger index =  images.count * pullingPercent;
+    if (index >= images.count) index = images.count - 1;
+    self.gifView.image = images[index];
+}
+
+- (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;
+    }
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 根据状态做事情
+    if (state == MJRefreshStatePulling || state == MJRefreshStateRefreshing) {
+        NSArray *images = self.stateImages[@(state)];
+        if (images.count == 0) return;
+        
+        self.gifView.hidden = NO;
+        [self.gifView stopAnimating];
+        if (images.count == 1) { // 单张图片
+            self.gifView.image = [images lastObject];
+        } else { // 多张图片
+            self.gifView.animationImages = images;
+            self.gifView.animationDuration = [self.stateDurations[@(state)] doubleValue];
+            [self.gifView startAnimating];
+        }
+    } else if (state == MJRefreshStateIdle) {
+        self.gifView.hidden = NO;
+    } else if (state == MJRefreshStateNoMoreData) {
+        self.gifView.hidden = YES;
+    }
+}
+@end

+ 15 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.h

@@ -0,0 +1,15 @@
+//
+//  MJRefreshBackNormalFooter.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshBackStateFooter.h"
+
+@interface MJRefreshBackNormalFooter : MJRefreshBackStateFooter
+@property (weak, nonatomic, readonly) UIImageView *arrowView;
+/** 菊花的样式 */
+@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle;
+@end

+ 123 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackNormalFooter.m

@@ -0,0 +1,123 @@
+//
+//  MJRefreshBackNormalFooter.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshBackNormalFooter.h"
+#import "NSBundle+MJRefresh.h"
+
+@interface MJRefreshBackNormalFooter()
+{
+    __unsafe_unretained UIImageView *_arrowView;
+}
+@property (weak, nonatomic) UIActivityIndicatorView *loadingView;
+@end
+
+@implementation MJRefreshBackNormalFooter
+#pragma mark - 懒加载子控件
+- (UIImageView *)arrowView
+{
+    if (!_arrowView) {
+        UIImageView *arrowView = [[UIImageView alloc] initWithImage:[NSBundle mj_arrowImage]];
+        [self addSubview:_arrowView = arrowView];
+    }
+    return _arrowView;
+}
+
+
+- (UIActivityIndicatorView *)loadingView
+{
+    if (!_loadingView) {
+        UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:self.activityIndicatorViewStyle];
+        loadingView.hidesWhenStopped = YES;
+        [self addSubview:_loadingView = loadingView];
+    }
+    return _loadingView;
+}
+
+- (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle
+{
+    _activityIndicatorViewStyle = activityIndicatorViewStyle;
+    
+    self.loadingView = nil;
+    [self setNeedsLayout];
+}
+#pragma mark - 重写父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    // 箭头的中心点
+    CGFloat arrowCenterX = self.mj_w * 0.5;
+    if (!self.stateLabel.hidden) {
+        arrowCenterX -= self.labelLeftInset + self.stateLabel.mj_textWith * 0.5;
+    }
+    CGFloat arrowCenterY = self.mj_h * 0.5;
+    CGPoint arrowCenter = CGPointMake(arrowCenterX, arrowCenterY);
+    
+    // 箭头
+    if (self.arrowView.constraints.count == 0) {
+        self.arrowView.mj_size = self.arrowView.image.size;
+        self.arrowView.center = arrowCenter;
+    }
+    
+    // 圈圈
+    if (self.loadingView.constraints.count == 0) {
+        self.loadingView.center = arrowCenter;
+    }
+    
+    self.arrowView.tintColor = self.stateLabel.textColor;
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 根据状态做事情
+    if (state == MJRefreshStateIdle) {
+        if (oldState == MJRefreshStateRefreshing) {
+            self.arrowView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI);
+            [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
+                self.loadingView.alpha = 0.0;
+            } completion:^(BOOL finished) {
+                // 防止动画结束后,状态已经不是MJRefreshStateIdle
+                if (state != MJRefreshStateIdle) return;
+                
+                self.loadingView.alpha = 1.0;
+                [self.loadingView stopAnimating];
+                
+                self.arrowView.hidden = NO;
+            }];
+        } else {
+            self.arrowView.hidden = NO;
+            [self.loadingView stopAnimating];
+            [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+                self.arrowView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI);
+            }];
+        }
+    } else if (state == MJRefreshStatePulling) {
+        self.arrowView.hidden = NO;
+        [self.loadingView stopAnimating];
+        [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+            self.arrowView.transform = CGAffineTransformIdentity;
+        }];
+    } else if (state == MJRefreshStateRefreshing) {
+        self.arrowView.hidden = YES;
+        [self.loadingView startAnimating];
+    } else if (state == MJRefreshStateNoMoreData) {
+        self.arrowView.hidden = YES;
+        [self.loadingView stopAnimating];
+    }
+}
+
+@end

+ 21 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.h

@@ -0,0 +1,21 @@
+//
+//  MJRefreshBackStateFooter.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/6/13.
+//  Copyright © 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshBackFooter.h"
+
+@interface MJRefreshBackStateFooter : MJRefreshBackFooter
+/** 文字距离圈圈、箭头的距离 */
+@property (assign, nonatomic) CGFloat labelLeftInset;
+/** 显示刷新状态的label */
+@property (weak, nonatomic, readonly) UILabel *stateLabel;
+/** 设置state状态下的文字 */
+- (void)setTitle:(NSString *)title forState:(MJRefreshState)state;
+
+/** 获取state状态下的title */
+- (NSString *)titleForState:(MJRefreshState)state;
+@end

+ 82 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Footer/Back/MJRefreshBackStateFooter.m

@@ -0,0 +1,82 @@
+//
+//  MJRefreshBackStateFooter.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/6/13.
+//  Copyright © 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshBackStateFooter.h"
+
+@interface MJRefreshBackStateFooter()
+{
+    /** 显示刷新状态的label */
+    __unsafe_unretained UILabel *_stateLabel;
+}
+/** 所有状态对应的文字 */
+@property (strong, nonatomic) NSMutableDictionary *stateTitles;
+@end
+
+@implementation MJRefreshBackStateFooter
+#pragma mark - 懒加载
+- (NSMutableDictionary *)stateTitles
+{
+    if (!_stateTitles) {
+        self.stateTitles = [NSMutableDictionary dictionary];
+    }
+    return _stateTitles;
+}
+
+- (UILabel *)stateLabel
+{
+    if (!_stateLabel) {
+        [self addSubview:_stateLabel = [UILabel mj_label]];
+    }
+    return _stateLabel;
+}
+
+#pragma mark - 公共方法
+- (void)setTitle:(NSString *)title forState:(MJRefreshState)state
+{
+    if (title == nil) return;
+    self.stateTitles[@(state)] = title;
+    self.stateLabel.text = self.stateTitles[@(self.state)];
+}
+
+- (NSString *)titleForState:(MJRefreshState)state {
+  return self.stateTitles[@(state)];
+}
+
+#pragma mark - 重写父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    // 初始化间距
+    self.labelLeftInset = MJRefreshLabelLeftInset;
+    
+    // 初始化文字
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterIdleText] forState:MJRefreshStateIdle];
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterPullingText] forState:MJRefreshStatePulling];
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterRefreshingText] forState:MJRefreshStateRefreshing];
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshBackFooterNoMoreDataText] forState:MJRefreshStateNoMoreData];
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    if (self.stateLabel.constraints.count) return;
+    
+    // 状态标签
+    self.stateLabel.frame = self.bounds;
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 设置状态文字
+    self.stateLabel.text = self.stateTitles[@(state)];
+}
+@end

+ 17 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.h

@@ -0,0 +1,17 @@
+//
+//  MJRefreshGifHeader.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshStateHeader.h"
+
+@interface MJRefreshGifHeader : MJRefreshStateHeader
+@property (weak, nonatomic, readonly) UIImageView *gifView;
+
+/** 设置state状态下的动画图片images 动画持续时间duration*/
+- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state;
+- (void)setImages:(NSArray *)images forState:(MJRefreshState)state;
+@end

+ 133 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshGifHeader.m

@@ -0,0 +1,133 @@
+//
+//  MJRefreshGifHeader.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshGifHeader.h"
+
+@interface MJRefreshGifHeader()
+{
+    __unsafe_unretained UIImageView *_gifView;
+}
+/** 所有状态对应的动画图片 */
+@property (strong, nonatomic) NSMutableDictionary *stateImages;
+/** 所有状态对应的动画时间 */
+@property (strong, nonatomic) NSMutableDictionary *stateDurations;
+@end
+
+@implementation MJRefreshGifHeader
+#pragma mark - 懒加载
+- (UIImageView *)gifView
+{
+    if (!_gifView) { 
+        UIImageView *gifView = [[UIImageView alloc] init]; 
+        [self addSubview:_gifView = gifView]; 
+    } 
+    return _gifView; 
+}
+
+- (NSMutableDictionary *)stateImages 
+{ 
+    if (!_stateImages) { 
+        self.stateImages = [NSMutableDictionary dictionary]; 
+    } 
+    return _stateImages; 
+}
+
+- (NSMutableDictionary *)stateDurations 
+{ 
+    if (!_stateDurations) { 
+        self.stateDurations = [NSMutableDictionary dictionary]; 
+    } 
+    return _stateDurations; 
+}
+
+#pragma mark - 公共方法
+- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state 
+{ 
+    if (images == nil) return; 
+    
+    self.stateImages[@(state)] = images; 
+    self.stateDurations[@(state)] = @(duration); 
+    
+    /* 根据图片设置控件的高度 */ 
+    UIImage *image = [images firstObject]; 
+    if (image.size.height > self.mj_h) { 
+        self.mj_h = image.size.height; 
+    } 
+}
+
+- (void)setImages:(NSArray *)images forState:(MJRefreshState)state 
+{ 
+    [self setImages:images duration:images.count * 0.1 forState:state]; 
+}
+
+#pragma mark - 实现父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    // 初始化间距
+    self.labelLeftInset = 20;
+}
+
+- (void)setPullingPercent:(CGFloat)pullingPercent
+{
+    [super setPullingPercent:pullingPercent];
+    NSArray *images = self.stateImages[@(MJRefreshStateIdle)];
+    if (self.state != MJRefreshStateIdle || images.count == 0) return;
+    // 停止动画
+    [self.gifView stopAnimating];
+    // 设置当前需要显示的图片
+    NSUInteger index =  images.count * pullingPercent;
+    if (index >= images.count) index = images.count - 1;
+    self.gifView.image = images[index];
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    if (self.gifView.constraints.count) return;
+    
+    self.gifView.frame = self.bounds;
+    if (self.stateLabel.hidden && self.lastUpdatedTimeLabel.hidden) {
+        self.gifView.contentMode = UIViewContentModeCenter;
+    } else {
+        self.gifView.contentMode = UIViewContentModeRight;
+        
+        CGFloat stateWidth = self.stateLabel.mj_textWith;
+        CGFloat timeWidth = 0.0;
+        if (!self.lastUpdatedTimeLabel.hidden) {
+            timeWidth = self.lastUpdatedTimeLabel.mj_textWith;
+        }
+        CGFloat textWidth = MAX(stateWidth, timeWidth);
+        self.gifView.mj_w = self.mj_w * 0.5 - textWidth * 0.5 - self.labelLeftInset;
+    }
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 根据状态做事情
+    if (state == MJRefreshStatePulling || state == MJRefreshStateRefreshing) {
+        NSArray *images = self.stateImages[@(state)];
+        if (images.count == 0) return;
+        
+        [self.gifView stopAnimating];
+        if (images.count == 1) { // 单张图片
+            self.gifView.image = [images lastObject];
+        } else { // 多张图片
+            self.gifView.animationImages = images;
+            self.gifView.animationDuration = [self.stateDurations[@(state)] doubleValue];
+            [self.gifView startAnimating];
+        }
+    } else if (state == MJRefreshStateIdle) {
+        [self.gifView stopAnimating];
+    }
+}
+@end

+ 15 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.h

@@ -0,0 +1,15 @@
+//
+//  MJRefreshNormalHeader.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshStateHeader.h"
+
+@interface MJRefreshNormalHeader : MJRefreshStateHeader
+@property (weak, nonatomic, readonly) UIImageView *arrowView;
+/** 菊花的样式 */
+@property (assign, nonatomic) UIActivityIndicatorViewStyle activityIndicatorViewStyle;
+@end

+ 127 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshNormalHeader.m

@@ -0,0 +1,127 @@
+//
+//  MJRefreshNormalHeader.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshNormalHeader.h"
+#import "NSBundle+MJRefresh.h"
+
+@interface MJRefreshNormalHeader()
+{
+    __unsafe_unretained UIImageView *_arrowView;
+}
+@property (weak, nonatomic) UIActivityIndicatorView *loadingView;
+@end
+
+@implementation MJRefreshNormalHeader
+#pragma mark - 懒加载子控件
+- (UIImageView *)arrowView
+{
+    if (!_arrowView) {
+        UIImageView *arrowView = [[UIImageView alloc] initWithImage:[NSBundle mj_arrowImage]];
+        [self addSubview:_arrowView = arrowView];
+    }
+    return _arrowView;
+}
+
+- (UIActivityIndicatorView *)loadingView
+{
+    if (!_loadingView) {
+        UIActivityIndicatorView *loadingView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:self.activityIndicatorViewStyle];
+        loadingView.hidesWhenStopped = YES;
+        [self addSubview:_loadingView = loadingView];
+    }
+    return _loadingView;
+}
+
+#pragma mark - 公共方法
+- (void)setActivityIndicatorViewStyle:(UIActivityIndicatorViewStyle)activityIndicatorViewStyle
+{
+    _activityIndicatorViewStyle = activityIndicatorViewStyle;
+    
+    self.loadingView = nil;
+    [self setNeedsLayout];
+}
+
+#pragma mark - 重写父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    self.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    // 箭头的中心点
+    CGFloat arrowCenterX = self.mj_w * 0.5;
+    if (!self.stateLabel.hidden) {
+        CGFloat stateWidth = self.stateLabel.mj_textWith;
+        CGFloat timeWidth = 0.0;
+        if (!self.lastUpdatedTimeLabel.hidden) {
+            timeWidth = self.lastUpdatedTimeLabel.mj_textWith;
+        }
+        CGFloat textWidth = MAX(stateWidth, timeWidth);
+        arrowCenterX -= textWidth / 2 + self.labelLeftInset;
+    }
+    CGFloat arrowCenterY = self.mj_h * 0.5;
+    CGPoint arrowCenter = CGPointMake(arrowCenterX, arrowCenterY);
+    
+    // 箭头
+    if (self.arrowView.constraints.count == 0) {
+        self.arrowView.mj_size = self.arrowView.image.size;
+        self.arrowView.center = arrowCenter;
+    }
+        
+    // 圈圈
+    if (self.loadingView.constraints.count == 0) {
+        self.loadingView.center = arrowCenter;
+    }
+    
+    self.arrowView.tintColor = self.stateLabel.textColor;
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 根据状态做事情
+    if (state == MJRefreshStateIdle) {
+        if (oldState == MJRefreshStateRefreshing) {
+            self.arrowView.transform = CGAffineTransformIdentity;
+            
+            [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
+                self.loadingView.alpha = 0.0;
+            } completion:^(BOOL finished) {
+                // 如果执行完动画发现不是idle状态,就直接返回,进入其他状态
+                if (self.state != MJRefreshStateIdle) return;
+                
+                self.loadingView.alpha = 1.0;
+                [self.loadingView stopAnimating];
+                self.arrowView.hidden = NO;
+            }];
+        } else {
+            [self.loadingView stopAnimating];
+            self.arrowView.hidden = NO;
+            [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+                self.arrowView.transform = CGAffineTransformIdentity;
+            }];
+        }
+    } else if (state == MJRefreshStatePulling) {
+        [self.loadingView stopAnimating];
+        self.arrowView.hidden = NO;
+        [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+            self.arrowView.transform = CGAffineTransformMakeRotation(0.000001 - M_PI);
+        }];
+    } else if (state == MJRefreshStateRefreshing) {
+        self.loadingView.alpha = 1.0; // 防止refreshing -> idle的动画完毕动作没有被执行
+        [self.loadingView startAnimating];
+        self.arrowView.hidden = YES;
+    }
+}
+@end

+ 25 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.h

@@ -0,0 +1,25 @@
+//
+//  MJRefreshStateHeader.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshHeader.h"
+
+@interface MJRefreshStateHeader : MJRefreshHeader
+#pragma mark - 刷新时间相关
+/** 利用这个block来决定显示的更新时间文字 */
+@property (copy, nonatomic) NSString *(^lastUpdatedTimeText)(NSDate *lastUpdatedTime);
+/** 显示上一次刷新时间的label */
+@property (weak, nonatomic, readonly) UILabel *lastUpdatedTimeLabel;
+
+#pragma mark - 状态相关
+/** 文字距离圈圈、箭头的距离 */
+@property (assign, nonatomic) CGFloat labelLeftInset;
+/** 显示刷新状态的label */
+@property (weak, nonatomic, readonly) UILabel *stateLabel;
+/** 设置state状态下的文字 */
+- (void)setTitle:(NSString *)title forState:(MJRefreshState)state;
+@end

+ 167 - 0
HappyJob/Pods/MJRefresh/MJRefresh/Custom/Header/MJRefreshStateHeader.m

@@ -0,0 +1,167 @@
+//
+//  MJRefreshStateHeader.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 15/4/24.
+//  Copyright (c) 2015年 小码哥. All rights reserved.
+//
+
+#import "MJRefreshStateHeader.h"
+
+@interface MJRefreshStateHeader()
+{
+    /** 显示上一次刷新时间的label */
+    __unsafe_unretained UILabel *_lastUpdatedTimeLabel;
+    /** 显示刷新状态的label */
+    __unsafe_unretained UILabel *_stateLabel;
+}
+/** 所有状态对应的文字 */
+@property (strong, nonatomic) NSMutableDictionary *stateTitles;
+@end
+
+@implementation MJRefreshStateHeader
+#pragma mark - 懒加载
+- (NSMutableDictionary *)stateTitles
+{
+    if (!_stateTitles) {
+        self.stateTitles = [NSMutableDictionary dictionary];
+    }
+    return _stateTitles;
+}
+
+- (UILabel *)stateLabel
+{
+    if (!_stateLabel) {
+        [self addSubview:_stateLabel = [UILabel mj_label]];
+    }
+    return _stateLabel;
+}
+
+- (UILabel *)lastUpdatedTimeLabel
+{
+    if (!_lastUpdatedTimeLabel) {
+        [self addSubview:_lastUpdatedTimeLabel = [UILabel mj_label]];
+    }
+    return _lastUpdatedTimeLabel;
+}
+
+#pragma mark - 公共方法
+- (void)setTitle:(NSString *)title forState:(MJRefreshState)state
+{
+    if (title == nil) return;
+    self.stateTitles[@(state)] = title;
+    self.stateLabel.text = self.stateTitles[@(self.state)];
+}
+
+#pragma mark - 日历获取在9.x之后的系统使用currentCalendar会出异常。在8.0之后使用系统新API。
+- (NSCalendar *)currentCalendar {
+    if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {
+        return [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
+    }
+    return [NSCalendar currentCalendar];
+}
+
+#pragma mark key的处理
+- (void)setLastUpdatedTimeKey:(NSString *)lastUpdatedTimeKey
+{
+    [super setLastUpdatedTimeKey:lastUpdatedTimeKey];
+    
+    // 如果label隐藏了,就不用再处理
+    if (self.lastUpdatedTimeLabel.hidden) return;
+    
+    NSDate *lastUpdatedTime = [[NSUserDefaults standardUserDefaults] objectForKey:lastUpdatedTimeKey];
+    
+    // 如果有block
+    if (self.lastUpdatedTimeText) {
+        self.lastUpdatedTimeLabel.text = self.lastUpdatedTimeText(lastUpdatedTime);
+        return;
+    }
+    
+    if (lastUpdatedTime) {
+        // 1.获得年月日
+        NSCalendar *calendar = [self currentCalendar];
+        NSUInteger unitFlags = NSCalendarUnitYear| NSCalendarUnitMonth | NSCalendarUnitDay |NSCalendarUnitHour |NSCalendarUnitMinute;
+        NSDateComponents *cmp1 = [calendar components:unitFlags fromDate:lastUpdatedTime];
+        NSDateComponents *cmp2 = [calendar components:unitFlags fromDate:[NSDate date]];
+        
+        // 2.格式化日期
+        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
+        BOOL isToday = NO;
+        if ([cmp1 day] == [cmp2 day]) { // 今天
+            formatter.dateFormat = @" HH:mm";
+            isToday = YES;
+        } else if ([cmp1 year] == [cmp2 year]) { // 今年
+            formatter.dateFormat = @"MM-dd HH:mm";
+        } else {
+            formatter.dateFormat = @"yyyy-MM-dd HH:mm";
+        }
+        NSString *time = [formatter stringFromDate:lastUpdatedTime];
+        
+        // 3.显示日期
+        self.lastUpdatedTimeLabel.text = [NSString stringWithFormat:@"%@%@%@",
+                                          [NSBundle mj_localizedStringForKey:MJRefreshHeaderLastTimeText],
+                                          isToday ? [NSBundle mj_localizedStringForKey:MJRefreshHeaderDateTodayText] : @"",
+                                          time];
+    } else {
+        self.lastUpdatedTimeLabel.text = [NSString stringWithFormat:@"%@%@",
+                                          [NSBundle mj_localizedStringForKey:MJRefreshHeaderLastTimeText],
+                                          [NSBundle mj_localizedStringForKey:MJRefreshHeaderNoneLastDateText]];
+    }
+}
+
+#pragma mark - 覆盖父类的方法
+- (void)prepare
+{
+    [super prepare];
+    
+    // 初始化间距
+    self.labelLeftInset = MJRefreshLabelLeftInset;
+    
+    // 初始化文字
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderIdleText] forState:MJRefreshStateIdle];
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderPullingText] forState:MJRefreshStatePulling];
+    [self setTitle:[NSBundle mj_localizedStringForKey:MJRefreshHeaderRefreshingText] forState:MJRefreshStateRefreshing];
+}
+
+- (void)placeSubviews
+{
+    [super placeSubviews];
+    
+    if (self.stateLabel.hidden) return;
+    
+    BOOL noConstrainsOnStatusLabel = self.stateLabel.constraints.count == 0;
+    
+    if (self.lastUpdatedTimeLabel.hidden) {
+        // 状态
+        if (noConstrainsOnStatusLabel) self.stateLabel.frame = self.bounds;
+    } else {
+        CGFloat stateLabelH = self.mj_h * 0.5;
+        // 状态
+        if (noConstrainsOnStatusLabel) {
+            self.stateLabel.mj_x = 0;
+            self.stateLabel.mj_y = 0;
+            self.stateLabel.mj_w = self.mj_w;
+            self.stateLabel.mj_h = stateLabelH;
+        }
+        
+        // 更新时间
+        if (self.lastUpdatedTimeLabel.constraints.count == 0) {
+            self.lastUpdatedTimeLabel.mj_x = 0;
+            self.lastUpdatedTimeLabel.mj_y = stateLabelH;
+            self.lastUpdatedTimeLabel.mj_w = self.mj_w;
+            self.lastUpdatedTimeLabel.mj_h = self.mj_h - self.lastUpdatedTimeLabel.mj_y;
+        }
+    }
+}
+
+- (void)setState:(MJRefreshState)state
+{
+    MJRefreshCheckState
+    
+    // 设置状态文字
+    self.stateLabel.text = self.stateTitles[@(state)];
+    
+    // 重新设置key(重新显示时间)
+    self.lastUpdatedTimeKey = self.lastUpdatedTimeKey;
+}
+@end

BIN
HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/arrow@2x.png


+ 16 - 0
HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/en.lproj/Localizable.strings

@@ -0,0 +1,16 @@
+"MJRefreshHeaderIdleText" = "Pull down to refresh";
+"MJRefreshHeaderPullingText" = "Release to refresh";
+"MJRefreshHeaderRefreshingText" = "Loading...";
+
+"MJRefreshAutoFooterIdleText" = "Tap or pull up to load more";
+"MJRefreshAutoFooterRefreshingText" = "Loading...";
+"MJRefreshAutoFooterNoMoreDataText" = "No more data";
+
+"MJRefreshBackFooterIdleText" = "Pull up to load more";
+"MJRefreshBackFooterPullingText" = "Release to load more.";
+"MJRefreshBackFooterRefreshingText" = "Loading...";
+"MJRefreshBackFooterNoMoreDataText" = "No more data";
+
+"MJRefreshHeaderLastTimeText" = "Last updated: ";
+"MJRefreshHeaderDateTodayText" = "Today";
+"MJRefreshHeaderNoneLastDateText" = "No record";

BIN
HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hans.lproj/Localizable.strings


+ 16 - 0
HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.bundle/zh-Hant.lproj/Localizable.strings

@@ -0,0 +1,16 @@
+"MJRefreshHeaderIdleText" = "下拉可以刷新";
+"MJRefreshHeaderPullingText" = "鬆開立即刷新";
+"MJRefreshHeaderRefreshingText" = "正在刷新數據中...";
+
+"MJRefreshAutoFooterIdleText" = "點擊或上拉加載更多";
+"MJRefreshAutoFooterRefreshingText" = "正在加載更多的數據...";
+"MJRefreshAutoFooterNoMoreDataText" = "已經全部加載完畢";
+
+"MJRefreshBackFooterIdleText" = "上拉可以加載更多";
+"MJRefreshBackFooterPullingText" = "鬆開立即加載更多";
+"MJRefreshBackFooterRefreshingText" = "正在加載更多的數據...";
+"MJRefreshBackFooterNoMoreDataText" = "已經全部加載完畢";
+
+"MJRefreshHeaderLastTimeText" = "最後更新:";
+"MJRefreshHeaderDateTodayText" = "今天";
+"MJRefreshHeaderNoneLastDateText" = "無記錄";

+ 14 - 0
HappyJob/Pods/MJRefresh/MJRefresh/MJRefresh.h

@@ -0,0 +1,14 @@
+//  代码地址: https://github.com/CoderMJLee/MJRefresh
+//  代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
+
+#import "UIScrollView+MJRefresh.h"
+#import "UIScrollView+MJExtension.h"
+#import "UIView+MJExtension.h"
+
+#import "MJRefreshNormalHeader.h"
+#import "MJRefreshGifHeader.h"
+
+#import "MJRefreshBackNormalFooter.h"
+#import "MJRefreshBackGifFooter.h"
+#import "MJRefreshAutoNormalFooter.h"
+#import "MJRefreshAutoGifFooter.h"

+ 76 - 0
HappyJob/Pods/MJRefresh/MJRefresh/MJRefreshConst.h

@@ -0,0 +1,76 @@
+//  代码地址: https://github.com/CoderMJLee/MJRefresh
+//  代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
+#import <UIKit/UIKit.h>
+#import <objc/message.h>
+
+// 弱引用
+#define MJWeakSelf __weak typeof(self) weakSelf = self;
+
+// 日志输出
+#ifdef DEBUG
+#define MJRefreshLog(...) NSLog(__VA_ARGS__)
+#else
+#define MJRefreshLog(...)
+#endif
+
+// 过期提醒
+#define MJRefreshDeprecated(instead) NS_DEPRECATED(2_0, 2_0, 2_0, 2_0, instead)
+
+// 运行时objc_msgSend
+#define MJRefreshMsgSend(...) ((void (*)(void *, SEL, UIView *))objc_msgSend)(__VA_ARGS__)
+#define MJRefreshMsgTarget(target) (__bridge void *)(target)
+
+// RGB颜色
+#define MJRefreshColor(r, g, b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0]
+
+// 文字颜色
+#define MJRefreshLabelTextColor MJRefreshColor(90, 90, 90)
+
+// 字体大小
+#define MJRefreshLabelFont [UIFont boldSystemFontOfSize:14]
+
+// 常量
+UIKIT_EXTERN const CGFloat MJRefreshLabelLeftInset;
+UIKIT_EXTERN const CGFloat MJRefreshHeaderHeight;
+UIKIT_EXTERN const CGFloat MJRefreshFooterHeight;
+UIKIT_EXTERN const CGFloat MJRefreshFastAnimationDuration;
+UIKIT_EXTERN const CGFloat MJRefreshSlowAnimationDuration;
+
+UIKIT_EXTERN NSString *const MJRefreshKeyPathContentOffset;
+UIKIT_EXTERN NSString *const MJRefreshKeyPathContentSize;
+UIKIT_EXTERN NSString *const MJRefreshKeyPathContentInset;
+UIKIT_EXTERN NSString *const MJRefreshKeyPathPanState;
+
+UIKIT_EXTERN NSString *const MJRefreshHeaderLastUpdatedTimeKey;
+
+UIKIT_EXTERN NSString *const MJRefreshHeaderIdleText;
+UIKIT_EXTERN NSString *const MJRefreshHeaderPullingText;
+UIKIT_EXTERN NSString *const MJRefreshHeaderRefreshingText;
+
+UIKIT_EXTERN NSString *const MJRefreshAutoFooterIdleText;
+UIKIT_EXTERN NSString *const MJRefreshAutoFooterRefreshingText;
+UIKIT_EXTERN NSString *const MJRefreshAutoFooterNoMoreDataText;
+
+UIKIT_EXTERN NSString *const MJRefreshBackFooterIdleText;
+UIKIT_EXTERN NSString *const MJRefreshBackFooterPullingText;
+UIKIT_EXTERN NSString *const MJRefreshBackFooterRefreshingText;
+UIKIT_EXTERN NSString *const MJRefreshBackFooterNoMoreDataText;
+
+UIKIT_EXTERN NSString *const MJRefreshHeaderLastTimeText;
+UIKIT_EXTERN NSString *const MJRefreshHeaderDateTodayText;
+UIKIT_EXTERN NSString *const MJRefreshHeaderNoneLastDateText;
+
+// 状态检查
+#define MJRefreshCheckState \
+MJRefreshState oldState = self.state; \
+if (state == oldState) return; \
+[super setState:state];
+
+// 异步主线程执行,不强持有Self
+#define MJRefreshDispatchAsyncOnMainQueue(x) \
+__weak typeof(self) weakSelf = self; \
+dispatch_async(dispatch_get_main_queue(), ^{ \
+typeof(weakSelf) self = weakSelf; \
+{x} \
+});
+

+ 33 - 0
HappyJob/Pods/MJRefresh/MJRefresh/MJRefreshConst.m

@@ -0,0 +1,33 @@
+//  代码地址: https://github.com/CoderMJLee/MJRefresh
+//  代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
+#import <UIKit/UIKit.h>
+
+const CGFloat MJRefreshLabelLeftInset = 25;
+const CGFloat MJRefreshHeaderHeight = 54.0;
+const CGFloat MJRefreshFooterHeight = 44.0;
+const CGFloat MJRefreshFastAnimationDuration = 0.25;
+const CGFloat MJRefreshSlowAnimationDuration = 0.4;
+
+NSString *const MJRefreshKeyPathContentOffset = @"contentOffset";
+NSString *const MJRefreshKeyPathContentInset = @"contentInset";
+NSString *const MJRefreshKeyPathContentSize = @"contentSize";
+NSString *const MJRefreshKeyPathPanState = @"state";
+
+NSString *const MJRefreshHeaderLastUpdatedTimeKey = @"MJRefreshHeaderLastUpdatedTimeKey";
+
+NSString *const MJRefreshHeaderIdleText = @"MJRefreshHeaderIdleText";
+NSString *const MJRefreshHeaderPullingText = @"MJRefreshHeaderPullingText";
+NSString *const MJRefreshHeaderRefreshingText = @"MJRefreshHeaderRefreshingText";
+
+NSString *const MJRefreshAutoFooterIdleText = @"MJRefreshAutoFooterIdleText";
+NSString *const MJRefreshAutoFooterRefreshingText = @"MJRefreshAutoFooterRefreshingText";
+NSString *const MJRefreshAutoFooterNoMoreDataText = @"MJRefreshAutoFooterNoMoreDataText";
+
+NSString *const MJRefreshBackFooterIdleText = @"MJRefreshBackFooterIdleText";
+NSString *const MJRefreshBackFooterPullingText = @"MJRefreshBackFooterPullingText";
+NSString *const MJRefreshBackFooterRefreshingText = @"MJRefreshBackFooterRefreshingText";
+NSString *const MJRefreshBackFooterNoMoreDataText = @"MJRefreshBackFooterNoMoreDataText";
+
+NSString *const MJRefreshHeaderLastTimeText = @"MJRefreshHeaderLastTimeText";
+NSString *const MJRefreshHeaderDateTodayText = @"MJRefreshHeaderDateTodayText";
+NSString *const MJRefreshHeaderNoneLastDateText = @"MJRefreshHeaderNoneLastDateText";

+ 16 - 0
HappyJob/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.h

@@ -0,0 +1,16 @@
+//
+//  NSBundle+MJRefresh.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 16/6/13.
+//  Copyright © 2016年 小码哥. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface NSBundle (MJRefresh)
++ (instancetype)mj_refreshBundle;
++ (UIImage *)mj_arrowImage;
++ (NSString *)mj_localizedStringForKey:(NSString *)key value:(NSString *)value;
++ (NSString *)mj_localizedStringForKey:(NSString *)key;
+@end

+ 0 - 0
HappyJob/Pods/MJRefresh/MJRefresh/NSBundle+MJRefresh.m


Some files were not shown because too many files changed in this diff