From 3d8ce4866799bea7e66699acdeb86b60b0ba033c Mon Sep 17 00:00:00 2001
From: 无故事王国 <841720330@qq.com>
Date: 星期一, 03 六月 2024 19:51:06 +0800
Subject: [PATCH] add

---
 DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketTagCCell.xib       |   65 +
 DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketCCell.swift        |   10 
 DolphinEnglishLearnStudent/ViewModel/UserViewModel.swift                |   55 +
 DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.xib         |   22 
 DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.swift           |   20 
 DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.swift       |   26 
 DolphinEnglishLearnStudent/Login/LoginVC.xib                            |    2 
 DolphinEnglishLearnStudent/ViewModel/RefreshModel.swift                 |  305 ++++++
 DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketTagCCell.swift     |   20 
 DolphinEnglishLearnStudent/Moudle/Me/MeVC.xib                           |    3 
 DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.xib         |   28 
 DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.swift      |  100 ++
 DolphinEnglishLearnStudent/Moudle/Home/View/AwardListView.swift         |   28 
 DolphinEnglishLearnStudent/Moudle/Home/HomeVC.swift                     |   10 
 DolphinEnglishLearnStudent/Other/UIView/CommonBannerView.swift          |  208 ++++
 DolphinEnglishLearnStudent/Services/Services.swift                      |  213 ++++
 DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.xib       |   15 
 DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.swift       |   98 ++
 DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.swift     |   39 
 DolphinEnglishLearnStudent/Moudle/Home/Listen/VC/HomeListenMenuVC.swift |   18 
 DolphinEnglishLearnStudent/Other/UIView/CityAddressPickerView.swift     |  248 +++++
 DolphinEnglishLearnStudent/Moudle/Market/MarketVC.xib                   |    1 
 DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.xib        |   73 +
 DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageVC.swift           |   26 
 DolphinEnglishLearnStudent/SceneDelegate.swift                          |    4 
 DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.swift         |   29 
 DolphinEnglishLearnStudent/Moudle/Me/MeVC.swift                         |   19 
 DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.xib             |   10 
 DolphinEnglishLearnStudent/Login/LoginVC.swift                          |   18 
 Podfile                                                                 |    1 
 DolphinEnglishLearnStudent/Moudle/Me/VC/ExchangeRecordHistoryVC.swift   |   14 
 DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.swift     |  102 ++
 DolphinEnglishLearnStudent/Services/NetworkRequest.swift                |  278 ++++++
 DolphinEnglishLearnStudent/Config/Config.swift                          |   34 
 DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.xib       |   13 
 DolphinEnglishLearnStudent/Models/CommonModel.swift                     |  237 +++++
 DolphinEnglishLearnStudent/Moudle/Market/MarketVC.swift                 |  109 ++
 DolphinEnglishLearnStudent/Moudle/Me/VC/StudyVC.swift                   |   18 
 DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.xib         |    3 
 DolphinEnglishLearnStudent/Other/CommonWebVC.swift                      |   32 
 DolphinEnglishLearnStudent.xcodeproj/project.pbxproj                    |   68 +
 DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.swift       |    7 
 DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.xib           |   26 
 43 files changed, 2,528 insertions(+), 127 deletions(-)

diff --git a/DolphinEnglishLearnStudent.xcodeproj/project.pbxproj b/DolphinEnglishLearnStudent.xcodeproj/project.pbxproj
index 002fec5..03e9779 100644
--- a/DolphinEnglishLearnStudent.xcodeproj/project.pbxproj
+++ b/DolphinEnglishLearnStudent.xcodeproj/project.pbxproj
@@ -58,6 +58,13 @@
 		1319B0292C0818540052F889 /* HomeListenStory_2_VC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1319B0282C0818540052F889 /* HomeListenStory_2_VC.swift */; };
 		1319B02C2C081A320052F889 /* SimpleImageCCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1319B02A2C081A320052F889 /* SimpleImageCCell.swift */; };
 		1319B02D2C081A320052F889 /* SimpleImageCCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1319B02B2C081A320052F889 /* SimpleImageCCell.xib */; };
+		1319B0312C0859370052F889 /* Services.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1319B02F2C0859370052F889 /* Services.swift */; };
+		1319B0322C0859370052F889 /* NetworkRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1319B0302C0859370052F889 /* NetworkRequest.swift */; };
+		1319B0352C0859E20052F889 /* UserViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1319B0342C0859E20052F889 /* UserViewModel.swift */; };
+		131C030A2C0D564000EA4C25 /* MarketTagCCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 131C03092C0D564000EA4C25 /* MarketTagCCell.xib */; };
+		131C030B2C0D564000EA4C25 /* MarketTagCCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131C03082C0D564000EA4C25 /* MarketTagCCell.swift */; };
+		131C030D2C0D6A4800EA4C25 /* CommonBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131C030C2C0D6A4800EA4C25 /* CommonBannerView.swift */; };
+		131C03112C0DA5D500EA4C25 /* CityAddressPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131C03102C0DA5D500EA4C25 /* CityAddressPickerView.swift */; };
 		133386382C007E91002EE788 /* HomeListenFight_lesson_2_VC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 133386372C007E91002EE788 /* HomeListenFight_lesson_2_VC.swift */; };
 		13397D962C05EA9D003440F9 /* ListenFight_Game_CCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13397D942C05EA9D003440F9 /* ListenFight_Game_CCell.swift */; };
 		13397D972C05EA9D003440F9 /* ListenFight_Game_CCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13397D952C05EA9D003440F9 /* ListenFight_Game_CCell.xib */; };
@@ -81,6 +88,8 @@
 		13A830FA2C043A0600BB2F23 /* Lesson_3_AnswerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13A830F92C043A0600BB2F23 /* Lesson_3_AnswerView.xib */; };
 		13AA25392C00759600F075B3 /* HomeStudyCompleteVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13AA25372C00759600F075B3 /* HomeStudyCompleteVC.swift */; };
 		13AA253A2C00759600F075B3 /* HomeStudyCompleteVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13AA25382C00759600F075B3 /* HomeStudyCompleteVC.xib */; };
+		13CD3AC72C0874B3007E1065 /* CommonModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CD3AC62C0874B3007E1065 /* CommonModel.swift */; };
+		13CD3AC92C0886E5007E1065 /* RefreshModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CD3AC82C0886E5007E1065 /* RefreshModel.swift */; };
 		13CDF4492C0566E400E8D4FD /* HomeListenFight_lesson_4_VC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CDF4482C0566E400E8D4FD /* HomeListenFight_lesson_4_VC.swift */; };
 		13CDF44C2C056A6900E8D4FD /* ListenFight_lesson_4_CCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13CDF44B2C056A6900E8D4FD /* ListenFight_lesson_4_CCell.xib */; };
 		13CDF44D2C056A6900E8D4FD /* ListenFight_lesson_4_CCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13CDF44A2C056A6900E8D4FD /* ListenFight_lesson_4_CCell.swift */; };
@@ -157,6 +166,13 @@
 		1319B0282C0818540052F889 /* HomeListenStory_2_VC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeListenStory_2_VC.swift; sourceTree = "<group>"; };
 		1319B02A2C081A320052F889 /* SimpleImageCCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleImageCCell.swift; sourceTree = "<group>"; };
 		1319B02B2C081A320052F889 /* SimpleImageCCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SimpleImageCCell.xib; sourceTree = "<group>"; };
+		1319B02F2C0859370052F889 /* Services.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Services.swift; sourceTree = "<group>"; };
+		1319B0302C0859370052F889 /* NetworkRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkRequest.swift; sourceTree = "<group>"; };
+		1319B0342C0859E20052F889 /* UserViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserViewModel.swift; sourceTree = "<group>"; };
+		131C03082C0D564000EA4C25 /* MarketTagCCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarketTagCCell.swift; sourceTree = "<group>"; };
+		131C03092C0D564000EA4C25 /* MarketTagCCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MarketTagCCell.xib; sourceTree = "<group>"; };
+		131C030C2C0D6A4800EA4C25 /* CommonBannerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CommonBannerView.swift; sourceTree = "<group>"; };
+		131C03102C0DA5D500EA4C25 /* CityAddressPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CityAddressPickerView.swift; sourceTree = "<group>"; };
 		133386372C007E91002EE788 /* HomeListenFight_lesson_2_VC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeListenFight_lesson_2_VC.swift; sourceTree = "<group>"; };
 		13397D942C05EA9D003440F9 /* ListenFight_Game_CCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListenFight_Game_CCell.swift; sourceTree = "<group>"; };
 		13397D952C05EA9D003440F9 /* ListenFight_Game_CCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ListenFight_Game_CCell.xib; sourceTree = "<group>"; };
@@ -180,6 +196,8 @@
 		13A830F92C043A0600BB2F23 /* Lesson_3_AnswerView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = Lesson_3_AnswerView.xib; sourceTree = "<group>"; };
 		13AA25372C00759600F075B3 /* HomeStudyCompleteVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeStudyCompleteVC.swift; sourceTree = "<group>"; };
 		13AA25382C00759600F075B3 /* HomeStudyCompleteVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = HomeStudyCompleteVC.xib; sourceTree = "<group>"; };
+		13CD3AC62C0874B3007E1065 /* CommonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonModel.swift; sourceTree = "<group>"; };
+		13CD3AC82C0886E5007E1065 /* RefreshModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RefreshModel.swift; sourceTree = "<group>"; };
 		13CDF4482C0566E400E8D4FD /* HomeListenFight_lesson_4_VC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeListenFight_lesson_4_VC.swift; sourceTree = "<group>"; };
 		13CDF44A2C056A6900E8D4FD /* ListenFight_lesson_4_CCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListenFight_lesson_4_CCell.swift; sourceTree = "<group>"; };
 		13CDF44B2C056A6900E8D4FD /* ListenFight_lesson_4_CCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ListenFight_lesson_4_CCell.xib; sourceTree = "<group>"; };
@@ -235,6 +253,9 @@
 		130278282BFD957100DDCE81 /* DolphinEnglishLearnStudent */ = {
 			isa = PBXGroup;
 			children = (
+				13CD3AC52C08749E007E1065 /* Models */,
+				1319B0332C0859D70052F889 /* ViewModel */,
+				1319B02E2C08592D0052F889 /* Services */,
 				130278632BFD9E5D00DDCE81 /* Moudle */,
 				130278582BFD985E00DDCE81 /* Other */,
 				1302784E2BFD97EF00DDCE81 /* Login */,
@@ -275,6 +296,7 @@
 		130278472BFD979200DDCE81 /* Base */ = {
 			isa = PBXGroup;
 			children = (
+				1319B0362C085B040052F889 /* View */,
 				130278432BFD979200DDCE81 /* BaseNav.swift */,
 				130278442BFD979200DDCE81 /* BaseTabBarVC.swift */,
 				130278452BFD979200DDCE81 /* BaseVC.swift */,
@@ -295,6 +317,7 @@
 		130278562BFD985E00DDCE81 /* UIView */ = {
 			isa = PBXGroup;
 			children = (
+				131C030C2C0D6A4800EA4C25 /* CommonBannerView.swift */,
 				130278512BFD985E00DDCE81 /* BitrhdayPickerView.swift */,
 				130278522BFD985E00DDCE81 /* CommonAlertView.swift */,
 				130278532BFD985E00DDCE81 /* CommonAlertView.xib */,
@@ -302,6 +325,7 @@
 				130278552BFD985E00DDCE81 /* CommonInputView.xib */,
 				1362C75E2BFF4BA900BD7F73 /* StudyHandleView.swift */,
 				1362C7602BFF4BB100BD7F73 /* StudyHandleView.xib */,
+				131C03102C0DA5D500EA4C25 /* CityAddressPickerView.swift */,
 			);
 			path = UIView;
 			sourceTree = "<group>";
@@ -352,6 +376,8 @@
 			children = (
 				1302786A2BFD9ED600DDCE81 /* MarketCCell.swift */,
 				1302786B2BFD9ED600DDCE81 /* MarketCCell.xib */,
+				131C03082C0D564000EA4C25 /* MarketTagCCell.swift */,
+				131C03092C0D564000EA4C25 /* MarketTagCCell.xib */,
 			);
 			path = CCell;
 			sourceTree = "<group>";
@@ -395,6 +421,31 @@
 				130278902BFD9FBF00DDCE81 /* Home_1_TCell.xib */,
 			);
 			path = TCell;
+			sourceTree = "<group>";
+		};
+		1319B02E2C08592D0052F889 /* Services */ = {
+			isa = PBXGroup;
+			children = (
+				1319B0302C0859370052F889 /* NetworkRequest.swift */,
+				1319B02F2C0859370052F889 /* Services.swift */,
+			);
+			path = Services;
+			sourceTree = "<group>";
+		};
+		1319B0332C0859D70052F889 /* ViewModel */ = {
+			isa = PBXGroup;
+			children = (
+				13CD3AC82C0886E5007E1065 /* RefreshModel.swift */,
+				1319B0342C0859E20052F889 /* UserViewModel.swift */,
+			);
+			path = ViewModel;
+			sourceTree = "<group>";
+		};
+		1319B0362C085B040052F889 /* View */ = {
+			isa = PBXGroup;
+			children = (
+			);
+			path = View;
 			sourceTree = "<group>";
 		};
 		13649E992C002FDF001B04E2 /* CCell */ = {
@@ -456,6 +507,14 @@
 				13AA25382C00759600F075B3 /* HomeStudyCompleteVC.xib */,
 			);
 			path = VC;
+			sourceTree = "<group>";
+		};
+		13CD3AC52C08749E007E1065 /* Models */ = {
+			isa = PBXGroup;
+			children = (
+				13CD3AC62C0874B3007E1065 /* CommonModel.swift */,
+			);
+			path = Models;
 			sourceTree = "<group>";
 		};
 		13EEB88F2BFED3C6002996FC /* View */ = {
@@ -607,6 +666,7 @@
 				13EEB8A92BFF354B002996FC /* HomeListen_item_TCell.xib in Resources */,
 				13CDF4512C05757400E8D4FD /* Lesson_4_AnswerView.xib in Resources */,
 				1319B02D2C081A320052F889 /* SimpleImageCCell.xib in Resources */,
+				131C030A2C0D564000EA4C25 /* MarketTagCCell.xib in Resources */,
 				130278982BFD9FBF00DDCE81 /* GoodsItemTCell.xib in Resources */,
 				13CDF44C2C056A6900E8D4FD /* ListenFight_lesson_4_CCell.xib in Resources */,
 				130278962BFD9FBF00DDCE81 /* Home_1_TCell.xib in Resources */,
@@ -669,12 +729,19 @@
 				130278992BFD9FBF00DDCE81 /* Home_1_TCell.swift in Sources */,
 				1302784B2BFD979200DDCE81 /* TapBtn.swift in Sources */,
 				13CDF44F2C05756C00E8D4FD /* Lesson_4_AnswerView.swift in Sources */,
+				1319B0312C0859370052F889 /* Services.swift in Sources */,
 				13EEB8A82BFF354B002996FC /* HomeListen_item_TCell.swift in Sources */,
 				13A830F12C04196400BB2F23 /* HomeListenFight_lesson_3_VC.swift in Sources */,
 				13CDF44D2C056A6900E8D4FD /* ListenFight_lesson_4_CCell.swift in Sources */,
+				131C030B2C0D564000EA4C25 /* MarketTagCCell.swift in Sources */,
+				13CD3AC72C0874B3007E1065 /* CommonModel.swift in Sources */,
+				131C030D2C0D6A4800EA4C25 /* CommonBannerView.swift in Sources */,
+				1319B0322C0859370052F889 /* NetworkRequest.swift in Sources */,
 				1362C75F2BFF4BA900BD7F73 /* StudyHandleView.swift in Sources */,
 				130278672BFD9E8C00DDCE81 /* HomeVC.swift in Sources */,
+				131C03112C0DA5D500EA4C25 /* CityAddressPickerView.swift in Sources */,
 				130278482BFD979200DDCE81 /* BaseNav.swift in Sources */,
+				1319B0352C0859E20052F889 /* UserViewModel.swift in Sources */,
 				130278622BFD999200DDCE81 /* LoginVC.swift in Sources */,
 				13EEB89C2BFF1C35002996FC /* HomeListenMenuVC.swift in Sources */,
 				13CDF4492C0566E400E8D4FD /* HomeListenFight_lesson_4_VC.swift in Sources */,
@@ -703,6 +770,7 @@
 				1302788D2BFD9F4200DDCE81 /* CoinRecordHistoryVC.swift in Sources */,
 				13A049FF2C058B1400F1F52E /* HomeListenFight_lesson_5_VC.swift in Sources */,
 				1302785A2BFD985E00DDCE81 /* CommonAlertView.swift in Sources */,
+				13CD3AC92C0886E5007E1065 /* RefreshModel.swift in Sources */,
 				1302782C2BFD957100DDCE81 /* SceneDelegate.swift in Sources */,
 				1302787D2BFD9ED600DDCE81 /* MarketExchangeVC.swift in Sources */,
 				1302789A2BFD9FBF00DDCE81 /* AddressManageTCell.swift in Sources */,
diff --git a/DolphinEnglishLearnStudent/Config/Config.swift b/DolphinEnglishLearnStudent/Config/Config.swift
index ca04b6a..f37c501 100644
--- a/DolphinEnglishLearnStudent/Config/Config.swift
+++ b/DolphinEnglishLearnStudent/Config/Config.swift
@@ -32,10 +32,35 @@
 }
 
 
+func LogSuccess(_ items:Any...,separator:String=" ",file:String=#file,function:String=#function,line:Int=#line){
+#if DEBUG
+				if #available(iOS 14.0, *) {
+								let logger = Logger(subsystem: "English", category: function)
+								logger.error("\(items)")
+				}else{
+								let file = (file as NSString).lastPathComponent.split(separator: ".").first!;
+								print("✅✅✅ SUCCESS: \(file)  \(function) [Line: \(line)]: \(items)",separator);
+				}
+
+#endif
+}
+
+func LogError(_ items:Any...,separator:String=" ",file:String=#file,function:String=#function,line:Int=#line){
+#if DEBUG
+				if #available(iOS 14.0, *) {
+								let logger = Logger(subsystem: "English", category: function)
+								logger.error("\(items)")
+				}else{
+								let file = (file as NSString).lastPathComponent.split(separator: ".").first!;
+								print("❌❌❌ ERROR: \(file)  \(function) [Line: \(line)]: \(items)",separator);
+				}
+#endif
+}
+
 func LogInfo(_ items:Any...,separator:String=" ",file:String=#file,function:String=#function,line:Int=#line){
 #if DEBUG
 				if #available(iOS 14.0, *) {
-								let logger = Logger(subsystem: "WanPai", category: function)
+								let logger = Logger(subsystem: "English", category: function)
 								logger.error("\(items)")
 				}else{
 								let file = (file as NSString).lastPathComponent.split(separator: ".").first!;
@@ -44,6 +69,13 @@
 #endif
 }
 
+func LogResponse(_ items:Any...,separator:String=" ",file:String=#file,function:String=#function,line:Int=#line){
+#if DEBUG
+				print("返回数据")
+				print(items);
+#endif
+}
+
 //提示框
 func alert(msg: String) {
 				SVProgressHUD.showInfo(withStatus: msg)
diff --git a/DolphinEnglishLearnStudent/Login/LoginVC.swift b/DolphinEnglishLearnStudent/Login/LoginVC.swift
index 21da0cb..6b2dcd1 100644
--- a/DolphinEnglishLearnStudent/Login/LoginVC.swift
+++ b/DolphinEnglishLearnStudent/Login/LoginVC.swift
@@ -41,7 +41,7 @@
 												alert(msg: "请输入验证码");return false
 								}
 
-								guard tf_phone.text!.count != 6 else {
+								guard tf_authCode.text!.count == 6 else {
 												alert(msg: "请输入6位验证码");return false
 								}
 								return true
@@ -54,14 +54,14 @@
 
 				/// 隐私协议
 				@IBAction func privacyAction(_ sender: UIButton) {
-								let vc = CommonWebVC(type: .privacyAgreement)
+								let vc = CommonWebVC(type: .PrivacyPolicy)
 								vc.title = "隐私协议"
 								self.navigationController?.pushViewController(vc, animated: true)
 				}
 
 				/// 用户协议
 				@IBAction func privacyUserAction(_ sender: UIButton) {
-								let vc = CommonWebVC(type: .userAgreement)
+								let vc = CommonWebVC(type: .UserProtocol)
 								vc.title = "用户协议"
 								self.navigationController?.pushViewController(vc, animated: true)
 				}
@@ -69,7 +69,9 @@
 
 				@IBAction func getCodeAction(_ sender: UIButton) {
 								guard authInputPhone() else {return}
-								sender.openCountDown(60, defultTitle: "获取验证码", textColor:UIColor(hexStr: "#41A2EB"), unenableColor: .gray)
+								Services.sendPhoneCode(phone: tf_phone.text!).subscribe(onNext: {_ in
+												sender.openCountDown(60, defultTitle: "获取验证码", textColor:UIColor(hexStr: "#41A2EB"), unenableColor: .gray)
+								}).disposed(by: disposeBag)
 				}
 
 				@IBAction func loginAction(_ sender: UIButton) {
@@ -81,6 +83,12 @@
 												alert(msg: "请阅读并同意《隐私协议》《用户协议》");return
 								}
 
-								sceneDelegate?.loginSuccess()
+								Services.login(phone: tf_phone.text!, code: tf_authCode.text!).subscribe(onNext: {result in
+												if var token = result.data?.token{
+																token.request_time = Int(Date().timeIntervalSince1970)
+																LoginTokenModel.saveToken(token)
+																sceneDelegate?.loginSuccess()
+												}
+								}).disposed(by: disposeBag)
 				}
 }
diff --git a/DolphinEnglishLearnStudent/Login/LoginVC.xib b/DolphinEnglishLearnStudent/Login/LoginVC.xib
index bd86a55..b58e11e 100644
--- a/DolphinEnglishLearnStudent/Login/LoginVC.xib
+++ b/DolphinEnglishLearnStudent/Login/LoginVC.xib
@@ -131,6 +131,7 @@
                     </constraints>
                     <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                     <state key="normal" image="btn_choose_u"/>
+                    <state key="selected" image="btn_choose"/>
                     <connections>
                         <action selector="chooseAction:" destination="-1" eventType="touchUpInside" id="taa-1D-MNJ"/>
                     </connections>
@@ -210,6 +211,7 @@
     </objects>
     <resources>
         <image name="bg_login" width="296" height="129"/>
+        <image name="btn_choose" width="28" height="28"/>
         <image name="btn_choose_u" width="28" height="28"/>
         <image name="icon_input_code" width="15" height="18"/>
         <image name="icon_input_phone" width="16" height="18"/>
diff --git a/DolphinEnglishLearnStudent/Models/CommonModel.swift b/DolphinEnglishLearnStudent/Models/CommonModel.swift
new file mode 100644
index 0000000..b41fefc
--- /dev/null
+++ b/DolphinEnglishLearnStudent/Models/CommonModel.swift
@@ -0,0 +1,237 @@
+//
+//  CommonModel.swift
+//  DolphinEnglishLearnStudent
+//
+//  Created by 无故事王国 on 2024/5/30.
+//
+
+import Foundation
+import HandyJSON
+import UserDefaultsStore
+
+struct LoginModel:HandyJSON{
+				var token:LoginTokenModel?
+}
+
+struct LoginTokenModel:HandyJSON,Identifiable,Codable{
+				static let idKey = \LoginTokenModel.id
+				var id: Int = 0
+
+				var access_token = ""
+				var expires_in = 0
+				var request_time = 0 //请求时间
+
+				private static let userInfo = UserDefaultsStore<LoginTokenModel>(uniqueIdentifier: "LoginTokenModel")!
+
+				static func saveToken(_ model:LoginTokenModel){
+								do{
+												try LoginTokenModel.userInfo.save(model)
+								}catch{
+
+								}
+				}
+
+				static func isOverdue()->Bool{
+								if let token = LoginTokenModel.getToken(){
+												//过期时间(秒)
+												let overdueTimeval = token.expires_in * 60 + token.request_time
+												
+												if overdueTimeval < Int(Date().timeIntervalSince1970){
+																return true
+												}
+												return false
+								}
+								return true
+				}
+
+				static func getToken()->LoginTokenModel?{
+								return LoginTokenModel.userInfo.allObjects().first
+				}
+
+				static func clearToken(){
+								LoginTokenModel.userInfo.deleteAll()
+				}
+}
+
+
+struct RecommendModel:HandyJSON{
+				var basicCount: Int = 0
+				var coverImg: String = ""
+				var createBy: String = ""
+				var createTime: String = ""
+				var detail: String = ""
+				var detailImg: String = ""
+				var disabled: Bool = false
+				var id: Int = 0
+				var insertTime: String = ""
+				var integral: Int = 0
+				var inventory: Int = 0
+				var isDelete: Int = 0
+				var name: String = ""
+				var price: Int = 0
+				var surplus: Int = 0
+				var total: Int = 0
+				var type: Int = 0
+				var typeIds: String = ""
+				var updateBy: String = ""
+				var updateTime: String = ""
+				var userCount: Int = 0
+}
+
+struct MarketModel:HandyJSON{
+				var basicCount: Int = 0
+				var coverImg: String = ""
+				var createBy: String = ""
+				var createTime: String = ""
+				var detail: String = ""
+				var detailImg: String = ""
+				var disabled: Bool = false
+				var id: Int = 0
+				var integral: Int = 0
+				var inventory: Int = 0
+				var isDelete: Int = 0
+				var name: String = ""
+				var price: Int = 0
+				var surplus: Int = 0
+				var total: Int = 0
+				var type: Int = 0
+				var typeIds: String = ""
+				var updateBy: String = ""
+				var updateTime: String = ""
+				var userCount: Int = 0
+}
+
+struct MarketTypeModel:HandyJSON,Hashable{
+				var id = 0
+				var name = ""
+}
+
+struct MarketDetailModel:HandyJSON{
+				var exchangeNumber: Int = 0
+				var good: MarketModel?
+				var goodTypes = [MarketTypeModel]()
+				var orderNumber: String = ""
+				var recipient: MarketRecipientModel?
+}
+
+struct MarketRecipientModel:HandyJSON,Hashable{
+				var id = 0
+				var name = ""
+}
+
+struct AddressModel:HandyJSON{
+				var address: String = ""
+				var city: String = ""
+				var cityCode: String = ""
+				var createBy: String = ""
+				var createTime: String = ""
+				var disabled: Bool = false
+				var id: Int = 0
+				var isDefault: Int = 0
+				var province: String = ""
+				var provinceCode: String = ""
+				var recipient: String = ""
+				var recipientPhone: String = ""
+				var updateBy: String = ""
+				var updateTime: String = ""
+				var userId: Int = 0
+}
+
+struct AddressTreeModel:HandyJSON{
+				var id = 0
+				var name = ""
+				var code = ""
+				var parentId = 0
+				var children:[AddressTreeModel]?
+}
+
+struct IntegralModel:HandyJSON{
+				var createBy: String = ""
+				var createTime: String = ""
+				var disabled: Bool = false
+				var gameId: Int = 0
+				var id: Int = 0
+				var integral: String = ""
+				var method: String = ""
+				var storyId: Int = 0
+				var type: String = ""
+				var updateBy: String = ""
+				var updateTime: String = ""
+				var userId: Int = 0
+}
+
+struct ExchangeRecordModel:HandyJSON{
+				var completeTime: String = ""
+				var consigneeAddress: String = ""
+				var consigneeName: String = ""
+				var consigneePhone: String = ""
+				var count: Int = 0
+				var createBy: String = ""
+				var createTime: String = ""
+				var disabled: Bool = false
+				var express: String = ""
+				var expressNumber: String = ""
+				var expressTime: String = ""
+				var goodsId: Int = 0
+				var id: Int = 0
+				var insertTime: String = ""
+				var integral: Int = 0
+				var orderNumber: String = ""
+				var state: Int = 0
+				var updateBy: String = ""
+				var updateTime: String = ""
+				var userId: Int = 0
+}
+
+struct StudyGamesModel:HandyJSON{
+				var gameRecordList = [StudyGamesRecordModel]()
+				var record:StudyDataRecordModel?
+}
+
+
+struct StudyGamesRecordModel:HandyJSON{
+				var accuracy: Int = 0
+				var createBy: String?
+				var createTime: String?
+				var disabled: Bool = false
+				var gameDifficulty: Int = 0
+				var gameId: Int = 0
+				var gameName: String?
+				var id: Int = 0
+				var updateBy: String?
+				var updateTime: String?
+				var userId: Int = 0
+				var useTime: Int = 0
+}
+
+struct StudyDataRecordModel:HandyJSON{
+				var answer: Int = 0
+				var createBy: String?
+				var createTime: String?
+				var day: Int = 0
+				var disabled: Bool = false
+				var id: Int = 0
+				var induction: Int = 0
+				var listen: Int = 0
+				var look: Int = 0
+				var monthStudy: Int = 0
+				var pair: Int = 0
+				var surplus: Int = 0
+				var todayStudy: Int = 0
+				var totalStudy: Int = 0
+				var updateBy: String?
+				var updateTime: String?
+				var userId: Int = 0
+				var week: Int = 0
+				var weekStudy: Int = 0
+}
+
+struct ListenWeekModel:HandyJSON{
+				var id = 0
+				var day = 0
+				var quarter = 0
+				var title = ""
+				var totalIntegral = 0
+				var type = 0
+				var week = 0
+}
diff --git a/DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.swift b/DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.swift
index d0f2c1f..5f87507 100644
--- a/DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.swift
@@ -11,11 +11,16 @@
 class AwardListCCell: UICollectionViewCell {
 
 				@IBOutlet weak var image_awar: UIImageView!
+				@IBOutlet weak var label_title: UILabel!
 				override func awakeFromNib() {
         super.awakeFromNib()
-        // Initialization code
     }
 
+				func setModel(_ model:RecommendModel){
+								image_awar.sd_setImage(with: URL(string: model.coverImg))
+								image_awar.jq_cornerRadius = 8
+								label_title.text = model.name
+				}
 
 				override func layoutSubviews() {
 								super.layoutSubviews()
diff --git a/DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.xib b/DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.xib
index c926478..a185c7f 100644
--- a/DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Home/CCell/AwardListCCell.xib
@@ -10,21 +10,30 @@
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
         <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="_AwardListCCell" id="gTV-IL-0wX" customClass="AwardListCCell" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
-            <rect key="frame" x="0.0" y="0.0" width="276" height="526"/>
+            <rect key="frame" x="0.0" y="0.0" width="243" height="526"/>
             <autoresizingMask key="autoresizingMask"/>
             <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
-                <rect key="frame" x="0.0" y="0.0" width="276" height="526"/>
+                <rect key="frame" x="0.0" y="0.0" width="243" height="526"/>
                 <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                 <subviews>
                     <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="YbH-L3-L1g">
-                        <rect key="frame" x="0.0" y="0.0" width="276" height="359"/>
+                        <rect key="frame" x="0.0" y="0.0" width="243" height="316"/>
                         <color key="backgroundColor" red="0.61960784310000006" green="0.54117647059999996" blue="0.85882352939999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                         <constraints>
                             <constraint firstAttribute="width" secondItem="YbH-L3-L1g" secondAttribute="height" multiplier="1:1.3" id="K9A-Ng-kLe"/>
                         </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="boolean" keyPath="ld_maskToBoundsXIB" value="YES"/>
+                            <userDefinedRuntimeAttribute type="number" keyPath="ld_cornerRadiusXIB">
+                                <real key="value" value="8"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
                     </imageView>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wPP-pc-amm">
-                        <rect key="frame" x="0.0" y="368" width="276" height="19.5"/>
+                        <rect key="frame" x="0.0" y="325" width="243" height="44"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="44" id="7Eh-PB-yFf"/>
+                        </constraints>
                         <fontDescription key="fontDescription" type="system" weight="medium" pointSize="16"/>
                         <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
                         <nil key="highlightedColor"/>
@@ -39,11 +48,12 @@
                 <constraint firstAttribute="trailing" secondItem="wPP-pc-amm" secondAttribute="trailing" id="UHp-wV-FRO"/>
                 <constraint firstItem="YbH-L3-L1g" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="WD8-o4-ZS3"/>
             </constraints>
-            <size key="customSize" width="276" height="526"/>
+            <size key="customSize" width="243" height="526"/>
             <connections>
                 <outlet property="image_awar" destination="YbH-L3-L1g" id="kuW-TO-4BH"/>
+                <outlet property="label_title" destination="wPP-pc-amm" id="vw9-1s-r0k"/>
             </connections>
-            <point key="canvasLocation" x="130.2439024390244" y="140.84745762711864"/>
+            <point key="canvasLocation" x="116.70731707317073" y="140.84745762711864"/>
         </collectionViewCell>
     </objects>
 </document>
diff --git a/DolphinEnglishLearnStudent/Moudle/Home/HomeVC.swift b/DolphinEnglishLearnStudent/Moudle/Home/HomeVC.swift
index 1715ba3..77e0951 100644
--- a/DolphinEnglishLearnStudent/Moudle/Home/HomeVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Home/HomeVC.swift
@@ -11,10 +11,12 @@
 
     override func viewDidLoad() {
         super.viewDidLoad()
-
-								AwardListView.show {
-												
-								}
+								Services.goodRecommend().subscribe(onNext: { data in
+												AwardListView.show(items: data.data ?? []) {[weak self] model in
+																let vc = MarketContentVC(goodsId: model.id)
+																self?.push(vc: vc)
+												}
+								}).disposed(by: disposeBag)
     }
 
 				@IBAction func listenAction(_ sender: UIButton) {
diff --git a/DolphinEnglishLearnStudent/Moudle/Home/Listen/VC/HomeListenMenuVC.swift b/DolphinEnglishLearnStudent/Moudle/Home/Listen/VC/HomeListenMenuVC.swift
index d22fedc..366d310 100644
--- a/DolphinEnglishLearnStudent/Moudle/Home/Listen/VC/HomeListenMenuVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Home/Listen/VC/HomeListenMenuVC.swift
@@ -9,15 +9,27 @@
 
 class HomeListenMenuVC: BaseVC {
 
+
 				@IBOutlet weak var tableView: UITableView!
 				@IBOutlet weak var collectionView: UICollectionView!
 
+				private var repeatColors = ["#F8A169","#92CADB","#9E8ADB","#6DD1BA","#37C06E","#DEB975","#C54A59","#5DA0D3","#F0C433","#DC4827"]
 				private var titleItems = ["第一季","第二季","第三季","第四季"]
 				private var selectIndexPath:IndexPath = IndexPath(row: 0, section: 0)
 
+				private var dataItems = Array<[ListenWeekModel]>(repeating: [], count: 4)
+
 				override func viewDidLoad() {
 								super.viewDidLoad()
+								getData()
+				}
 
+
+				private func getData(){
+								Services.weekList(quarter: selectIndexPath.row).subscribe(onNext: {result in
+												self.dataItems[self.selectIndexPath.row] = result.data ?? []
+												self.collectionView.reloadData()
+								}).disposed(by: disposeBag)
 				}
 
 				override func setUI() {
@@ -53,7 +65,7 @@
 				}
 
 				func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-								return 20
+								return dataItems[selectIndexPath.row].count
 				}
 
 				func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
@@ -74,6 +86,10 @@
 extension HomeListenMenuVC:UITableViewDataSource,UITableViewDelegate{
 				func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
 								selectIndexPath = indexPath
+
+								if dataItems[indexPath.row].count == 0{
+												getData()
+								}
 								tableView.reloadData()
 				}
 
diff --git a/DolphinEnglishLearnStudent/Moudle/Home/View/AwardListView.swift b/DolphinEnglishLearnStudent/Moudle/Home/View/AwardListView.swift
index 3086483..62af126 100644
--- a/DolphinEnglishLearnStudent/Moudle/Home/View/AwardListView.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Home/View/AwardListView.swift
@@ -11,6 +11,8 @@
 
 				@IBOutlet weak var collectionView: UICollectionView!
 				@IBOutlet weak var view_container: UIView!
+				private var items = [RecommendModel]()
+				private var clickClouse:((RecommendModel)->Void)!
 				override func awakeFromNib() {
 								super.awakeFromNib()
 								self.alpha = 0
@@ -22,8 +24,13 @@
 								layoutIfNeeded()
 				}
 
-				static func show(clouse:@escaping ()->Void){
+				static func show(items:[RecommendModel],clouse:@escaping (RecommendModel)->Void){
+
+								if items.count == 0{return}
+
 								let awardListView = AwardListView.jq_loadNibView()
+								awardListView.items = items
+								awardListView.clickClouse = clouse
 								sceneDelegate?.window?.addSubview(awardListView)
 								awardListView.frame = sceneDelegate?.window?.frame ?? .zero
 
@@ -31,6 +38,8 @@
 												awardListView.alpha = 1
 												awardListView.view_container.transform = .init(translationX: 1.0, y: 1.0)
 												awardListView.layoutIfNeeded()
+								}completion: { _ in
+												awardListView.collectionView.reloadData()
 								}
 				}
 
@@ -45,23 +54,36 @@
 }
 
 extension AwardListView:UICollectionViewDelegate{
+				func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
 
+
+								UIView.animate(withDuration: 0.4) {
+												self.alpha = 0
+												self.view_container.transform = .init(scaleX: 0.1, y: 0.1)
+								} completion: { _ in
+												self.removeFromSuperview()
+												let item = self.items[indexPath.row]
+												self.clickClouse(item)
+								}
+				}
 }
 
 extension AwardListView:UICollectionViewDataSource{
 				func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+								let item = items[indexPath.row]
 								let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "_AwardListCCell", for: indexPath) as! AwardListCCell
+								cell.setModel(item)
 								return cell
 				}
 
 				func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-								return 6
+								return items.count
 				}
 }
 
 extension AwardListView:UICollectionViewDelegateFlowLayout{
 				func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
-								let w = (self.jq_width - 74 - 190) / 3.0
+								let w = (JQ_ScreenW - 37 * 2 - 144 * 2 - 44 * 2) / 3.0
 								return CGSize(width: w, height: w * 1.552)
 				}
 
diff --git a/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketCCell.swift b/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketCCell.swift
index 0a4e206..cb6e8e5 100644
--- a/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketCCell.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketCCell.swift
@@ -18,6 +18,16 @@
         
     }
 
+				var marketModel:MarketModel?{
+								didSet{
+												if let m = marketModel{
+																cover_imageView.sd_setImage(with: URL(string: m.coverImg))
+																label_title.text = m.name
+																label_coin.text = "\(m.integral)积分"
+												}
+								}
+				}
+
 				override func layoutSubviews() {
 								super.layoutSubviews()
 								jq_addShadows(shadowColor: UIColor(hexStr: "#D9D9D9"), corner: 8, radius: 20, offset: CGSize(width: 0, height: 20), opacity: 1)
diff --git a/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketTagCCell.swift b/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketTagCCell.swift
new file mode 100644
index 0000000..0180dc4
--- /dev/null
+++ b/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketTagCCell.swift
@@ -0,0 +1,20 @@
+//
+//  MarketTagCCell.swift
+//  DolphinEnglishLearnStudent
+//
+//  Created by 无故事王国 on 2024/6/3.
+//
+
+import UIKit
+
+class MarketTagCCell: UICollectionViewCell {
+
+				@IBOutlet weak var view_container: UIView!
+				@IBOutlet weak var label_name: UILabel!
+				
+				override func awakeFromNib() {
+        super.awakeFromNib()
+								view_container.jq_borderColor = UIColor(hexString: "#41A2EB")
+    }
+
+}
diff --git a/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketTagCCell.xib b/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketTagCCell.xib
new file mode 100644
index 0000000..b8982d1
--- /dev/null
+++ b/DolphinEnglishLearnStudent/Moudle/Market/CCell/MarketTagCCell.xib
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
+    <device id="ipad10_9rounded" orientation="portrait" layout="fullscreen" appearance="light"/>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
+        <capability name="System colors in document resources" minToolsVersion="11.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="_MarketTagCCell" id="gTV-IL-0wX" customClass="MarketTagCCell" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
+            <rect key="frame" x="0.0" y="0.0" width="106" height="66"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
+                <rect key="frame" x="0.0" y="0.0" width="106" height="66"/>
+                <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ynz-c6-wvK">
+                        <rect key="frame" x="0.0" y="0.0" width="106" height="66"/>
+                        <subviews>
+                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fam-fP-fIA">
+                                <rect key="frame" x="17" y="10" width="72" height="47"/>
+                                <fontDescription key="fontDescription" type="system" weight="semibold" pointSize="16"/>
+                                <color key="textColor" red="0.25490196079999999" green="0.63529411759999999" blue="0.92156862750000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                <nil key="highlightedColor"/>
+                            </label>
+                        </subviews>
+                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                        <constraints>
+                            <constraint firstAttribute="trailing" secondItem="fam-fP-fIA" secondAttribute="trailing" constant="17" id="Zzp-0t-bAM"/>
+                            <constraint firstAttribute="bottom" secondItem="fam-fP-fIA" secondAttribute="bottom" constant="9" id="aCk-9L-SKS"/>
+                            <constraint firstItem="fam-fP-fIA" firstAttribute="top" secondItem="ynz-c6-wvK" secondAttribute="top" constant="10" id="k72-Fv-BOv"/>
+                            <constraint firstItem="fam-fP-fIA" firstAttribute="leading" secondItem="ynz-c6-wvK" secondAttribute="leading" constant="17" id="wC7-gL-7u1"/>
+                        </constraints>
+                        <userDefinedRuntimeAttributes>
+                            <userDefinedRuntimeAttribute type="boolean" keyPath="ld_maskToBoundsXIB" value="YES"/>
+                            <userDefinedRuntimeAttribute type="number" keyPath="ld_cornerRadiusXIB">
+                                <real key="value" value="20.5"/>
+                            </userDefinedRuntimeAttribute>
+                        </userDefinedRuntimeAttributes>
+                    </view>
+                </subviews>
+            </view>
+            <constraints>
+                <constraint firstAttribute="trailing" secondItem="ynz-c6-wvK" secondAttribute="trailing" id="QjW-oE-Tgj"/>
+                <constraint firstAttribute="bottom" secondItem="ynz-c6-wvK" secondAttribute="bottom" id="e07-4t-A2U"/>
+                <constraint firstItem="ynz-c6-wvK" firstAttribute="top" secondItem="gTV-IL-0wX" secondAttribute="top" id="ew2-Uv-ect"/>
+                <constraint firstItem="ynz-c6-wvK" firstAttribute="leading" secondItem="gTV-IL-0wX" secondAttribute="leading" id="ohm-Eq-BKS"/>
+            </constraints>
+            <size key="customSize" width="106" height="66"/>
+            <connections>
+                <outlet property="label_name" destination="fam-fP-fIA" id="uca-7s-UDX"/>
+                <outlet property="view_container" destination="ynz-c6-wvK" id="05W-u9-fnI"/>
+            </connections>
+            <point key="canvasLocation" x="68.048780487804876" y="23.898305084745765"/>
+        </collectionViewCell>
+    </objects>
+    <resources>
+        <systemColor name="systemBackgroundColor">
+            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+        </systemColor>
+    </resources>
+</document>
diff --git a/DolphinEnglishLearnStudent/Moudle/Market/MarketVC.swift b/DolphinEnglishLearnStudent/Moudle/Market/MarketVC.swift
index 47e263e..0e4998a 100644
--- a/DolphinEnglishLearnStudent/Moudle/Market/MarketVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Market/MarketVC.swift
@@ -7,17 +7,51 @@
 
 import UIKit
 import QMUIKit
+import RxRelay
+import RxSwift
+
+class MarketListViewModel:RefreshInnerModel<MarketModel>{
+
+				let keywords = BehaviorRelay<String>(value:"")
+				let types = BehaviorRelay<[String]>(value:[])
+				let menuTypes = BehaviorRelay<[MarketTypeModel]>(value:[])
+				var selectMenuTypes = Set<MarketTypeModel>(){
+								didSet{
+												types.accept(selectMenuTypes.map({$0.name}))
+												beginRefresh()
+								}
+				}
+
+				override func api() -> (Observable<BaseResponse<BaseResponseList<MarketModel>>>)? {
+								Services.goodsList(keywords: keywords.value, page: page, type: types.value)
+				}
+}
+
 
 class MarketVC: BaseVC {
 				@IBOutlet weak var tf_search: QMUITextField!
 				@IBOutlet weak var menu_collectView: UICollectionView!
 				@IBOutlet weak var content_collectionView: UICollectionView!
+				@IBOutlet weak var label_surplusCoin: UILabel!
+				
+				private let viewModel = MarketListViewModel()
 
 				private var cellW = (JQ_ScreenW - 130 - 15) / 4.0
 
     override func viewDidLoad() {
         super.viewDidLoad()
 
+								viewModel.configure(content_collectionView,needMore: true)
+								viewModel.beginRefresh()
+
+								Services.getIntegral().subscribe(onNext: {[weak self] result in
+												self?.label_surplusCoin.text = "\(result.data ?? 0)"
+								}).disposed(by: disposeBag)
+
+								Services.goodTypeStudy().subscribe(onNext: {[weak self] result in
+												self?.viewModel.menuTypes.accept(result.data ?? [])
+												self?.menu_collectView.reloadData()
+								}).disposed(by: disposeBag)
     }
 
 				override func setUI() {
@@ -28,39 +62,93 @@
 								content_collectionView.backgroundColor = .clear
 								content_collectionView.contentInset = UIEdgeInsets(top: 0, left: 65, bottom: 0, right:65)
 								content_collectionView.register(UINib(nibName: "MarketCCell", bundle: nil), forCellWithReuseIdentifier: "_MarketCCell")
+								tf_search.returnKeyType = .search
+								tf_search.delegate = self
+
+								menu_collectView.backgroundColor = .clear
+								menu_collectView.dataSource = self
+								menu_collectView.delegate = self
+								menu_collectView.register(UINib(nibName: "MarketTagCCell", bundle: nil), forCellWithReuseIdentifier: "_MarketTagCCell")
 				}
 
 				@IBAction func searchAction(_ sender: UIButton) {
-
+								view.endEditing(true)
+								viewModel.keywords.accept(tf_search.text!)
+								viewModel.beginRefresh()
 				}
 }
 
 extension MarketVC:UICollectionViewDelegate{
 				func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
-								let vc = MarketContentVC()
-								vc.title = "商品详情"
-								push(vc: vc)
+
+								if collectionView == menu_collectView{
+												let model = viewModel.menuTypes.value[indexPath.row]
+												if viewModel.selectMenuTypes.contains(model){
+																viewModel.selectMenuTypes.remove(model)
+												}else{
+																viewModel.selectMenuTypes.insert(model)
+												}
+												collectionView.reloadData()
+								}else{
+												let v = viewModel.dataSource.value?.records[indexPath.row]
+												let vc = MarketContentVC(goodsId: v?.id ?? 0)
+												vc.title = "商品详情"
+												push(vc: vc)
+								}
 				}
 }
 
 extension MarketVC:UICollectionViewDataSource{
 				func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
-								return 30
+
+								if collectionView == menu_collectView{
+												return viewModel.menuTypes.value.count
+								}
+
+								return viewModel.dataSource.value?.records.count ?? 0
 				}
 				
 				func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+
+								if collectionView == menu_collectView{
+												let cell	=  collectionView.dequeueReusableCell(withReuseIdentifier: "_MarketTagCCell", for: indexPath) as! MarketTagCCell
+												let model = viewModel.menuTypes.value[indexPath.row]
+												cell.label_name.text = model.name
+
+												if viewModel.selectMenuTypes.contains(model){
+																cell.view_container.backgroundColor = UIColor(hexString: "#41A2EB")
+																cell.view_container.jq_borderWidth = 0
+																cell.label_name.textColor = .white
+												}else{
+																cell.view_container.backgroundColor = UIColor.white
+																cell.view_container.jq_borderWidth = 1
+																cell.label_name.textColor = UIColor(hexString: "#41A2EB")
+												}
+												return cell
+								}
+
 							let cell	=  collectionView.dequeueReusableCell(withReuseIdentifier: "_MarketCCell", for: indexPath) as! MarketCCell
-								cell.backgroundColor = .gray.withAlphaComponent(0.5)
+								let model = viewModel.dataSource.value?.records[indexPath.row]
+								cell.marketModel = model
+								cell.backgroundColor = .white
 								return cell
 				}
 }
 
 extension MarketVC:UICollectionViewDelegateFlowLayout{
 				func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+
+								if collectionView == menu_collectView{
+												return CGSize(width: 100, height: 41)
+								}
+
 								return CGSize(width: cellW, height: cellW * 1.09)
 				}
 
 				func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
+								if collectionView == menu_collectView{
+												return 29
+								}
 								return 24
 				}
 
@@ -68,3 +156,12 @@
 								return 5
 				}
 }
+
+extension MarketVC:QMUITextFieldDelegate{
+				func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+								view.endEditing(true)
+								viewModel.keywords.accept(textField.text!)
+								viewModel.beginRefresh()
+								return true
+				}
+}
diff --git a/DolphinEnglishLearnStudent/Moudle/Market/MarketVC.xib b/DolphinEnglishLearnStudent/Moudle/Market/MarketVC.xib
index c2ad621..dd20976 100644
--- a/DolphinEnglishLearnStudent/Moudle/Market/MarketVC.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Market/MarketVC.xib
@@ -12,6 +12,7 @@
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MarketVC" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
             <connections>
                 <outlet property="content_collectionView" destination="EPp-Vf-S4a" id="nYe-TY-YF6"/>
+                <outlet property="label_surplusCoin" destination="82B-Dg-Sap" id="oRO-iM-jgF"/>
                 <outlet property="menu_collectView" destination="OCn-Jg-gWg" id="v5E-bg-k90"/>
                 <outlet property="tf_search" destination="Jv9-DX-cX8" id="Y6V-ux-8OL"/>
                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
diff --git a/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.swift b/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.swift
index e5ef208..5daa03a 100644
--- a/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.swift
@@ -7,11 +7,24 @@
 
 import UIKit
 import WebKit
+import RxRelay
+
+class MarketContentViewModel{
+				//购买数量
+				var number = BehaviorRelay<Int>(value:1)
+				var detailModel = BehaviorRelay<MarketDetailModel?>(value:nil)
+				var surplusCoin = BehaviorRelay<Int>(value:0)
+				var goodsId = BehaviorRelay<Int>(value:0)
+				
+//				var orderNumber = BehaviorRelay<String>(value:"")
+				//收获地址
+				var address = BehaviorRelay<[AddressModel]>(value: [])
+}
 
 class MarketContentVC: BaseVC {
 
 				@IBOutlet weak var scrollView: UIScrollView!
-				@IBOutlet weak var image_cover: UIImageView!
+				@IBOutlet weak var view_banner: CommonBannerView!
 				@IBOutlet weak var view_footer: UIView!
 				@IBOutlet weak var view_container: UIView!
 				@IBOutlet weak var label_coin: UILabel!
@@ -22,10 +35,52 @@
 				@IBOutlet weak var label_surplusCoin: UILabel!
 				@IBOutlet weak var label_costCoin: UILabel!
 				@IBOutlet weak var cons_footHei: NSLayoutConstraint!
+				@IBOutlet weak var webViewHeiCons: NSLayoutConstraint!
+
+				private var viewModel = MarketContentViewModel()
+
+			required	init(goodsId:Int) {
+								super.init(nibName: nil, bundle: nil)
+							self.viewModel.goodsId.accept(goodsId)
+				}
+				
+				required init?(coder: NSCoder) {
+								fatalError("init(coder:) has not been implemented")
+				}
 				
 				override func viewDidLoad() {
         super.viewDidLoad()
 
+								Services.goodsDetail(goodsId: viewModel.goodsId.value).subscribe(onNext: {[weak self] result in
+												if let m = result.data{
+
+																let banner = m.good?.detailImg.components(separatedBy: ",").map({ url in
+																				return CommonBannerModel(index: 0, id: 0, name: nil, resource: url, mediaType: .imageUrl)
+																})
+
+																self?.view_banner.setItems(items: banner ?? [], autoRoll: true, selectClouse: nil)
+
+																self?.label_coin.text = "\(m.good?.integral ?? 0)"
+																self?.label_costCoin.text = "\(m.good?.integral ?? 0)"
+																self?.label_title.text = m.good?.name ?? ""
+																self?.label_categry.text = m.goodTypes.map({$0.name}).joined(separator: "|")
+
+																var info_Array = Array<String>()
+																info_Array.append("剩余数量:\(m.good?.surplus ?? 0)")
+																info_Array.append("可换数量:\(m.good?.userCount ?? 0)")
+																info_Array.append("\(m.exchangeNumber)人兑换")
+
+																self?.label_info.text = info_Array.joined(separator: "|")
+																self?.webView.loadHTMLString(m.good?.detail.jq_wrapHtml() ?? "", baseURL: nil)
+																self?.viewModel.detailModel.accept(m)
+												}
+
+								}).disposed(by: disposeBag)
+
+								Services.getIntegral().subscribe(onNext: {[weak self] result in
+												self?.label_surplusCoin.text = "剩余积分:\(result.data ?? 0)"
+												self?.viewModel.surplusCoin.accept(result.data ?? 0)
+								}).disposed(by: disposeBag)
     }
 
 				override func setUI() {
@@ -34,20 +89,51 @@
 								cons_footHei.constant = 54 + UIDevice.jq_safeEdges.bottom
 				}
 
+				override func setRx() {
+								webView.scrollView.rx.observe(CGSize.self, "contentSize").map { (size) -> CGFloat? in
+												if let size = size{
+																return size.height
+												}
+												return nil
+								}.subscribe(onNext: { [unowned self](height) in
+												if let height = height{
+																self.webViewHeiCons.constant = height
+												}
+								}).disposed(by: disposeBag)
+				}
+
 
 				@IBAction func exchangeAction(_ sender: UIButton) {
-//								CommonAlertView.show(isSinple: true, content: "兑换失败,当前剩余积分不足!") {
-//
-//								}
 
-								let vc = MarketExchangeVC()
+								guard viewModel.detailModel.value?.good?.surplus != 0 else {
+												CommonAlertView.show(isSinple: true, content: "兑换失败,当前剩余数量不足!") {
+
+												}
+												return
+								}
+
+								guard viewModel.detailModel.value?.good?.userCount != 0 else {
+												CommonAlertView.show(isSinple: true, content: "兑换失败,当前可换数量不足!") {
+
+												}
+												return
+								}
+
+								guard (viewModel.detailModel.value?.good?.integral ?? 0) < viewModel.surplusCoin.value else {
+												CommonAlertView.show(isSinple: true, content: "兑换失败,当前剩余积分不足!") {
+
+												}
+												return
+								}
+
+								let vc = MarketExchangeVC(viewModel: viewModel)
 								vc.title = "立即兑换"
 								push(vc: vc)
 				}
 
 				override func viewDidLayoutSubviews() {
 								super.viewDidLayoutSubviews()
-								image_cover.jq_addCorners(corner: [.topLeft,.topRight], radius: 8)
+								view_banner.jq_addCorners(corner: [.topLeft,.topRight], radius: 8)
 								view_footer.jq_addShadows(shadowColor: UIColor(hexStr: "#DEDEDE").withAlphaComponent(0.5), corner: 0, radius: 4, offset: CGSize(width: 0, height: -1), opacity: 1)
 
 								view_container.jq_addShadows(shadowColor: UIColor(hexStr: "#D9D9D9").withAlphaComponent(0.28), corner: 8, radius: 5, offset: CGSize(width: 0, height: 2), opacity: 1)
diff --git a/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.xib b/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.xib
index 1e2ccf3..fc87ec6 100644
--- a/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketContentVC.xib
@@ -12,7 +12,6 @@
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MarketContentVC" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
             <connections>
                 <outlet property="cons_footHei" destination="O1c-0y-Iw9" id="Oj2-S6-uVD"/>
-                <outlet property="image_cover" destination="HQ8-qZ-zeA" id="0xr-UI-5I9"/>
                 <outlet property="label_categry" destination="YLo-dD-PTM" id="kCG-k8-Baa"/>
                 <outlet property="label_coin" destination="yrU-ab-vv9" id="4UT-Q9-CO3"/>
                 <outlet property="label_costCoin" destination="Br9-rb-zWu" id="Qyp-x1-Ff0"/>
@@ -21,9 +20,11 @@
                 <outlet property="label_title" destination="PgE-zX-EIu" id="FWi-qa-sK0"/>
                 <outlet property="scrollView" destination="loc-rm-BZe" id="xqU-OW-GgJ"/>
                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
+                <outlet property="view_banner" destination="lUx-IV-YIU" id="9RA-3Q-ceF"/>
                 <outlet property="view_container" destination="3V0-GL-Fmn" id="D6J-fr-4H2"/>
                 <outlet property="view_footer" destination="mp9-Bg-Kez" id="41u-8O-co7"/>
                 <outlet property="webView" destination="ZOY-ws-sjP" id="bXL-3r-nKs"/>
+                <outlet property="webViewHeiCons" destination="xMb-sR-Ext" id="8RD-Be-b0n"/>
             </connections>
         </placeholder>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
@@ -93,13 +94,6 @@
                         <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3V0-GL-Fmn">
                             <rect key="frame" x="0.0" y="0.0" width="556" height="681"/>
                             <subviews>
-                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="HQ8-qZ-zeA">
-                                    <rect key="frame" x="0.0" y="0.0" width="556" height="319.5"/>
-                                    <color key="backgroundColor" systemColor="systemGray5Color"/>
-                                    <constraints>
-                                        <constraint firstAttribute="width" secondItem="HQ8-qZ-zeA" secondAttribute="height" multiplier="1:0.575" id="4sO-41-6AB"/>
-                                    </constraints>
-                                </imageView>
                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="yrU-ab-vv9">
                                     <rect key="frame" x="14" y="329.5" width="10" height="25"/>
                                     <constraints>
@@ -171,30 +165,37 @@
                                         <wkPreferences key="preferences"/>
                                     </wkWebViewConfiguration>
                                 </wkWebView>
+                                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lUx-IV-YIU" customClass="CommonBannerView" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
+                                    <rect key="frame" x="0.0" y="0.0" width="556" height="319.5"/>
+                                    <color key="backgroundColor" systemColor="systemBackgroundColor"/>
+                                    <constraints>
+                                        <constraint firstAttribute="width" secondItem="lUx-IV-YIU" secondAttribute="height" multiplier="1:0.575" id="Vfi-RM-kqs"/>
+                                    </constraints>
+                                </view>
                             </subviews>
                             <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                             <constraints>
+                                <constraint firstItem="yrU-ab-vv9" firstAttribute="top" secondItem="lUx-IV-YIU" secondAttribute="bottom" constant="10" id="0Z9-Wg-moE"/>
                                 <constraint firstItem="fkp-fX-eUo" firstAttribute="top" secondItem="3WZ-Jf-leh" secondAttribute="bottom" constant="15" id="1lu-mH-O3t"/>
-                                <constraint firstItem="HQ8-qZ-zeA" firstAttribute="leading" secondItem="3V0-GL-Fmn" secondAttribute="leading" id="2L8-TY-eC1"/>
                                 <constraint firstAttribute="trailing" secondItem="SHM-HW-3QJ" secondAttribute="trailing" constant="14" id="3fT-Df-Icu"/>
                                 <constraint firstItem="ZOY-ws-sjP" firstAttribute="top" secondItem="fkp-fX-eUo" secondAttribute="bottom" constant="10" id="4Sb-GV-SMH"/>
                                 <constraint firstItem="fkp-fX-eUo" firstAttribute="leading" secondItem="3V0-GL-Fmn" secondAttribute="leading" constant="14" id="CGr-W8-bYc"/>
+                                <constraint firstItem="lUx-IV-YIU" firstAttribute="top" secondItem="3V0-GL-Fmn" secondAttribute="top" id="CJV-El-ct7"/>
                                 <constraint firstItem="LtS-Mg-aeT" firstAttribute="centerY" secondItem="yrU-ab-vv9" secondAttribute="centerY" id="Eqy-fC-VXN"/>
                                 <constraint firstItem="SHM-HW-3QJ" firstAttribute="leading" secondItem="3V0-GL-Fmn" secondAttribute="leading" constant="14" id="IcX-sV-UsY"/>
                                 <constraint firstAttribute="trailing" secondItem="PgE-zX-EIu" secondAttribute="trailing" constant="14" id="KOH-43-2e0"/>
+                                <constraint firstItem="lUx-IV-YIU" firstAttribute="leading" secondItem="3V0-GL-Fmn" secondAttribute="leading" id="OoB-ef-zF5"/>
                                 <constraint firstItem="3WZ-Jf-leh" firstAttribute="top" secondItem="SHM-HW-3QJ" secondAttribute="bottom" constant="15" id="TZb-uR-n12"/>
                                 <constraint firstItem="yrU-ab-vv9" firstAttribute="leading" secondItem="3V0-GL-Fmn" secondAttribute="leading" constant="14" id="bvf-qv-PXf"/>
                                 <constraint firstItem="LtS-Mg-aeT" firstAttribute="leading" secondItem="yrU-ab-vv9" secondAttribute="trailing" id="ce9-HT-eYR"/>
-                                <constraint firstItem="yrU-ab-vv9" firstAttribute="top" secondItem="HQ8-qZ-zeA" secondAttribute="bottom" constant="10" id="fcu-Lq-OG7"/>
                                 <constraint firstAttribute="trailing" secondItem="3WZ-Jf-leh" secondAttribute="trailing" constant="13" id="gDs-iU-l4D"/>
-                                <constraint firstItem="HQ8-qZ-zeA" firstAttribute="top" secondItem="3V0-GL-Fmn" secondAttribute="top" id="gge-7H-yMR"/>
+                                <constraint firstAttribute="trailing" secondItem="lUx-IV-YIU" secondAttribute="trailing" id="i5N-By-Pa9"/>
                                 <constraint firstItem="ZOY-ws-sjP" firstAttribute="leading" secondItem="3V0-GL-Fmn" secondAttribute="leading" constant="14" id="k11-lO-F1N"/>
                                 <constraint firstItem="SHM-HW-3QJ" firstAttribute="top" secondItem="PgE-zX-EIu" secondAttribute="bottom" constant="7" id="kjs-SE-QJz"/>
                                 <constraint firstItem="3WZ-Jf-leh" firstAttribute="leading" secondItem="3V0-GL-Fmn" secondAttribute="leading" constant="13" id="msq-Yj-Hkl"/>
                                 <constraint firstItem="PgE-zX-EIu" firstAttribute="top" secondItem="yrU-ab-vv9" secondAttribute="bottom" constant="7" id="tro-c3-NxF"/>
                                 <constraint firstItem="PgE-zX-EIu" firstAttribute="leading" secondItem="3V0-GL-Fmn" secondAttribute="leading" constant="14" id="upN-6F-Xy0"/>
                                 <constraint firstAttribute="bottom" secondItem="ZOY-ws-sjP" secondAttribute="bottom" constant="10" id="x2O-1I-fif"/>
-                                <constraint firstAttribute="trailing" secondItem="HQ8-qZ-zeA" secondAttribute="trailing" id="xc1-2D-IN1"/>
                                 <constraint firstAttribute="trailing" secondItem="ZOY-ws-sjP" secondAttribute="trailing" constant="14" id="zdu-6P-uIG"/>
                             </constraints>
                         </view>
@@ -225,9 +226,6 @@
     <resources>
         <systemColor name="systemBackgroundColor">
             <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
-        </systemColor>
-        <systemColor name="systemGray5Color">
-            <color red="0.89803921568627454" green="0.89803921568627454" blue="0.91764705882352937" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
         </systemColor>
     </resources>
 </document>
diff --git a/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.swift b/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.swift
index 9cad328..02bb8c4 100644
--- a/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.swift
@@ -7,10 +7,7 @@
 
 import UIKit
 import RxRelay
-
-class MarketViewModel{
-				var number = BehaviorRelay<Int>(value:1)
-}
+import QMUIKit
 
 class MarketExchangeVC: BaseVC {
 				@IBOutlet weak var scrollView: UIScrollView!
@@ -18,11 +15,57 @@
 				@IBOutlet weak var view_container: UIView!
 				@IBOutlet weak var field_number: UITextField!
 				@IBOutlet weak var cons_footerHei: NSLayoutConstraint!
+				@IBOutlet weak var label_address: UILabel!
+				@IBOutlet weak var label_address_info: UILabel!
+				@IBOutlet weak var img_cover: UIImageView!
+				@IBOutlet weak var label_goodsName: UILabel!
+				@IBOutlet weak var label_coin: UILabel!
+				@IBOutlet weak var btn_add: UIButton!
+				@IBOutlet weak var btn_reduce: UIButton!
+				@IBOutlet weak var textView_remark: QMUITextView!
+				@IBOutlet weak var label_num: UILabel!
+				@IBOutlet weak var label_needCoin: UILabel!
+				@IBOutlet weak var label_orderNum: UILabel!
+				@IBOutlet weak var label_footNeedCoin: UILabel!
 				
-				private var viewModel = MarketViewModel()
+				private var viewModel = MarketContentViewModel()
 
+				required init(viewModel:MarketContentViewModel) {
+								super.init(nibName: nil, bundle: nil)
+								self.viewModel = viewModel
+				}
+				
+				required init?(coder: NSCoder) {
+								fatalError("init(coder:) has not been implemented")
+				}
+				
     override func viewDidLoad() {
         super.viewDidLoad()
+
+								Services.redeemNow(goodId: viewModel.detailModel.value!.good!.id).subscribe(onNext: {result in
+												self.label_orderNum.text = result.data?.orderNumber ?? ""
+												self.viewModel.detailModel.accept(result.data)
+								}).disposed(by: disposeBag)
+
+								Services.addressList().subscribe(onNext: {[weak self]result in
+												self?.viewModel.address.accept(result.data ?? [])
+												if let first = result.data?.filter({$0.isDefault == 1}).first{
+																self?.label_address.text = first.address
+																self?.label_address_info.text = first.recipient + "|" + first.recipientPhone
+												}else{
+																self?.label_address.text = "新建收货地址"
+																self?.label_address_info.isHidden = true
+												}
+								}).disposed(by: disposeBag)
+
+								self.img_cover.sd_setImage(with: URL(string: viewModel.detailModel.value?.good?.coverImg))
+								self.label_goodsName.text = viewModel.detailModel.value?.good?.name ?? ""
+								self.label_coin.text = "\(viewModel.detailModel.value?.good?.integral ?? 0)"
+								if viewModel.detailModel.value?.good?.userCount == 1{
+												btn_add.isEnabled = false
+												btn_reduce.isEnabled = false
+												field_number.isEnabled = false
+								}
     }
 
 				override func setUI() {
@@ -35,25 +78,62 @@
 				override func setRx() {
 								viewModel.number.subscribe(onNext: {[weak self] num in
 												self?.field_number.text = "\(num)"
+												self?.label_num.text = "\(num)"
+												let totalCoin = num * (self?.viewModel.detailModel.value?.good?.integral ?? 0)
+												self?.label_needCoin.text = "\(totalCoin)"
+												self?.label_footNeedCoin.text = "\(totalCoin)"
 								}).disposed(by: disposeBag)
 				}
 
-
+				@IBAction func addressAction(_ sender: Any) {
+								if viewModel.address.value.filter({$0.isDefault == 1}).count > 0{
+												let vc = AddressManageVC(type: .choose)
+												vc.title = "地址管理"
+												push(vc: vc)
+								}else{
+												let vc = AddressManageVC(type: .handle)
+												vc.title = "地址管理"
+												push(vc: vc)
+								}
+				}
+				
 				@IBAction func addNumAction(_ sender: UIButton) {
-								let num = viewModel.number.value + 1
+								var num = viewModel.number.value + 1
+								if  num >= viewModel.detailModel.value?.good?.userCount ?? 0{
+												num = viewModel.detailModel.value?.good?.userCount ?? 0
+												sender.isEnabled = false
+								}
 								viewModel.number.accept(num)
 				}
 
 				@IBAction func reduceAction(_ sender: UIButton) {
 								let num = max(1,viewModel.number.value - 1)
 								viewModel.number.accept(num)
+								btn_add.isEnabled = true
 				}
 
 				@IBAction func exchangeAction(_ sender: UIButton) {
+
+								guard viewModel.address.value.filter({$0.isDefault == 1}).count != 0 else{
+												CommonAlertView.show(content: "请先设置收货地址") {
+																let vc = AddressManageVC(type: .handle)
+																vc.title = "地址管理"
+																self.push(vc: vc)
+												}
+												return
+								}
+
 								CommonAlertView.show(content: "确认兑换当前商品吗?") {
-												let vc = ExchangeResultVC(resultType: .success)
-												vc.title = "商品详情"
-												self.push(vc: vc)
+												let goodsId = self.viewModel.detailModel.value!.good!.id
+												let num = self.viewModel.number.value
+												let orderNumber = self.viewModel.detailModel.value?.orderNumber ?? ""
+												let recipientId = self.viewModel.detailModel.value?.recipient?.id ?? 0
+
+												Services.goodsExchangeStudy(goodsId: goodsId, number: num, orderNumber: orderNumber, recipientId: recipientId, remark: self.textView_remark.text!).subscribe(onNext: {_ in
+																let vc = ExchangeResultVC(resultType: .success)
+																vc.title = "商品详情"
+																self.push(vc: vc)
+												}).disposed(by: self.disposeBag)
 								}
 				}
 }
diff --git a/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.xib b/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.xib
index 10ddf4e..7835f2e 100644
--- a/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Market/VC/MarketExchangeVC.xib
@@ -11,9 +11,21 @@
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MarketExchangeVC" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
             <connections>
+                <outlet property="btn_add" destination="wqg-IO-Jti" id="tqa-wd-rR2"/>
+                <outlet property="btn_reduce" destination="H9G-ck-ezM" id="uPJ-2M-QEo"/>
                 <outlet property="cons_footerHei" destination="71z-Eh-Ya8" id="V0f-Rh-ggi"/>
                 <outlet property="field_number" destination="1nG-XY-fwB" id="xye-yR-VBc"/>
+                <outlet property="img_cover" destination="QM5-dP-No2" id="xux-xq-ol5"/>
+                <outlet property="label_address" destination="ph9-Ra-CxP" id="b0j-bK-UQV"/>
+                <outlet property="label_address_info" destination="Hns-QV-baw" id="v5s-wf-nHN"/>
+                <outlet property="label_coin" destination="Zy6-3Q-Lgi" id="WNc-y4-9Yn"/>
+                <outlet property="label_footNeedCoin" destination="Nka-ZK-eeP" id="1wN-Kd-xoF"/>
+                <outlet property="label_goodsName" destination="SZF-J0-byW" id="bMb-RR-rHM"/>
+                <outlet property="label_needCoin" destination="vFF-je-HEk" id="XDA-D5-HO1"/>
+                <outlet property="label_num" destination="p4X-ju-9r7" id="Cmx-HF-NKT"/>
+                <outlet property="label_orderNum" destination="BaU-rt-9wh" id="fwg-Lq-bZB"/>
                 <outlet property="scrollView" destination="hFz-gY-osL" id="xXh-5z-6XE"/>
+                <outlet property="textView_remark" destination="Rq2-vc-D0Q" id="sDq-vQ-gM6"/>
                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
                 <outlet property="view_container" destination="4wG-oJ-eBG" id="8U4-Q9-4Ap"/>
                 <outlet property="view_footer" destination="d3o-Ba-FIK" id="EMz-WT-ojz"/>
@@ -80,7 +92,7 @@
                                 <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="HCf-Ym-o1O">
                                     <rect key="frame" x="0.0" y="0.0" width="556" height="600"/>
                                     <subviews>
-                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sfn-3Q-b7V">
+                                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="sfn-3Q-b7V" customClass="TapBtn" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
                                             <rect key="frame" x="0.0" y="0.0" width="556" height="90"/>
                                             <subviews>
                                                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="5h7-8X-cXI">
@@ -90,44 +102,48 @@
                                                         <constraint firstAttribute="height" constant="3" id="7Bs-Y1-RKJ"/>
                                                     </constraints>
                                                 </view>
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ph9-Ra-CxP">
-                                                    <rect key="frame" x="14" y="28" width="492" height="20"/>
-                                                    <constraints>
-                                                        <constraint firstAttribute="height" constant="20" id="cgw-w2-dsN"/>
-                                                    </constraints>
-                                                    <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
-                                                    <color key="textColor" red="0.011764705882352941" green="0.015686274509803921" blue="0.019607843137254902" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
-                                                    <nil key="highlightedColor"/>
-                                                </label>
                                                 <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_more_gray" translatesAutoresizingMaskIntoConstraints="NO" id="jKh-8m-ogE">
                                                     <rect key="frame" x="536" y="40" width="6" height="10"/>
                                                 </imageView>
-                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Hns-QV-baw">
-                                                    <rect key="frame" x="14" y="53" width="492" height="14.5"/>
-                                                    <fontDescription key="fontDescription" type="system" pointSize="12"/>
-                                                    <nil key="textColor"/>
-                                                    <nil key="highlightedColor"/>
-                                                </label>
+                                                <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="ZAd-Ha-PgP">
+                                                    <rect key="frame" x="14" y="25.5" width="36" height="39.5"/>
+                                                    <subviews>
+                                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ph9-Ra-CxP">
+                                                            <rect key="frame" x="0.0" y="0.0" width="36" height="20"/>
+                                                            <constraints>
+                                                                <constraint firstAttribute="height" constant="20" id="cgw-w2-dsN"/>
+                                                            </constraints>
+                                                            <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
+                                                            <color key="textColor" red="0.011764705882352941" green="0.015686274509803921" blue="0.019607843137254902" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                                                            <nil key="highlightedColor"/>
+                                                        </label>
+                                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Hns-QV-baw">
+                                                            <rect key="frame" x="0.0" y="25" width="36" height="14.5"/>
+                                                            <fontDescription key="fontDescription" type="system" pointSize="12"/>
+                                                            <nil key="textColor"/>
+                                                            <nil key="highlightedColor"/>
+                                                        </label>
+                                                    </subviews>
+                                                </stackView>
                                             </subviews>
                                             <constraints>
                                                 <constraint firstItem="jKh-8m-ogE" firstAttribute="centerY" secondItem="sfn-3Q-b7V" secondAttribute="centerY" id="AIT-eX-UYg"/>
                                                 <constraint firstAttribute="trailing" secondItem="5h7-8X-cXI" secondAttribute="trailing" id="Byx-At-ZHn"/>
                                                 <constraint firstAttribute="height" constant="90" id="Gtx-jC-H0V"/>
-                                                <constraint firstItem="ph9-Ra-CxP" firstAttribute="leading" secondItem="sfn-3Q-b7V" secondAttribute="leading" constant="14" id="L6f-uW-gIs"/>
-                                                <constraint firstItem="ph9-Ra-CxP" firstAttribute="top" secondItem="sfn-3Q-b7V" secondAttribute="top" constant="28" id="Pzt-wT-2Uz"/>
+                                                <constraint firstItem="ZAd-Ha-PgP" firstAttribute="leading" secondItem="sfn-3Q-b7V" secondAttribute="leading" constant="14" id="KKV-Kz-UZ6"/>
                                                 <constraint firstAttribute="bottom" secondItem="5h7-8X-cXI" secondAttribute="bottom" id="dS7-Gn-QOD"/>
-                                                <constraint firstAttribute="trailing" secondItem="jKh-8m-ogE" secondAttribute="trailing" constant="14" id="fpD-Vw-mh2"/>
                                                 <constraint firstItem="5h7-8X-cXI" firstAttribute="leading" secondItem="sfn-3Q-b7V" secondAttribute="leading" id="g86-ED-gAW"/>
-                                                <constraint firstItem="Hns-QV-baw" firstAttribute="trailing" secondItem="ph9-Ra-CxP" secondAttribute="trailing" id="hFX-F5-1NJ"/>
-                                                <constraint firstItem="Hns-QV-baw" firstAttribute="leading" secondItem="ph9-Ra-CxP" secondAttribute="leading" id="l9W-26-0ij"/>
-                                                <constraint firstItem="Hns-QV-baw" firstAttribute="top" secondItem="ph9-Ra-CxP" secondAttribute="bottom" constant="5" id="mta-MA-VXe"/>
-                                                <constraint firstAttribute="trailing" secondItem="ph9-Ra-CxP" secondAttribute="trailing" constant="50" id="oe6-gk-huK"/>
+                                                <constraint firstAttribute="trailing" secondItem="jKh-8m-ogE" secondAttribute="trailing" constant="14" id="on7-ez-QYT"/>
+                                                <constraint firstItem="ZAd-Ha-PgP" firstAttribute="centerY" secondItem="sfn-3Q-b7V" secondAttribute="centerY" id="qhc-bm-AqF"/>
                                             </constraints>
+                                            <connections>
+                                                <action selector="addressAction:" destination="-1" eventType="touchUpInside" id="fj4-mV-Wor"/>
+                                            </connections>
                                         </view>
                                         <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Pcy-2J-bsd">
                                             <rect key="frame" x="0.0" y="90" width="556" height="366"/>
                                             <subviews>
-                                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="QM5-dP-No2">
+                                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="QM5-dP-No2">
                                                     <rect key="frame" x="14" y="15" width="170" height="170"/>
                                                     <constraints>
                                                         <constraint firstAttribute="width" constant="170" id="gTg-aH-0dy"/>
@@ -239,9 +255,8 @@
                                                         <action selector="addNumAction:" destination="-1" eventType="touchUpInside" id="N9f-5O-JZz"/>
                                                     </connections>
                                                 </button>
-                                                <button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="H9G-ck-ezM">
-                                                    <rect key="frame" x="702" y="206" width="32" height="22"/>
-                                                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+                                                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="H9G-ck-ezM">
+                                                    <rect key="frame" x="440" y="207" width="32" height="22"/>
                                                     <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                                                     <state key="normal" image="btn_reduce"/>
                                                     <state key="disabled" image="btn_reduce_un"/>
@@ -253,11 +268,13 @@
                                             <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                                             <constraints>
                                                 <constraint firstAttribute="trailing" secondItem="SZF-J0-byW" secondAttribute="trailing" constant="13" id="2bc-jD-0jQ"/>
+                                                <constraint firstItem="Y1j-mH-7vJ" firstAttribute="centerY" secondItem="H9G-ck-ezM" secondAttribute="centerY" id="3fZ-cn-vBb"/>
                                                 <constraint firstItem="QM5-dP-No2" firstAttribute="top" secondItem="Pcy-2J-bsd" secondAttribute="top" constant="15" id="3oV-je-E0W"/>
                                                 <constraint firstItem="SZF-J0-byW" firstAttribute="leading" secondItem="QM5-dP-No2" secondAttribute="trailing" constant="13" id="4nD-DW-K4G"/>
                                                 <constraint firstItem="wqg-IO-Jti" firstAttribute="leading" secondItem="Y1j-mH-7vJ" secondAttribute="trailing" id="96J-NH-U7L"/>
                                                 <constraint firstItem="MS7-3T-DWG" firstAttribute="top" secondItem="EeU-Wx-jBI" secondAttribute="bottom" constant="17" id="APQ-K4-sOj"/>
                                                 <constraint firstAttribute="trailing" secondItem="xEk-ac-udO" secondAttribute="trailing" constant="14" id="AaJ-eg-xRI"/>
+                                                <constraint firstItem="wqg-IO-Jti" firstAttribute="height" secondItem="H9G-ck-ezM" secondAttribute="height" id="BxV-pF-PDX"/>
                                                 <constraint firstAttribute="trailing" secondItem="Y1j-mH-7vJ" secondAttribute="trailing" constant="42" id="Cnz-nI-ucx"/>
                                                 <constraint firstItem="xEk-ac-udO" firstAttribute="leading" secondItem="Pcy-2J-bsd" secondAttribute="leading" constant="12" id="DSj-62-NMj"/>
                                                 <constraint firstItem="MS7-3T-DWG" firstAttribute="leading" secondItem="EeU-Wx-jBI" secondAttribute="leading" id="EM3-jV-CSR"/>
@@ -269,6 +286,7 @@
                                                 <constraint firstItem="Y1j-mH-7vJ" firstAttribute="top" secondItem="h4B-Ju-L2P" secondAttribute="bottom" constant="22" id="RcG-f4-yEi"/>
                                                 <constraint firstItem="h4B-Ju-L2P" firstAttribute="centerY" secondItem="Zy6-3Q-Lgi" secondAttribute="centerY" id="ScA-Kv-FAY"/>
                                                 <constraint firstItem="xEk-ac-udO" firstAttribute="top" secondItem="5zn-TC-ZAu" secondAttribute="bottom" constant="14" id="TRf-HU-Y0g"/>
+                                                <constraint firstItem="wqg-IO-Jti" firstAttribute="width" secondItem="H9G-ck-ezM" secondAttribute="width" id="TaG-sx-WqG"/>
                                                 <constraint firstAttribute="trailing" secondItem="5zn-TC-ZAu" secondAttribute="trailing" constant="14" id="XsR-S7-5se"/>
                                                 <constraint firstItem="h4B-Ju-L2P" firstAttribute="leading" secondItem="Zy6-3Q-Lgi" secondAttribute="trailing" id="XyT-7a-Pzk"/>
                                                 <constraint firstItem="5zn-TC-ZAu" firstAttribute="top" secondItem="MS7-3T-DWG" secondAttribute="bottom" constant="12" id="Zb6-DZ-qrC"/>
@@ -276,6 +294,7 @@
                                                 <constraint firstItem="EeU-Wx-jBI" firstAttribute="top" secondItem="QM5-dP-No2" secondAttribute="bottom" constant="18" id="kWP-Z3-Uve"/>
                                                 <constraint firstItem="QM5-dP-No2" firstAttribute="leading" secondItem="Pcy-2J-bsd" secondAttribute="leading" constant="14" id="lJI-a1-yyL"/>
                                                 <constraint firstItem="EeU-Wx-jBI" firstAttribute="leading" secondItem="Pcy-2J-bsd" secondAttribute="leading" constant="14" id="pIg-OO-tpF"/>
+                                                <constraint firstItem="Y1j-mH-7vJ" firstAttribute="leading" secondItem="H9G-ck-ezM" secondAttribute="trailing" id="v1W-TC-i1N"/>
                                                 <constraint firstItem="h4B-Ju-L2P" firstAttribute="bottom" secondItem="QM5-dP-No2" secondAttribute="bottom" id="z2m-b7-4WH"/>
                                             </constraints>
                                         </view>
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/MeVC.swift b/DolphinEnglishLearnStudent/Moudle/Me/MeVC.swift
index ec4ed38..449d943 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/MeVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Me/MeVC.swift
@@ -14,11 +14,22 @@
 				@IBOutlet weak var btn_exchangeRecord: QMUIButton!
 				@IBOutlet weak var btn_share: QMUIButton!
 				@IBOutlet weak var btn_etudyRecord: QMUIButton!
-
+				@IBOutlet weak var imge_cover: UIImageView!
+				@IBOutlet weak var label_name: UILabel!
+				@IBOutlet weak var label_info: UILabel!
+				
     override func viewDidLoad() {
         super.viewDidLoad()
 
-        // Do any additional setup after loading the view.
+								Services.userInfo().subscribe(onNext: {result in
+												if let model = result.data{
+																self.imge_cover.sd_setImage(with: URL(string: model.headImg))
+																self.label_name.text = model.name
+//																var items = Array<String>()
+//																items.append("剩余积分:\(model.integral)")
+//																items.append("学习进度:\(model.integral)")
+												}
+								}).disposed(by: disposeBag)
     }
 
 
@@ -69,7 +80,9 @@
 
 				@IBAction func quitAction(_ sender: UIButton) {
 								CommonAlertView.show(content: "确认退出当前账户吗?") {
-
+												Services.logoutStudy().subscribe(onNext: {result in
+																sceneDelegate?.needLogin()
+												}).disposed(by: self.disposeBag)
 								}
 				}
 }
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/MeVC.xib b/DolphinEnglishLearnStudent/Moudle/Me/MeVC.xib
index 76037b8..47ebb3b 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/MeVC.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Me/MeVC.xib
@@ -16,6 +16,9 @@
                 <outlet property="btn_etudyRecord" destination="0pk-gO-3Qh" id="SeS-bo-pn4"/>
                 <outlet property="btn_exchangeRecord" destination="uH5-eT-V9Z" id="8gd-zT-JND"/>
                 <outlet property="btn_share" destination="gtG-mF-MKi" id="ejw-y9-ugq"/>
+                <outlet property="imge_cover" destination="qXF-FL-HEr" id="fG7-3a-cHy"/>
+                <outlet property="label_info" destination="LJb-Ki-p3S" id="88F-Ay-1nv"/>
+                <outlet property="label_name" destination="D0d-O7-Pt2" id="C7j-gd-GwB"/>
                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
             </connections>
         </placeholder>
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.swift b/DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.swift
index c5564b3..add306d 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.swift
@@ -6,6 +6,7 @@
 //
 
 import UIKit
+import RxSwift
 
 class AddressManageTCell: UITableViewCell {
 
@@ -15,7 +16,19 @@
 				@IBOutlet weak var btn_delete: UIButton!
 				@IBOutlet weak var btn_edit: UIButton!
 				@IBOutlet weak var img_more: UIImageView!
-				
+				@IBOutlet weak var label_address: UILabel!
+				@IBOutlet weak var label_addressInfo: UILabel!
+
+				private var disposeBag = DisposeBag()
+
+				var addressModel:AddressModel!{
+								didSet{
+												label_address.text = addressModel.address
+												label_addressInfo.text = addressModel.recipient + "|" + addressModel.recipientPhone
+												isDefault(addressModel.isDefault == 1)
+								}
+				}
+
     override func awakeFromNib() {
         super.awakeFromNib()
 								selectionStyle = .none
@@ -24,6 +37,10 @@
 
 				func isDefault(_ state:Bool){
 								if state{
+
+												let attribute = AttributedStringbuilder.build().add(string:"  默认 ", withFont: .systemFont(ofSize: 14, weight: .medium), withColor: UIColor.white).mutableAttributedString
+												btn_default.setAttributedTitle(attribute, for: .normal)
+
 												btn_default.setTitle(" 默认 ", for: .normal)
 												btn_default.backgroundColor = UIColor(hexStr: "#F7462D")
 												btn_default.setTitleColor(.white, for: .normal)
@@ -37,13 +54,23 @@
 				}
 
 				@IBAction func deleteAction(_ sender: UIButton) {
-								CommonAlertView.show(content:"确认删除所选信息吗?") {
-
+								CommonAlertView.show(content:"确认删除所选信息吗?") {[weak self] () in
+												guard let weakSelf = self else { return }
+												Services.deleteAddress(id: weakSelf.addressModel.id).subscribe(onNext: { _ in
+																NotificationCenter.default.post(name: AddressManage_Refresh_Noti, object: nil)
+												}).disposed(by: weakSelf.disposeBag)
 								}
 				}
+
+				@IBAction func setDefaultAction(_ sender: UIButton) {
+								Services.setDefaultStudy(id: addressModel.id).subscribe(onNext: { _ in
+												NotificationCenter.default.post(name: AddressManage_Refresh_Noti, object: nil)
+								}).disposed(by: disposeBag)
+				}
 				
+
 				@IBAction func editAction(_ sender: UIButton) {
-								let vc = AddressManageHandleVC()
+								let vc = AddressManageHandleVC(addressModel)
 								vc.title = "编辑地址"
 								JQ_currentViewController().jq_push(vc: vc)
 				}
@@ -57,5 +84,9 @@
 												contentView.jq_addCorners(corner: [.bottomLeft,.bottomLeft], radius: 10)
 								}
 
+								if isFist && isLast{
+												contentView.jq_addCorners(corner: .allCorners, radius: 10)
+								}
+
 				}
 }
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.xib b/DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.xib
index 03c61f5..aef8819 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Me/TCell/AddressManageTCell.xib
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
-    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <device id="ipad10_9rounded" orientation="portrait" layout="fullscreen" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
@@ -10,7 +10,7 @@
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="95" id="KGk-i7-Jjw" customClass="AddressManageTCell" customModule="DolphinEnglishLearnManager" customModuleProvider="target">
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="95" id="KGk-i7-Jjw" customClass="AddressManageTCell" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
             <rect key="frame" x="0.0" y="0.0" width="447" height="95"/>
             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
             <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
@@ -27,7 +27,7 @@
                         <nil key="highlightedColor"/>
                     </label>
                     <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ezc-re-P3r">
-                        <rect key="frame" x="375" y="18.666666666666668" width="58" height="17.000000000000004"/>
+                        <rect key="frame" x="375" y="18.5" width="58" height="17"/>
                         <constraints>
                             <constraint firstAttribute="height" constant="17" id="0Kf-PA-7Or"/>
                             <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="42" id="4RT-3H-dH2"/>
@@ -37,9 +37,12 @@
                         <state key="normal" title="设为默认">
                             <color key="titleColor" red="0.25490196079999999" green="0.63529411759999999" blue="0.92156862750000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                         </state>
+                        <connections>
+                            <action selector="setDefaultAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="p3w-8e-C9z"/>
+                        </connections>
                     </button>
                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="-- | --" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="g9x-qe-0Me">
-                        <rect key="frame" x="13.999999999999996" y="42" width="41.666666666666657" height="17"/>
+                        <rect key="frame" x="14" y="42" width="42" height="17"/>
                         <constraints>
                             <constraint firstAttribute="height" constant="17" id="04w-Er-l9A"/>
                         </constraints>
@@ -77,7 +80,7 @@
                         </connections>
                     </button>
                     <imageView hidden="YES" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="icon_more_gray" translatesAutoresizingMaskIntoConstraints="NO" id="Qav-bf-Mlo">
-                        <rect key="frame" x="427" y="42.666666666666664" width="6" height="10"/>
+                        <rect key="frame" x="427" y="42.5" width="6" height="10"/>
                     </imageView>
                 </subviews>
                 <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
@@ -106,6 +109,8 @@
                 <outlet property="btn_delete" destination="a8n-tE-gqa" id="elJ-VF-A4k"/>
                 <outlet property="btn_edit" destination="WFf-ch-GdK" id="Wfz-Oo-mbZ"/>
                 <outlet property="img_more" destination="Qav-bf-Mlo" id="ykH-wg-Brt"/>
+                <outlet property="label_address" destination="Qjx-I2-glv" id="iwX-fL-7LK"/>
+                <outlet property="label_addressInfo" destination="g9x-qe-0Me" id="cZT-hR-szg"/>
             </connections>
             <point key="canvasLocation" x="202.29007633587784" y="49.647887323943664"/>
         </tableViewCell>
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.swift b/DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.swift
index da004ec..6dc7fa9 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.swift
@@ -8,7 +8,16 @@
 import UIKit
 
 class GoodsItemTCell: UITableViewCell {
-
+				
+				@IBOutlet weak var label_state: UILabel!
+				@IBOutlet weak var label_goodsName: UILabel!
+				@IBOutlet weak var label_types: UILabel!
+				@IBOutlet weak var label_goodsNum: UILabel!
+				@IBOutlet weak var label_receiptInfo: UILabel!
+				@IBOutlet weak var label_sendInfo: UILabel!
+				@IBOutlet weak var btn_state: UIButton!
+				@IBOutlet weak var label_coin: UILabel!
+				
 				@IBOutlet weak var view_container: UIView!
 				override func awakeFromNib() {
         super.awakeFromNib()
@@ -17,6 +26,24 @@
 								view_container.jq_addShadows(shadowColor: UIColor(hexStr: "#D9D9D9").withAlphaComponent(0.28), corner: 8, radius: 3, offset: CGSize(width: 0, height: 2), opacity: 1)
     }
 
+				func setModel(_ model:ExchangeRecordModel){
+								label_goodsNum.text = "商品数量:\(model.count)"
+								label_coin.text = "\(model.integral)积分"
+
+								var items_consignee = Array<String>()
+								items_consignee.append(model.consigneeName)
+								items_consignee.append(model.consigneePhone)
+								items_consignee.append(model.consigneeAddress)
+								label_receiptInfo.text = "收货信息:" + items_consignee.joined(separator: "|")
+
+								var items_express = Array<String>()
+								items_express.append(model.express)
+								items_express.append(model.expressNumber)
+
+								label_sendInfo.isHidden = items_express.filter({!$0.isEmpty}).count == 0
+								label_sendInfo.text = "发货信息:" + items_express.joined(separator: "|")
+				}
+
 				@IBAction func handleAction(_ sender: UIButton) {
 								let vc = AddressManageVC(type: .choose)
 								vc.title = "修改地址"
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.xib b/DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.xib
index ffc3dcf..938ac98 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Me/TCell/GoodsItemTCell.xib
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
-    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <device id="ipad10_9rounded" orientation="portrait" layout="fullscreen" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
@@ -10,7 +10,7 @@
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="_GoodsItemTCell" rowHeight="344" id="KGk-i7-Jjw" customClass="GoodsItemTCell" customModule="DolphinEnglishLearnManager" customModuleProvider="target">
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="_GoodsItemTCell" rowHeight="344" id="KGk-i7-Jjw" customClass="GoodsItemTCell" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
             <rect key="frame" x="0.0" y="0.0" width="532" height="344"/>
             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
             <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
@@ -21,13 +21,13 @@
                         <rect key="frame" x="0.0" y="6" width="532" height="332"/>
                         <subviews>
                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9oA-7x-in6">
-                                <rect key="frame" x="8" y="19" width="41.333333333333336" height="20.333333333333329"/>
+                                <rect key="frame" x="8" y="19" width="41.5" height="20.5"/>
                                 <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                 <nil key="textColor"/>
                                 <nil key="highlightedColor"/>
                             </label>
                             <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="HZS-Oe-5LR">
-                                <rect key="frame" x="8" y="52.333333333333343" width="148" height="148"/>
+                                <rect key="frame" x="8" y="52.5" width="148" height="148"/>
                                 <constraints>
                                     <constraint firstAttribute="width" constant="148" id="D3I-iy-k6w"/>
                                     <constraint firstAttribute="width" secondItem="HZS-Oe-5LR" secondAttribute="height" multiplier="1:1" id="YQJ-eG-71N"/>
@@ -40,25 +40,25 @@
                                 </userDefinedRuntimeAttributes>
                             </imageView>
                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UdI-oe-WSO">
-                                <rect key="frame" x="173" y="52.333333333333336" width="234" height="19.333333333333336"/>
+                                <rect key="frame" x="173" y="52.5" width="234" height="19.5"/>
                                 <fontDescription key="fontDescription" type="system" pointSize="16"/>
                                 <color key="textColor" red="0.082352941176470587" green="0.086274509803921567" blue="0.094117647058823528" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0积分" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="nMG-SO-H2Z">
-                                <rect key="frame" x="481" y="52.666666666666664" width="40" height="18.666666666666664"/>
+                                <rect key="frame" x="481" y="53" width="40" height="19"/>
                                 <fontDescription key="fontDescription" name="DINAlternate-Bold" family="DIN Alternate" pointSize="16"/>
                                 <color key="textColor" red="0.96862745100000003" green="0.27450980390000002" blue="0.1764705882" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                 <nil key="highlightedColor"/>
                             </label>
                             <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="viA-yT-ZWk">
-                                <rect key="frame" x="173" y="71.666666666666671" width="359" height="17"/>
+                                <rect key="frame" x="173" y="72" width="359" height="17"/>
                                 <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                 <nil key="textColor"/>
                                 <nil key="highlightedColor"/>
                             </label>
                             <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" spacing="5" translatesAutoresizingMaskIntoConstraints="NO" id="vd5-iK-Ujb">
-                                <rect key="frame" x="173" y="95.666666666666686" width="303" height="70"/>
+                                <rect key="frame" x="173" y="96" width="303" height="70"/>
                                 <subviews>
                                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="商品数量:-" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="PlF-D7-xZD">
                                         <rect key="frame" x="0.0" y="0.0" width="303" height="20"/>
@@ -79,7 +79,7 @@
                                         <nil key="highlightedColor"/>
                                     </label>
                                     <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="发货信息:-" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="cSS-lo-Yba">
-                                        <rect key="frame" x="0.0" y="49.999999999999986" width="303" height="20"/>
+                                        <rect key="frame" x="0.0" y="50" width="303" height="20"/>
                                         <constraints>
                                             <constraint firstAttribute="height" constant="20" id="mDC-DF-Wc3"/>
                                         </constraints>
@@ -141,6 +141,14 @@
             </tableViewCellContentView>
             <viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
             <connections>
+                <outlet property="btn_state" destination="xwt-lH-fyW" id="YNc-qk-0gB"/>
+                <outlet property="label_coin" destination="nMG-SO-H2Z" id="weP-sJ-QLG"/>
+                <outlet property="label_goodsName" destination="UdI-oe-WSO" id="o9d-iH-BCJ"/>
+                <outlet property="label_goodsNum" destination="PlF-D7-xZD" id="1mj-HF-LGA"/>
+                <outlet property="label_receiptInfo" destination="qnF-SM-ngM" id="me5-fe-eW2"/>
+                <outlet property="label_sendInfo" destination="cSS-lo-Yba" id="4fa-fc-f69"/>
+                <outlet property="label_state" destination="9oA-7x-in6" id="lBa-OB-S8W"/>
+                <outlet property="label_types" destination="viA-yT-ZWk" id="3dU-h2-97f"/>
                 <outlet property="view_container" destination="EWl-m5-3O9" id="vyU-l1-0CY"/>
             </connections>
             <point key="canvasLocation" x="259.5419847328244" y="126.05633802816902"/>
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.swift b/DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.swift
index c834219..545162a 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.swift
@@ -9,6 +9,26 @@
 
 class Home_1_TCell: UITableViewCell {
 
+				@IBOutlet weak var label_1: UILabel!
+				@IBOutlet weak var label_2: UILabel!
+				@IBOutlet weak var label_3: UILabel!
+				@IBOutlet weak var label_4: UILabel!
+				
+				var integralModel:IntegralModel!{
+								didSet{
+												label_1.text = integralModel.createTime
+												label_2.text = integralModel.integral
+												label_3.text = integralModel.method
+												label_4.text = integralModel.type
+								}
+				}
+
+				var studyGamesRecordModel:StudyGamesRecordModel!{
+								didSet{
+
+								}
+				}
+
     override func awakeFromNib() {
         super.awakeFromNib()
 								selectionStyle = .none
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.xib b/DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.xib
index fdf2c39..a28f030 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Me/TCell/Home_1_TCell.xib
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="32700.99.1234" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
-    <device id="retina6_12" orientation="portrait" appearance="light"/>
+    <device id="ipad10_9rounded" orientation="portrait" layout="fullscreen" appearance="light"/>
     <dependencies>
         <deployment identifier="iOS"/>
         <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
@@ -9,7 +9,7 @@
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
         <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
-        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="_Home_1_TCell" id="KGk-i7-Jjw" customClass="Home_1_TCell" customModule="DolphinEnglishLearnManager" customModuleProvider="target">
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="_Home_1_TCell" id="KGk-i7-Jjw" customClass="Home_1_TCell" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
             <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
             <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
@@ -53,6 +53,12 @@
                     <constraint firstItem="xga-Br-Izz" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="dHd-ao-jYA"/>
                 </constraints>
             </tableViewCellContentView>
+            <connections>
+                <outlet property="label_1" destination="LLg-mN-hnD" id="7UE-le-ZJZ"/>
+                <outlet property="label_2" destination="bXA-iA-Sgc" id="4He-VH-alj"/>
+                <outlet property="label_3" destination="tft-ra-5If" id="CLY-lE-hEm"/>
+                <outlet property="label_4" destination="UQ2-uJ-GO9" id="nNZ-Gp-UJ9"/>
+            </connections>
             <point key="canvasLocation" x="139" y="21"/>
         </tableViewCell>
     </objects>
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.swift b/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.swift
index 5d7ced4..2f28e14 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.swift
@@ -6,17 +6,119 @@
 //
 
 import UIKit
+import QMUIKit
+import RxRelay
+
+class AddressManageHandleViewModel{
+				var userName = BehaviorRelay<String?>(value: nil)
+				var phone = BehaviorRelay<String?>(value: nil)
+				var provinceModel = BehaviorRelay<AddressTreeModel?>(value: nil)
+				var cityModel = BehaviorRelay<AddressTreeModel?>(value: nil)
+				var countryModel = BehaviorRelay<AddressTreeModel?>(value: nil)
+				var detailAddress = BehaviorRelay<String?>(value: nil)
+				var isDefault = BehaviorRelay<Bool>(value: false)
+}
 
 class AddressManageHandleVC: BaseVC {
+
+				@IBOutlet weak var tf_name: UITextField!
+				@IBOutlet weak var tf_phone: QMUITextField!
+				@IBOutlet weak var tf_address: QMUITextField!
+				@IBOutlet weak var tf_addressContent: QMUITextField!
+				@IBOutlet weak var btn_isDefault: UIButton!
+
+				let viewModel = AddressManageHandleViewModel()
+				private var updateModel:AddressModel?
 
 				@IBOutlet weak var view_container: UIView!
 				override func viewDidLoad() {
         super.viewDidLoad()
 
+								if let updateModel{
+												tf_name.text = updateModel.recipient
+												tf_phone.text = updateModel.recipientPhone
+												tf_address.text = updateModel.province + updateModel.city
+												tf_addressContent.text = updateModel.address
+												btn_isDefault.isSelected = updateModel.isDefault == 1
+
+												viewModel.userName.accept(updateModel.recipient)
+												viewModel.phone.accept(updateModel.recipientPhone)
+												viewModel.detailAddress.accept(updateModel.address)
+
+												viewModel.provinceModel.accept(AddressTreeModel(id: 0, name: updateModel.province, code: updateModel.provinceCode, parentId: 0, children: nil))
+												viewModel.cityModel.accept(AddressTreeModel(id: 0, name: updateModel.city, code: updateModel.cityCode, parentId: 0, children: nil))
+								}
     }
 
+				init(_ updateModel:AddressModel? = nil) {
+								super.init(nibName: nil, bundle: nil)
+								self.updateModel = updateModel
+				}
+				
+				required init?(coder: NSCoder) {
+								fatalError("init(coder:) has not been implemented")
+				}
+				
 				override func setUI() {
 								super.setUI()
 								view_container.jq_addShadows(shadowColor: UIColor(hexStr: "#D9D9D9").withAlphaComponent(0.28), corner: 8, radius: 20, offset: CGSize(width: 0, height: 2), opacity: 1)
+								tf_address.delegate = self
+				}
+
+				override func setRx() {
+								tf_name.rx.text.bind(to: viewModel.userName).disposed(by: disposeBag)
+								tf_phone.rx.text.bind(to: viewModel.phone).disposed(by: disposeBag)
+								tf_addressContent.rx.text.bind(to: viewModel.detailAddress).disposed(by: disposeBag)
+				}
+
+				@IBAction func chooseDefaultAction(_ sender: UIButton) {
+								sender.isSelected = !sender.isSelected
+				}
+				
+				@IBAction func saveAction(_ sender: UIButton) {
+								guard !(viewModel.userName.value?.isEmpty ?? true) else {
+												alert(msg: "请输入收件人姓名");return
+								}
+
+								guard !(viewModel.phone.value?.isEmpty ?? true) else {
+												alert(msg: "请输入收件人电话");return
+								}
+
+								guard viewModel.phone.value!.jq_isPhone else {
+												alert(msg: "请输入正确的手机号码");return
+								}
+
+								guard viewModel.cityModel.value != nil else {
+												alert(msg: "请选择所在城市");return
+								}
+
+								guard !(viewModel.detailAddress.value?.isEmpty ?? true) else {
+												alert(msg: "请输入详细地址");return
+								}
+
+								Services.addressSaveOrUpdate(id: updateModel?.id, province: viewModel.provinceModel.value, city: viewModel.cityModel.value, country: nil, userName: viewModel.userName.value, userPhone: viewModel.phone.value, isDefault: btn_isDefault.isSelected, detailAddress: viewModel.detailAddress.value ?? "").subscribe(onNext: {_ in
+												if self.updateModel != nil{
+																alertSuccess(msg: "编辑成功")
+												}else{
+																alertSuccess(msg: "添加成功")
+												}
+
+												self.navigationController?.popViewController()
+												NotificationCenter.default.post(name: AddressManage_Refresh_Noti, object: nil)
+								}).disposed(by: disposeBag)
+				}
+}
+
+extension AddressManageHandleVC:QMUITextFieldDelegate{
+
+				func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
+								CityAddressPickerView.show(title: "选择省市区") {[weak self] province, city, country in
+												self?.viewModel.provinceModel.accept(province)
+												self?.viewModel.cityModel.accept(city)
+												self?.viewModel.countryModel.accept(country)
+
+												textField.text = "\(province?.name ?? "") \(city?.name ?? "") \(country?.name ?? "")"
+								}
+								return false
 				}
 }
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.xib b/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.xib
index 7b8ca0f..b97b7a9 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageHandleVC.xib
@@ -11,6 +11,11 @@
     <objects>
         <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AddressManageHandleVC" customModule="DolphinEnglishLearnStudent" customModuleProvider="target">
             <connections>
+                <outlet property="btn_isDefault" destination="X5q-Za-IDi" id="6lr-qr-5nr"/>
+                <outlet property="tf_address" destination="FIR-Ti-oMo" id="XyJ-kk-oGH"/>
+                <outlet property="tf_addressContent" destination="9Rg-uR-zdR" id="sxn-jk-kYJ"/>
+                <outlet property="tf_name" destination="oWU-h5-9OT" id="9Gb-Hg-ka1"/>
+                <outlet property="tf_phone" destination="fLZ-09-hXt" id="YZs-at-Zeo"/>
                 <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
                 <outlet property="view_container" destination="qgb-Bj-4P0" id="eaY-Jn-MsE"/>
             </connections>
@@ -151,7 +156,7 @@
                                 <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="eNK-zb-eqQ">
                                     <rect key="frame" x="0.0" y="162" width="888" height="54"/>
                                     <subviews>
-                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="所在城市" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uwd-8E-QFK">
+                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="详细地址" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uwd-8E-QFK">
                                             <rect key="frame" x="14" y="18.5" width="57.5" height="17"/>
                                             <fontDescription key="fontDescription" type="system" weight="medium" pointSize="14"/>
                                             <nil key="textColor"/>
@@ -203,6 +208,9 @@
                                 <color key="titleColor" red="0.0" green="0.0" blue="0.0" alpha="0.80000000000000004" colorSpace="custom" customColorSpace="sRGB"/>
                             </state>
                             <state key="selected" title="设为默认" image="btn_choose"/>
+                            <connections>
+                                <action selector="chooseDefaultAction:" destination="-1" eventType="touchUpInside" id="6aM-GW-eHa"/>
+                            </connections>
                         </button>
                     </subviews>
                     <color key="backgroundColor" systemColor="systemBackgroundColor"/>
@@ -232,6 +240,9 @@
                             <real key="value" value="8"/>
                         </userDefinedRuntimeAttribute>
                     </userDefinedRuntimeAttributes>
+                    <connections>
+                        <action selector="saveAction:" destination="-1" eventType="touchUpInside" id="Ml0-tI-QPP"/>
+                    </connections>
                 </button>
             </subviews>
             <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageVC.swift b/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageVC.swift
index 40c70bd..b5bb5d2 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Me/VC/AddressManageVC.swift
@@ -6,6 +6,15 @@
 //
 
 import UIKit
+import RxSwift
+
+let AddressManage_Refresh_Noti = Notification.Name.init("AddressManage_Refresh_Noti")
+
+class AddressManageViewModel:RefreshModel<AddressModel>{
+				override func api() -> (Observable<BaseResponse<[AddressModel]>>)? {
+								Services.addressList()
+				}
+}
 
 class AddressManageVC: BaseVC {
 
@@ -16,6 +25,7 @@
 
 				private var tableView:UITableView!
 				private var addressManageType:AddressManageType!
+				private var viewModel = AddressManageViewModel()
 
 				required init(type:AddressManageType) {
 								super.init(nibName: nil, bundle: nil)
@@ -28,6 +38,9 @@
 				
     override func viewDidLoad() {
         super.viewDidLoad()
+
+								viewModel.configure(tableView)
+								viewModel.beginRefresh()
     }
 
 
@@ -73,6 +86,12 @@
 								}
 				}
 
+				override func setRx() {
+								NotificationCenter.default.rx.notification(AddressManage_Refresh_Noti).take(until: self.rx.deallocated).subscribe(onNext: {[weak self] _ in
+												self?.viewModel.beginRefresh()
+								}).disposed(by: disposeBag)
+				}
+
 				@objc func handleAction(){
 								let vc = AddressManageHandleVC()
 								vc.title = "地址管理"
@@ -86,10 +105,11 @@
 
 extension AddressManageVC:UITableViewDataSource{
 				func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+								 let model = viewModel.dataSource.value[indexPath.row]
 								 let cell = tableView.dequeueReusableCell(withIdentifier: "_AddressManageTCell") as! AddressManageTCell
+								cell.addressModel = model
 								cell.isFist = indexPath.row == 0
-								cell.isLast = indexPath.row == 9
-								cell.isDefault(indexPath.row == 0)
+								cell.isLast = indexPath.row == viewModel.dataSource.value.count - 1
 
 								cell.btn_edit.isHidden = addressManageType == .choose
 								cell.btn_delete.isHidden = addressManageType == .choose
@@ -100,7 +120,7 @@
 				}
 
 				func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-								return 10
+								return viewModel.dataSource.value.count
 				}
 
 				func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.swift b/DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.swift
index e38ece0..6db38ea 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.swift
@@ -7,9 +7,15 @@
 
 import UIKit
 import RxRelay
+import JQTools
+import RxSwift
 
-class CoinRecordHistoryViewModel{
+class CoinRecordHistoryViewModel:RefreshInnerModel<IntegralModel>{
 				var selectDate = BehaviorRelay<Date?>(value:nil)
+
+				override func api() -> (Observable<BaseResponse<BaseResponseList<IntegralModel>>>)? {
+								return Services.integralDetail(pageNum: page, time: selectDate.value?.jq_format("yyyy-MM"))
+				}
 }
 
 class CoinRecordHistoryVC: BaseVC {
@@ -23,6 +29,12 @@
 				override func viewDidLoad() {
 								super.viewDidLoad()
 
+								viewModel.configure(tableView,needMore: true)
+								viewModel.beginRefresh()
+
+								Services.getIntegral().subscribe(onNext: {reault in
+												self.label_coin.text = "\(reault.data ?? 0)"
+								}).disposed(by: disposeBag)
 				}
 
 				override func setUI() {
@@ -43,13 +55,19 @@
 								}).disposed(by: disposeBag)
 				}
 
-
 				@IBAction func chooseDateTimeAction(_ sender: UIButton) {
 								let year = viewModel.selectDate.value?.jq_nowYear() ?? Date().jq_nowYear()
 								let month = viewModel.selectDate.value?.jq_nowMonth() ?? Date().jq_nowMonth()
 								BitrhdayPickerView.show(title: "查询时间", type: .YM, defaultYear: year, defaultMonth: month, defaultDay: 0, minYear: 0) {[weak self] date in
 												self?.viewModel.selectDate.accept(date)
+												self?.viewModel.beginRefresh()
 								}
+				}
+
+				@IBAction func resetAction(_ sender: UIButton) {
+								viewModel.selectDate.accept(nil)
+								btn_selectDate.setTitle("请选择", for: .normal)
+								viewModel.beginRefresh()
 				}
 }
 
@@ -67,11 +85,13 @@
 												cell.contentView.backgroundColor = .white
 								}
 
+								let m = viewModel.dataSource.value?.records[indexPath.row]
+								cell.integralModel = m
 								return cell
 				}
 
 				func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-								return 5
+								return viewModel.dataSource.value?.records.count ?? 0
 				}
 
 				func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.xib b/DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.xib
index 1f5cb6f..48f0fe3 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.xib
+++ b/DolphinEnglishLearnStudent/Moudle/Me/VC/CoinRecordHistoryVC.xib
@@ -74,6 +74,9 @@
                             </constraints>
                             <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                             <state key="normal" image="btn_refresh"/>
+                            <connections>
+                                <action selector="resetAction:" destination="-1" eventType="touchUpInside" id="UoC-8u-vu0"/>
+                            </connections>
                         </button>
                     </subviews>
                     <constraints>
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/VC/ExchangeRecordHistoryVC.swift b/DolphinEnglishLearnStudent/Moudle/Me/VC/ExchangeRecordHistoryVC.swift
index 583e8ac..1a29931 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/VC/ExchangeRecordHistoryVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Me/VC/ExchangeRecordHistoryVC.swift
@@ -6,14 +6,25 @@
 //
 
 import UIKit
+import RxSwift
+
+class ExchangeRecordViewModel:RefreshModel<ExchangeRecordModel>{
+				override func api() -> (Observable<BaseResponse<[ExchangeRecordModel]>>)? {
+								return Services.exchangeRecord()
+				}
+}
 
 class ExchangeRecordHistoryVC: BaseVC {
 
+
+				private  let viewModel = ExchangeRecordViewModel()
 				private var tableView:UITableView!
 
     override func viewDidLoad() {
         super.viewDidLoad()
 
+								viewModel.configure(tableView)
+								viewModel.beginRefresh()
     }
 
 				override func setUI() {
@@ -42,11 +53,12 @@
 extension ExchangeRecordHistoryVC:UITableViewDataSource{
 				func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 								let cell = tableView.dequeueReusableCell(withIdentifier: "_GoodsItemTCell") as! GoodsItemTCell
+								cell.setModel(viewModel.dataSource.value[indexPath.row])
 								return cell
 				}
 
 				func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-								return 10
+								return viewModel.dataSource.value.count
 				}
 
 				func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
diff --git a/DolphinEnglishLearnStudent/Moudle/Me/VC/StudyVC.swift b/DolphinEnglishLearnStudent/Moudle/Me/VC/StudyVC.swift
index a4daf6e..ed38a0c 100644
--- a/DolphinEnglishLearnStudent/Moudle/Me/VC/StudyVC.swift
+++ b/DolphinEnglishLearnStudent/Moudle/Me/VC/StudyVC.swift
@@ -11,9 +11,21 @@
 				@IBOutlet weak var view_menu: UIView!
 				@IBOutlet weak var tableView: UITableView!
 				
+				private var gamesRecordModel:StudyGamesModel?{
+								didSet{
+												self.tableView.reloadData()
+								}
+				}
+
+
     override func viewDidLoad() {
         super.viewDidLoad()
 
+								Services.studyGamesRecord().subscribe(onNext: {result in
+												if let m = result.data{
+																self.gamesRecordModel = m
+												}
+								}).disposed(by: disposeBag)
     }
 
 				override func setUI() {
@@ -44,12 +56,16 @@
 								}else{
 												cell.contentView.backgroundColor = .white
 								}
+								if let m = gamesRecordModel?.gameRecordList[indexPath.row]{
+												cell.studyGamesRecordModel = m
+								}
+
 
 								return cell
 				}
 
 				func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
-								return 5
+								return gamesRecordModel?.gameRecordList.count ?? 0
 				}
 
 				func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
diff --git a/DolphinEnglishLearnStudent/Other/CommonWebVC.swift b/DolphinEnglishLearnStudent/Other/CommonWebVC.swift
index 2bc0e18..e2d4f11 100644
--- a/DolphinEnglishLearnStudent/Other/CommonWebVC.swift
+++ b/DolphinEnglishLearnStudent/Other/CommonWebVC.swift
@@ -10,16 +10,17 @@
 
 class CommonWebVC: BaseVC {
 
-				enum CommonWebType{
-								case logoff
-								case userAgreement
-								case privacyAgreement
-								case userGuide
-				}
+				private var type:AgreementType!
 
-				private var type:CommonWebType!
+				private lazy var webView:WKWebView = {
+								let webView = WKWebView()
+								webView.backgroundColor = .clear
+								webView.scrollView.backgroundColor = .clear
+								webView.isOpaque = false
+								return webView
+				}()
 
-				init(type:CommonWebType) {
+				init(type:AgreementType) {
 								super.init(nibName: nil, bundle: nil)
 								self.type = type
 				}
@@ -36,8 +37,14 @@
 				override func setUI() {
 								super.setUI()
 
+								view.addSubview(webView)
+								webView.snp.makeConstraints { make in
+												make.top.equalTo(self.view.safeAreaLayoutGuide.snp.top)
+												make.left.right.equalToSuperview()
+												make.bottom.equalTo(self.view.safeAreaLayoutGuide.snp.bottom)
+								}
 
-								if type == .logoff{
+								if type == .logout{
 												let completeBtn = UIButton(type: .custom)
 												completeBtn.jq_cornerRadius = 8
 												completeBtn.addTarget(self, action: #selector(handleAction), for: .touchUpInside)
@@ -76,6 +83,13 @@
 												});
 												timer.resume()
 								}
+
+
+								Services.getAgreement(type: type).subscribe(onNext: {[weak self]content in
+												if let content = content.data{
+																self?.webView.loadHTMLString(content.jq_wrapHtml(), baseURL: nil)
+												}
+								}).disposed(by: disposeBag)
 				}
 
 				@objc func handleAction(sender:UIButton){
diff --git a/DolphinEnglishLearnStudent/Other/UIView/CityAddressPickerView.swift b/DolphinEnglishLearnStudent/Other/UIView/CityAddressPickerView.swift
new file mode 100644
index 0000000..4b78330
--- /dev/null
+++ b/DolphinEnglishLearnStudent/Other/UIView/CityAddressPickerView.swift
@@ -0,0 +1,248 @@
+//
+//  CityAddressPickerView.swift
+//  DolphinEnglishLearnStudent
+//
+//  Created by 无故事王国 on 2024/6/3.
+//
+
+import UIKit
+import RxSwift
+
+class CityAddressPickerView: UIView {
+
+				private var disposeBag = DisposeBag()
+				private var items = [AddressTreeModel]()
+				private var clouse:((AddressTreeModel?,AddressTreeModel?,AddressTreeModel?)->Void)!
+
+				private var view_content:UIView = {
+								let v = UIView()
+								v.backgroundColor = .white
+								return v
+				}()
+
+				private var label_title:UILabel = {
+								let label = UILabel()
+								label.font = .systemFont(ofSize: 18, weight: .medium)
+								label.textColor = .black.withAlphaComponent(0.8)
+								return label
+				}()
+
+				private var btn_close:UIButton = {
+								let btn = UIButton(type: .custom)
+								btn.setImage(UIImage(named: "btn_close_circle"), for: .normal)
+								return btn
+				}()
+
+				private var btn_complete:UIButton = {
+								let btn = UIButton(type: .custom)
+								btn.setTitle("确认", for: .normal)
+								btn.titleLabel?.font = UIFont.systemFont(ofSize: 14, weight: .medium)
+								btn.setTitleColor(.white, for: .normal)
+								btn.backgroundColor = Config.ThemeColor
+								btn.jq_cornerRadius = 8
+								return btn
+				}()
+
+
+				private var picker:UIPickerView = {
+								let pickerView = UIPickerView()
+								return pickerView
+				}()
+
+
+				override init(frame: CGRect) {
+								super.init(frame: frame)
+								backgroundColor = UIColor.black.withAlphaComponent(0)
+								addSubview(view_content)
+								view_content.snp.makeConstraints { make in
+												make.left.right.equalToSuperview()
+												make.bottom.equalToSuperview().offset(JQ_ScreenW * 0.3278)
+												make.height.equalTo(JQ_ScreenW * 0.3278)
+								}
+
+
+								view_content.addSubview(btn_close)
+								btn_close.addTarget(self, action: #selector(closeAction), for: .touchUpInside)
+								btn_close.snp.makeConstraints { make in
+												make.top.equalTo(10)
+												make.right.equalTo(-11)
+												make.width.height.equalTo(23)
+								}
+
+								view_content.addSubview(label_title)
+								label_title.snp.makeConstraints { make in
+												make.top.equalTo(30)
+												make.centerX.equalToSuperview()
+												make.height.equalTo(18)
+								}
+
+								layoutIfNeeded()
+				}
+
+				private func setUI(){
+								var items = Array<String>()
+								items.append("省")
+								items.append("市")
+								items.append("区")
+
+								let stackView =  UIStackView()
+								stackView.axis = .horizontal
+								stackView.distribution = .fillEqually
+								stackView.spacing = 133
+								view_content.addSubview(stackView)
+								stackView.snp.makeConstraints { make in
+												make.top.equalTo(label_title.snp.bottom).offset(27)
+												make.height.equalTo(25)
+												make.centerX.equalToSuperview()
+								}
+
+								for (_,v) in items.enumerated(){
+												let label	 = UILabel()
+												label.text = v
+												label.font = UIFont.systemFont(ofSize: 18, weight: .medium)
+												label.textColor = .black.withAlphaComponent(0.8)
+												label.textAlignment = .center
+												stackView.addArrangedSubview(label)
+								}
+
+								view_content.addSubview(btn_complete)
+								btn_complete.snp.makeConstraints { make in
+												make.bottom.equalToSuperview().offset(-UIDevice.jq_safeEdges.bottom)
+												make.centerX.equalToSuperview()
+												make.width.equalTo(JQ_ScreenW * 0.1487)
+												make.height.equalTo(47)
+								}
+
+								view_content.addSubview(picker)
+								picker.delegate = self
+								picker.dataSource = self
+								picker.snp.makeConstraints { make in
+												make.top.equalTo(label_title.snp.bottom).offset(50)
+												make.bottom.equalTo(btn_complete.snp.top)
+												make.centerX.equalToSuperview()
+												make.width.equalTo(500)
+								}
+
+								btn_complete.addTarget(self, action: #selector(completeAction), for: .touchUpInside)
+				}
+
+				required init?(coder: NSCoder) {
+								fatalError("init(coder:) has not been implemented")
+				}
+
+				static func show(title:String,clouse:@escaping (AddressTreeModel?,AddressTreeModel?,AddressTreeModel?)->Void){
+								let pickerView = CityAddressPickerView(frame: sceneDelegate?.window?.frame ?? .zero)
+								pickerView.clouse = clouse
+								sceneDelegate?.window?.addSubview(pickerView)
+								pickerView.setUI()
+
+								UIView.animate(withDuration: 0.35) {
+												pickerView.backgroundColor = UIColor.black.withAlphaComponent(0.7)
+												pickerView.view_content.snp.updateConstraints { make in
+																make.bottom.equalToSuperview()
+												}
+												pickerView.layoutIfNeeded()
+								}completion: { _ in
+												Services.addressTree().subscribe(onNext: {data in
+																pickerView.items = data.data ?? []
+																pickerView.picker.reloadAllComponents()
+												}).disposed(by: pickerView.disposeBag)
+								}
+				}
+
+				@objc func closeAction(){
+								UIView.animate(withDuration: 0.35) {
+												self.backgroundColor = UIColor.black.withAlphaComponent(0)
+												self.view_content.snp.updateConstraints { make in
+																make.bottom.equalToSuperview().offset(JQ_ScreenW * 0.3278)
+												}
+												self.layoutIfNeeded()
+								}completion: { _ in
+												self.removeFromSuperview()
+								}
+				}
+
+				@objc func completeAction(){
+
+								let provinceIndex = picker.selectedRow(inComponent: 0)
+								let provinceModel = items[provinceIndex]
+								let cityModel = items[provinceIndex].children?[picker.selectedRow(inComponent: 1)]
+								let countryModel = items[provinceIndex].children?[picker.selectedRow(inComponent: 1)].children?[picker.selectedRow(inComponent: 2)]
+								clouse(provinceModel,cityModel,countryModel)
+								closeAction()
+				}
+}
+
+extension CityAddressPickerView:UIPickerViewDelegate & UIPickerViewDataSource{
+				func numberOfComponents(in pickerView: UIPickerView) -> Int {
+								if items.count > 0{
+												return 3
+								}
+								return 0
+
+				}
+
+				func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
+								return 40
+				}
+
+				func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
+
+								var resultLabel:UILabel?
+								if let label = view as? UILabel{
+												resultLabel = label
+								}else{
+												resultLabel = UILabel()
+												resultLabel!.font = UIFont.systemFont(ofSize: 18, weight: .semibold)
+												resultLabel!.textColor = UIColor(hexStr: "#3C3C3C")
+												resultLabel!.textAlignment = .center
+								}
+
+								if component == 0{
+												resultLabel!.text = items[row].name
+								}
+
+								if component == 1{
+												let v = items[pickerView.selectedRow(inComponent: 0)]
+												resultLabel!.text = v.children?[row].name ?? ""
+								}
+
+								if component == 2{
+												let v = items[pickerView.selectedRow(inComponent: 0)]
+												let v1 = v.children?[pickerView.selectedRow(inComponent: 1)]
+												resultLabel!.text = v1?.children?[row].name ?? ""
+								}
+
+								return resultLabel!
+				}
+
+				func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
+								if component == 0 {
+												return items.count
+								}
+
+								if component == 1{
+												let index = pickerView.selectedRow(inComponent: 0)
+												return items[index].children?.count ?? 0
+								}
+
+								if component == 2{
+												let indexI = pickerView.selectedRow(inComponent: 0)
+												let indexJ = pickerView.selectedRow(inComponent: 1)
+												return items[indexI].children?[indexJ].children?.count ?? 0
+								}
+
+								return 0
+				}
+
+				func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
+								if component == 0{
+												pickerView.reloadComponent(1)
+												pickerView.reloadComponent(2)
+								}
+
+								if component == 1{
+												pickerView.reloadComponent(2)
+								}
+				}
+}
diff --git a/DolphinEnglishLearnStudent/Other/UIView/CommonBannerView.swift b/DolphinEnglishLearnStudent/Other/UIView/CommonBannerView.swift
new file mode 100644
index 0000000..b7117d0
--- /dev/null
+++ b/DolphinEnglishLearnStudent/Other/UIView/CommonBannerView.swift
@@ -0,0 +1,208 @@
+//
+//  CommonBannerView.swift
+//  WanPai
+//
+//  Created by 无故事王国 on 2023/6/30.
+//
+
+import UIKit
+import SDWebImage
+struct CommonBannerModel {
+				var index = 0 //自定义索引
+				var id:Int? //ID
+				var name:String? //名称
+				var resource:String? //数据源:URL等
+				var mediaType:CommonBannerView.MediaType?
+}
+
+class CommonBannerView: UIView, UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
+
+				enum MediaType {
+								case videoUrl,imageUrl,imageLocal,videoLocal
+				}
+
+				private lazy var collectionView:UICollectionView = {
+								var layout = UICollectionViewFlowLayout()
+								layout.minimumLineSpacing = 0
+								layout.minimumInteritemSpacing = 0
+								layout.scrollDirection = .horizontal
+								layout.sectionInset = .zero
+								layout.headerReferenceSize = .zero
+								layout.footerReferenceSize = .zero
+								layout.itemSize = CGSize(width: self.width, height: self.height)
+								let collectionView = UICollectionView(frame:CGRect(x: 0, y: 0, width: self.width, height: self.height), collectionViewLayout: layout)
+								collectionView.delegate = self
+								collectionView.dataSource = self
+								collectionView.isPagingEnabled = true
+								collectionView.showsHorizontalScrollIndicator = false
+								collectionView.register(CommonBannerViewCell.self, forCellWithReuseIdentifier: "BannerView")
+								collectionView.decelerationRate = .normal
+								collectionView.contentInsetAdjustmentBehavior = .never
+								collectionView.backgroundColor = .white
+								collectionView.bounces = false
+								return collectionView
+				}()
+
+				private lazy var pageControl:UIPageControl = {
+								let control = UIPageControl()
+								control.currentPageIndicatorTintColor = .white
+								control.pageIndicatorTintColor = .gray.withAlphaComponent(0.6)
+								return control
+				}()
+
+				private var timer:Timer?
+
+				private var items = [CommonBannerModel]()
+				private var selectClouse:((CommonBannerModel)->Void)?
+				private var autoRoll:Bool = true
+				private var currentPage:Int = 0
+				private var timeInterval:Int = 5
+
+				override func awakeFromNib() {
+								super.awakeFromNib()
+								setUI()
+				}
+
+				public func setItems(items:[CommonBannerModel],autoRoll:Bool = true,selectClouse:((CommonBannerModel)->Void)? = nil){
+
+								self.items = items
+								if items.count > 1{
+												self.items.append(items.first!)
+								}
+								self.autoRoll = autoRoll
+								self.selectClouse = selectClouse
+								if items.count <= 1{self.autoRoll = false}
+
+								setUI()
+								collectionView.reloadData()
+
+								if self.autoRoll{
+												DispatchQueue.main.asyncAfter(deadline: .now()+5) {
+																self.startTimer()
+												}
+								}
+				}
+
+				private func setUI(){
+								addSubview(collectionView)
+								collectionView.snp.makeConstraints { make in
+												make.edges.equalToSuperview()
+								}
+
+								if items.count > 1{
+												pageControl.numberOfPages = items.count - 1
+
+												addSubview(pageControl)
+												pageControl.snp.makeConstraints { make in
+																make.centerX.equalToSuperview()
+																make.bottom.equalToSuperview().offset(-10)
+																make.height.equalTo(8)
+												}
+								}
+				}
+
+				private func startTimer(){
+								timer = Timer(timeInterval: TimeInterval(timeInterval), repeats: true, block: {[weak self] t in
+												guard let weakSelf = self else { return }
+
+												var page = weakSelf.collectionView.contentOffset.x / weakSelf.collectionView.width
+												weakSelf.currentPage = Int(page + 1)
+
+												if weakSelf.currentPage >= weakSelf.pageControl.numberOfPages{
+																weakSelf.currentPage = 0
+																weakSelf.collectionView.setContentOffset(.zero, animated: false)
+																weakSelf.pageControl.currentPage = 0
+												}
+												weakSelf.collectionView.setContentOffset(CGPoint(x: weakSelf.currentPage * Int(weakSelf.width), y: 0), animated: true)
+								})
+								timer?.fire()
+								RunLoop.current.add(timer!, forMode: .common)
+				}
+
+				func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
+								return items.count
+				}
+
+				func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
+								let item = items[indexPath.row]
+								selectClouse?(item)
+				}
+
+				func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
+								return CGSize(width:collectionView.bounds.size.width,height:ceil(collectionView.bounds.size.height))
+				}
+
+				func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
+								print("--开始滑动")
+								timer?.fireDate = Date.distantFuture
+				}
+
+				func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
+								let page = scrollView.contentOffset.x / scrollView.width
+								if page.int >= pageControl.numberOfPages{
+												pageControl.currentPage = 0
+								}else{
+												pageControl.currentPage = page.int
+								}
+								print("--结束滑动")
+								timer?.fireDate = Date.init(timeIntervalSinceNow: 3.0) //3秒后开启
+				}
+
+				func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
+								let page = scrollView.contentOffset.x / scrollView.width
+								if page.int >= pageControl.numberOfPages{
+												pageControl.currentPage = 0
+								}else{
+												pageControl.currentPage = page.int
+								}
+				}
+
+				func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
+								let page = scrollView.contentOffset.x / scrollView.width
+								if page.int >= pageControl.numberOfPages{
+												pageControl.currentPage = 0
+												collectionView.setContentOffset(.zero, animated: false)
+								}else{
+												pageControl.currentPage = page.int
+								}
+				}
+
+				func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
+								let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BannerView", for: indexPath) as! CommonBannerViewCell
+								let item = items[indexPath.row]
+
+								switch item.mediaType {
+												case .imageUrl:
+																if let i = item.resource{
+																				cell.imgView.sd_setImage(with: URL(string: i))
+																}
+												case .imageLocal:
+																if let i = item.resource{
+																				cell.imgView.image = UIImage(named: i)
+																}
+												default:break
+								}
+								return cell
+				}
+}
+
+class CommonBannerViewCell: UICollectionViewCell {
+
+				lazy var imgView:UIImageView = {
+								let img = UIImageView()
+								img.contentMode = .scaleToFill
+								return img
+				}()
+
+				override init(frame: CGRect) {
+								super.init(frame: frame)
+								contentView.addSubview(imgView)
+								imgView.snp.makeConstraints { make in
+												make.edges.equalToSuperview()
+								}
+				}
+
+				required init?(coder aDecoder: NSCoder) {
+								fatalError("init(coder:) has not been implemented")
+				}
+}
diff --git a/DolphinEnglishLearnStudent/SceneDelegate.swift b/DolphinEnglishLearnStudent/SceneDelegate.swift
index eb38bf5..c32eecd 100644
--- a/DolphinEnglishLearnStudent/SceneDelegate.swift
+++ b/DolphinEnglishLearnStudent/SceneDelegate.swift
@@ -24,6 +24,10 @@
 								SVProgressHUD.setMaximumDismissTimeInterval(1.5)
 								SVProgressHUD.setDefaultMaskType(.custom)
 
+								guard let tokenModel = LoginTokenModel.getToken(),!LoginTokenModel.isOverdue() else {
+												needLogin()
+												return
+								}
 								loginSuccess()
 				}
 
diff --git a/DolphinEnglishLearnStudent/Services/NetworkRequest.swift b/DolphinEnglishLearnStudent/Services/NetworkRequest.swift
new file mode 100644
index 0000000..7ad8825
--- /dev/null
+++ b/DolphinEnglishLearnStudent/Services/NetworkRequest.swift
@@ -0,0 +1,278 @@
+//
+//  NetworkRequest.swift
+//  HandyJSON
+//
+//  Created by Sweet on 2018/12/25.
+//  Copyright © 2018 Sweet. All rights reserved.
+//
+
+import Foundation
+import SwifterSwift
+import Alamofire
+import HandyJSON
+import RxSwift
+import SVProgressHUD
+import JQTools
+
+// 假设这是服务端返回的统一定义的response格式
+struct BaseResponse<T :HandyJSON>: HandyJSON {
+				var sysTime: Int = 0
+				var code: Int = -1 // 服务端返回码
+				var data: T? = nil // 具体的data的格式和业务相关,故用泛型定义
+				var msg: String = ""
+}
+
+struct BaseData<T: HandyJSON>: HandyJSON {
+				var records = [T]()
+}
+
+struct SimpleModel: HandyJSON {
+
+}
+struct HtmlModel: HandyJSON {
+				var  content = ""
+				var  content1 = ""
+				var id = 0
+				var type =  0
+}
+
+extension String: HandyJSON{
+
+}
+extension Array: HandyJSON{
+
+}
+extension Bool: HandyJSON{
+
+}
+
+extension Int: HandyJSON{
+
+}
+
+let SHAKEY = ""
+
+class ParamsAppender: NSObject {
+				var url: URL
+				var params:Dictionary = [String: Any]()
+
+				private init(url: String){
+								self.url = URL(string: url)!
+				}
+
+				@discardableResult
+				func interface(url: String) -> ParamsAppender {
+								self.url.appendPathComponent(url)
+								return self
+				}
+
+				@discardableResult
+				func append(key: String,value: Bool) -> ParamsAppender {
+								params += ["\(key)":"\(value)"]
+								return self
+				}
+
+				@discardableResult
+				func append(key: String,value: String?) -> ParamsAppender {
+								if value != nil && value?.isEmpty == false {
+												params += ["\(key)":"\(value!)"]
+								}
+								return self
+				}
+
+				@discardableResult
+				func append(key: String,value: Array<String>) -> ParamsAppender {
+								if value.isEmpty == false {
+												params += ["\(key)":value]
+								}
+								return self
+				}
+
+
+				@discardableResult
+				func append(key: String, value: Int?) -> ParamsAppender {
+								if value != nil{
+												params += ["\(key)":value!]
+								}
+								return self
+				}
+
+				@discardableResult
+				func append(key: String, value: Int64) -> ParamsAppender {
+								params += ["\(key)":value]
+								return self
+				}
+
+				@discardableResult
+				func append(key: String, value: Double?) -> ParamsAppender {
+								if value != nil{
+												params += ["\(key)":value!]
+								}
+								return self
+				}
+
+				@discardableResult
+				func append(key: String,data: Data?) -> ParamsAppender {
+								if data != nil{
+												params += ["\(key)": data!]
+								}
+								return self
+				}
+
+				@discardableResult
+				func append(key: String,url: URL) -> ParamsAppender {
+								params += ["\(key)":"\(url)"]
+								return self
+				}
+
+				@discardableResult
+				func append(dic: [String : Any]) -> ParamsAppender {
+								params += dic
+								return self
+				}
+
+				/// 参数加密
+				@discardableResult
+				func done() -> Parameters {
+								var paramsArray: [String] = []
+								// 排序
+								let sortedArray: [String] = Array(params.keys).sorted()
+
+								//防止自签名而错误
+								if !sortedArray.contains("sign"){
+												for item in sortedArray{
+																// 拼接字符串
+																if params.has(key: item){
+																				paramsArray.append("\(item)=\(params[item]!)")
+																}
+												}
+												let content = paramsArray.joined(separator: "&")
+												params += ["sign": "\(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))"]
+
+#if DEBUG
+												LogInfo("签名:\(content) ----- \(content.jq_hmacBase64(algorithm: .SHA1, key: SHAKEY))")
+#endif
+								}
+								return self.params
+				}
+
+				class func build(url: String) -> ParamsAppender {
+								return ParamsAppender(url: url)
+				}
+
+}
+class NetworkRequest {
+
+				static let sharedSessionManager: Alamofire.Session = {
+								let configuration = URLSessionConfiguration.default
+								configuration.timeoutIntervalForRequest = 10
+								return Alamofire.Session(configuration: configuration)
+				}()
+				enum NetRequestError: Error {
+								case Other(Int,String)
+								case URLNotFound
+								case DownloadFailed
+								case InvaildSession
+								case ModelError(String)
+								case DataAnalysis(String)
+				}
+
+				class func request<T: HandyJSON>(params: ParamsAppender, method: HTTPMethod,  encoding: ParameterEncoding? = nil, progress: Bool = true,ignoreAlert:Bool = false) -> Observable<BaseResponse<T>>{
+
+								return Observable<BaseResponse<T>>.create{ ob in
+												guard NetworkReachabilityManager.init(host: All_Url)!.isReachable else {
+																alertError(msg: "当前网络不可用")
+																ob.onError(AFError.invalidURL(url: params.url))
+																return Disposables.create{}
+												}
+
+												if progress {showHUD()}
+
+												var headers = HTTPHeaders()
+
+												if let token = LoginTokenModel.getToken()?.access_token{
+																headers.add(name: "Authorization", value: "Bearer" + " " + token)
+																LogInfo("USER_token:Bearer \(token)")
+												}
+
+												if encoding is JSONEncoding {
+																headers.add(name: "Content-Type", value: "application/json;charset=UTF-8")
+												}
+
+												var newEncoding: ParameterEncoding
+												if encoding != nil {
+																newEncoding = encoding!
+												} else {
+																newEncoding = method == .post ? URLEncoding.httpBody : URLEncoding.queryString
+												}
+
+												sharedSessionManager.request(params.url.absoluteString, method: method, parameters:params.done(), encoding: newEncoding, headers:headers).validate().responseData{response in
+																LogInfo("请求地址:\(params.url)")
+																LogInfo("请求参数:\(params.params)")
+																hiddenHUD()
+
+																guard response.error == nil else {
+																				LogError("\(response.error!)")
+
+																				var errorString = ""
+																				errorString.append("服务器故障:\(response.error!.localizedDescription)")
+																				if let code = response.error?.responseCode{
+																								errorString.append("\n【错误码:\(code)】")
+																				}
+																				if !ignoreAlert{
+																								alert(msg: errorString)
+																				}
+																				ob.onError(response.error!)
+																				return
+																}
+																if let data = response.data,let jsonString = String(data: data, encoding: String.Encoding.utf8){
+																				LogResponse(try! JSONSerialization.jsonObject(with: data))
+																				if let next = BaseResponse<T>.deserialize(from: jsonString){
+																								switch next.code{
+																												case 200:ob.onNext(next)
+																												case 504: //登录设备最大限制
+																																let attribute = AttributedStringbuilder.build().add(string:next.msg, withFont: .systemFont(ofSize: 14, weight: .medium), withColor: .black.withAlphaComponent(0.6)).mutableAttributedString
+//																																CommonAlertView.show(title: "提示", attribute: attribute, cancelStr: "关闭", completeStr: "关闭", isSingle: true, customBtnWidth: JQ_ScreenW - 170) { _ in
+//
+//																																}
+																												case 503: //登录被冻结
+																																let attribute = AttributedStringbuilder.build().add(string:next.msg, withFont: .systemFont(ofSize: 14, weight: .medium), withColor: .black.withAlphaComponent(0.6)).mutableAttributedString
+//																																CommonAlertView.show(title: "提示", attribute: attribute, cancelStr: "关闭", completeStr: "关闭", isSingle: true, customBtnWidth: JQ_ScreenW - 170) { _ in
+//
+//																																}
+//																												case 501:
+//																																CommonAlertView.show(title: "提示", content: next.msg,isSingle: true) { _ in
+//
+//																																}
+//																																ob.onError(NetRequestError.InvaildSession)
+																												case 401:
+																																if !ignoreAlert{
+																																				alertError(msg: "登录失效,请重新登录");ob.onError(NetRequestError.InvaildSession)
+																																}
+																																sceneDelegate?.needLogin()
+																												default:
+																																if !ignoreAlert{
+																																				alertError(msg: "\(next.msg)")
+																																}
+																																ob.onError(NetRequestError.Other(next.code,next.msg))
+																								}
+																				}
+																}
+																ob.onCompleted()
+												}
+												return Disposables.create{}
+								}
+				}
+}
+extension Dictionary {
+				mutating func append(dict: Dictionary) {
+								dict.forEach { (key, value) in
+												self.updateValue(value, forKey: key)
+								}
+				}
+}
+
+
+func createError(text:String,code:Int)->AFError{
+				return AFError.createURLRequestFailed(error: NSError(domain: text, code: code))
+}
diff --git a/DolphinEnglishLearnStudent/Services/Services.swift b/DolphinEnglishLearnStudent/Services/Services.swift
new file mode 100644
index 0000000..ea96788
--- /dev/null
+++ b/DolphinEnglishLearnStudent/Services/Services.swift
@@ -0,0 +1,213 @@
+//
+//  Services.swift
+//  YixiuShop
+//
+//  Created by Sweet on 2019/9/30.
+//  Copyright © 2019 jackLove. All rights reserved.
+//
+
+import UIKit
+import RxSwift
+import Alamofire
+import JQTools
+
+#if DEBUG
+let All_Url = "http://192.168.110.237:9000"
+#else
+let All_Url = "http://192.168.110.237:9000"
+#endif
+
+class Services: NSObject {
+
+}
+
+extension Services{
+				class func weekList(quarter:Int)->Observable<BaseResponse<[ListenWeekModel]>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/study/base/study/weekList")
+								params.append(key: "quarter", value: quarter)
+								return NetworkRequest.request(params: params, method: .get, progress: false)
+				}
+}
+
+// MARK: -- 登录部分
+extension Services{
+				class func sendPhoneCode(phone:String)->Observable<BaseResponse<SimpleModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/study/base/user/sendPhoneCode")
+								params.append(key: "phone", value: phone)
+								return NetworkRequest.request(params: params, method: .get, progress: true)
+				}
+
+				class func login(phone:String,code:String)->Observable<BaseResponse<LoginModel>>{
+												let params = ParamsAppender.build(url: All_Url)
+												params.interface(url: "/study/base/user/studyLogin")
+								params.append(key: "phone", value: phone)
+								params.append(key: "phoneCode", value: code)
+								return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding.default, progress: true)
+				}
+}
+
+// MARK: -- 首页
+extension Services{
+
+}
+
+
+// MARK: -- 商品
+extension Services{
+				class func goodRecommend()->Observable<BaseResponse<[RecommendModel]>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/study/base/study/goodRecommend")
+								return NetworkRequest.request(params: params, method: .get, progress: false)
+				}
+
+				class func goodsList(keywords:String,page:Int,pageSize:Int = 20,type:[String])->Observable<BaseResponse<BaseResponseList<MarketModel>>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/goodListStudy")
+												.append(key: "keywords", value: keywords)
+												.append(key: "pageNumber", value: page)
+												.append(key: "pageSize", value: pageSize)
+												.append(key: "type", value: type)
+								return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding.default, progress: false)
+				}
+
+				class func getIntegral()->Observable<BaseResponse<Int>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/study/base/study/getIntegralStudy")
+								return NetworkRequest.request(params: params, method: .get, progress: false)
+				}
+
+				class func goodTypeStudy()->Observable<BaseResponse<[MarketTypeModel]>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/goodTypeStudy")
+								return NetworkRequest.request(params: params, method: .get, progress: false)
+				}
+
+				class func goodsDetail(goodsId:Int)->Observable<BaseResponse<MarketDetailModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/goodDetail")
+												.append(key: "goodId", value: goodsId)
+								return NetworkRequest.request(params: params, method: .get, progress: true)
+				}
+
+				class func addressList()->Observable<BaseResponse<[AddressModel]>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/shopAddress")
+								return NetworkRequest.request(params: params, method: .get, progress: false)
+				}
+
+				class func deleteAddress(id:Int)->Observable<BaseResponse<SimpleModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/addressDelete")
+												.append(key: "id", value: id)
+								return NetworkRequest.request(params: params, method: .get, progress: true)
+				}
+
+				class func redeemNow(goodId:Int)->Observable<BaseResponse<MarketDetailModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/redeemNow")
+												.append(key: "goodId", value: goodId)
+								return NetworkRequest.request(params: params, method: .get, progress: true)
+				}
+
+				class func addressTree()->Observable<BaseResponse<[AddressTreeModel]>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/addressTree")
+								return NetworkRequest.request(params: params, method: .get, progress: true)
+				}
+
+				class func addressSaveOrUpdate(id:Int?,province:AddressTreeModel?,city:AddressTreeModel?,country:AddressTreeModel?,userName:String?,userPhone:String?,isDefault:Bool,detailAddress:String)->Observable<BaseResponse<SimpleModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/addressSaveOrUpdate")
+												.append(key: "id", value: id)
+												.append(key: "address", value: detailAddress)
+												.append(key: "city", value: city?.name)
+												.append(key: "cityCode", value: city?.code)
+												.append(key: "province", value: province?.name)
+												.append(key: "provinceCode", value: province?.code)
+												.append(key: "recipient", value: userName)
+												.append(key: "recipientPhone", value: userPhone)
+												.append(key: "isDefault", value: (isDefault == true) ? 1:0)
+								return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding.default, progress: true)
+				}
+
+				class func setDefaultStudy(id:Int)->Observable<BaseResponse<SimpleModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/setDefaultStudy")
+												.append(key: "id", value: id)
+								return NetworkRequest.request(params: params, method: .get, progress: true)
+				}
+
+				class func goodsExchangeStudy(goodsId:Int,number:Int,orderNumber:String,recipientId:Int,remark:String)->Observable<BaseResponse<SimpleModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/goodExchangeStudy")
+												.append(key: "goodId", value: goodsId)
+												.append(key: "number", value: number)
+												.append(key: "orderNumber", value: orderNumber)
+												.append(key: "recipientId", value: recipientId)
+												.append(key: "remark", value: remark)
+								return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding.default, progress: true)
+				}
+
+				class func userInfo()->Observable<BaseResponse<UserInfoModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/study/base/user/userInfo")
+								return NetworkRequest.request(params: params, method: .get, progress: false)
+				}
+
+				class func integralDetail(pageNum:Int,pageSize:Int = 20,time:String?)->Observable<BaseResponse<BaseResponseList<IntegralModel>>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/study/base/study/integralDetail")
+												.append(key: "pageNum", value: pageNum)
+												.append(key: "pageSize", value: pageSize)
+												.append(key: "time", value: time)
+								return NetworkRequest.request(params: params, method: .get, progress: false)
+				}
+
+				class func exchangeRecord()->Observable<BaseResponse<[ExchangeRecordModel]>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/goods/base/goods/exchangeRecord")
+								return NetworkRequest.request(params: params, method: .get, progress: false)
+				}
+
+				class func studyGamesRecord()->Observable<BaseResponse<StudyGamesModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/study/base/study/record")
+								return NetworkRequest.request(params: params, method: .get, progress: true)
+				}
+
+				class func logoutStudy()->Observable<BaseResponse<SimpleModel>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/study/base/user/logoutStudy")
+								return NetworkRequest.request(params: params, method: .post,encoding: JSONEncoding.default, progress: true)
+				}
+
+}
+
+extension Services{
+				class func getAgreement(type:AgreementType)->Observable<BaseResponse<String>>{
+								let params = ParamsAppender.build(url: All_Url)
+								params.interface(url: "/study/base/user/getProtocol")
+								params.append(key: "type", value: type.rawValue)
+								return NetworkRequest.request(params: params, method: .post, progress: true)
+				}
+}
+
+
+extension Services{
+				static func startNetworkMonitor(){
+								let manager = NetworkReachabilityManager(host: All_Url)
+								manager?.startListening(onUpdatePerforming: { status in
+												switch status {
+																case .notReachable:alertError(msg: "当前网络不可用")
+																case .reachable(let type):
+																				switch type{
+																								case .ethernetOrWiFi:alert(msg: "当前为Wi-Fi网络")
+																								case .cellular:alert(msg: "当前为移动网络")
+																				}
+																default:break
+												}
+								})
+				}
+}
diff --git a/DolphinEnglishLearnStudent/ViewModel/RefreshModel.swift b/DolphinEnglishLearnStudent/ViewModel/RefreshModel.swift
new file mode 100644
index 0000000..02276d9
--- /dev/null
+++ b/DolphinEnglishLearnStudent/ViewModel/RefreshModel.swift
@@ -0,0 +1,305 @@
+//
+//  RefreshModel.swift
+//  WanPai
+//
+//  Created by 无故事王国 on 2023/7/11.
+//
+
+import UIKit
+import MJRefresh
+import RxSwift
+import HandyJSON
+import RxRelay
+
+
+enum RefreshState {
+				case refreshing
+				case completedRefresh
+				case moreLoading
+				case completedLoad
+				case completedLoadWithNoMoreData
+}
+
+struct BaseResponseList<T :HandyJSON>: HandyJSON {
+				var records: [T] = []
+				var current:Int = 0
+				var hasNextPage:Bool = false
+				var hasPrevPage:Bool = false
+				var pages:Int = 0
+				var size:Int = 0
+				var startIndex:Int = 0
+				var total:Int = 0
+}
+
+protocol RefreshModelProctol {
+				associatedtype T:HandyJSON
+				func api()->(Observable<BaseResponse<[T]>>)?
+}
+
+protocol RefreshModelInnerProctol {
+				associatedtype T:HandyJSON
+				func api()->(Observable<BaseResponse<BaseResponseList<T>>>)?
+}
+
+
+class RefreshModel<T:HandyJSON>:RefreshModelProctol{
+				func api() -> (RxSwift.Observable<BaseResponse<[T]>>)? {return nil}
+				let disposeBag = DisposeBag()
+				enum RefreshType {case refresh,load}
+
+				private var handle:UIScrollView!
+
+				lazy var refreshSubject = PublishSubject<RefreshState>()
+				var page:Int = 1
+				var pageSize:Int = 20
+				private var needRefreshData:Bool = true
+				lazy var dataSource = BehaviorRelay<[T]>(value: [])
+
+				func resetPage(){
+								page = 1
+				}
+
+				func configure(_ scrollView:UITableView,needMore:Bool = true){
+								scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
+								if needMore{
+												scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
+								}
+								refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
+								handle = scrollView
+				}
+
+				func configure(_ scrollView:UICollectionView,needMore:Bool = true,needRefreshData:Bool = true){
+								self.needRefreshData = needRefreshData
+								scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
+								if needMore{
+												scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
+								}
+								refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
+								handle = scrollView
+				}
+
+				func beginRefresh(){
+								guard handle != nil else {return}
+								api()?.subscribe(onNext: { data in
+												if let datas = data.data{
+																self.dataSource.accept(datas)
+																self.refreshSubject.onNext(.completedRefresh)
+												}
+								}).disposed(by: disposeBag)
+				}
+
+				func refreshData() ->(()->Void) {
+								return {self.request(status: .refresh)}
+				}
+
+				func loadMoreData() ->(()->Void) {
+								return {self.request(status: .load)}
+				}
+
+				func request(status:RefreshType){
+								switch status {
+												case .refresh:
+																self.page = 1
+																self.refreshSubject.onNext(.refreshing)
+												case .load:
+																self.page += 1
+																self.refreshSubject.onNext(.moreLoading)
+								}
+
+								api()?.subscribe(onNext: { data in
+												if let datas = data.data{
+																switch status{
+																				case .refresh:
+																								self.dataSource.accept(datas)
+																								self.refreshSubject.onNext(.completedRefresh)
+																				case .load:
+																								self.dataSource.accept(self.dataSource.value + datas)
+																								if datas.count == 0{
+																												self.refreshSubject.onNext(.completedLoadWithNoMoreData)
+																								}else{
+																												self.refreshSubject.onNext(.completedLoad)
+																								}
+																}
+												}else{
+																self.refreshSubject.onNext(.completedLoadWithNoMoreData)
+												}
+								}, onError: { error in
+												self.refreshSubject.onNext(.completedLoad)
+
+								}).disposed(by: disposeBag)
+				}
+}
+
+
+class RefreshInnerModel<T:HandyJSON>:RefreshModelInnerProctol{
+				func api() -> (RxSwift.Observable<BaseResponse<BaseResponseList<T>>>)? {
+								return nil
+				}
+
+				let disposeBag = DisposeBag()
+				enum RefreshType {case refresh,load}
+
+				private var handle:UIScrollView!
+
+				lazy var refreshSubject = PublishSubject<RefreshState>()
+				var page:Int = 0
+				var pageSize:Int = 20
+				private var needRefreshData:Bool = true
+				lazy var dataSource = BehaviorRelay<BaseResponseList<T>?>(value: nil)
+
+				func configure(_ scrollView:UITableView,needMore:Bool = true){
+								scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
+								if needMore{
+												scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
+								}
+								refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
+								handle = scrollView
+				}
+
+				func configure(_ scrollView:UICollectionView,needMore:Bool = true,needRefreshData:Bool = true){
+								self.needRefreshData = needRefreshData
+								scrollView.mj_header = CustomRefreshHeaer.refreshing(with: refreshData())
+								if needMore{
+												scrollView.mj_footer = CustomRefreshFooter.refreshing(with: loadMoreData())
+								}
+								refreshSubject.bind(to: scrollView.rx.handlestatus()).disposed(by: disposeBag)
+								handle = scrollView
+				}
+				func resetPage(){
+								page = 1
+				}
+
+				func beginRefresh(){
+								handle.mj_header?.beginRefreshing()
+				}
+
+				func refreshData() ->(()->Void) {
+								return {self.request(status: .refresh)}
+				}
+
+				func loadMoreData() ->(()->Void) {
+								return {self.request(status: .load)}
+				}
+
+				func request(status:RefreshType){
+								switch status {
+												case .refresh:
+																self.page = 1
+																self.refreshSubject.onNext(.refreshing)
+												case .load:
+																self.page += 1
+																self.refreshSubject.onNext(.moreLoading)
+								}
+
+								api()?.subscribe(onNext: { data in
+												switch status{
+																case .refresh:
+																				self.dataSource.accept(data.data)
+																				self.refreshSubject.onNext(.completedRefresh)
+																case .load:
+																				var new = self.dataSource.value?.records ?? []
+																				new.append(contentsOf: data.data?.records ?? [])
+																				var model = self.dataSource.value
+																				model!.records = new
+																				self.dataSource.accept(model)
+																				if data.data?.records.count == 0{
+																								self.refreshSubject.onNext(.completedLoadWithNoMoreData)
+																				}else{
+																								self.refreshSubject.onNext(.completedLoad)
+																				}
+												}
+								}, onError: { error in
+												self.refreshSubject.onNext(.completedLoad)
+
+								}).disposed(by: disposeBag)
+				}
+
+
+}
+
+
+class CustomRefreshHeaer:MJRefreshNormalHeader{
+				static func refreshing(with refreshingBlock: @escaping MJRefreshComponentAction) -> MJRefreshNormalHeader? {
+								let refreshHeader = MJRefreshNormalHeader(refreshingBlock: refreshingBlock)
+								return refreshHeader
+				}
+}
+
+class CustomRefreshFooter:MJRefreshAutoNormalFooter{
+				static func refreshing(with refreshingBlock: @escaping MJRefreshComponentAction) -> MJRefreshAutoNormalFooter? {
+								let refrehFooter = MJRefreshAutoNormalFooter(refreshingBlock: refreshingBlock)
+								refrehFooter.isRefreshingTitleHidden = true
+								refrehFooter.stateLabel?.isHidden = true
+								return refrehFooter
+				}
+}
+
+extension Reactive where Base : UITableView {
+
+				func handlestatus() -> Binder<RefreshState> {
+								return Binder(self.base) { (tableView, status) in
+												switch status {
+																case .moreLoading:
+																				self.base.mj_footer?.beginRefreshing()
+																case .refreshing:
+																				self.base.reloadData()
+																				self.base.mj_footer?.resetNoMoreData()
+																				self.base.mj_header?.beginRefreshing()
+
+																case .completedLoadWithNoMoreData:
+																				DispatchQueue.main.async {
+																								self.base.reloadData()
+																				}
+																				(self.base.mj_footer as? MJRefreshAutoNormalFooter)?.stateLabel?.isHidden = false
+																				self.base.mj_footer?.endRefreshingWithNoMoreData()
+																				self.base.mj_header?.endRefreshing()
+																case .completedLoad:
+																				DispatchQueue.main.async {
+																								self.base.reloadData()
+																				}
+																				self.base.mj_footer?.endRefreshing()
+																				self.base.mj_header?.endRefreshing()
+																default:
+																				DispatchQueue.main.async {
+																								self.base.reloadData()
+																				}
+																				self.base.mj_header?.endRefreshing()
+																				self.base.mj_footer?.endRefreshing()
+												}
+								}
+				}
+}
+
+extension Reactive where Base : UICollectionView {
+
+				func handlestatus() -> Binder<RefreshState> {
+								return Binder(self.base) { (tableView, status) in
+												switch status {
+																case .moreLoading:
+																				self.base.mj_footer?.beginRefreshing()
+																case .refreshing:
+																				self.base.reloadData()
+																				self.base.mj_footer?.resetNoMoreData()
+																				self.base.mj_header?.endRefreshing()
+
+																case .completedLoadWithNoMoreData:
+																				DispatchQueue.main.async {
+																								self.base.reloadData()
+																				}
+																				self.base.mj_footer?.endRefreshingWithNoMoreData()
+																case .completedLoad:
+																				DispatchQueue.main.async {
+																								self.base.reloadData()
+																				}
+																				self.base.mj_footer?.endRefreshing()
+																default:
+																				DispatchQueue.main.async {
+																								self.base.reloadData()
+																				}
+																				self.base.mj_header?.endRefreshing()
+																				self.base.mj_footer?.endRefreshing()
+												}
+								}
+				}
+}
+
diff --git a/DolphinEnglishLearnStudent/ViewModel/UserViewModel.swift b/DolphinEnglishLearnStudent/ViewModel/UserViewModel.swift
new file mode 100644
index 0000000..bb2051a
--- /dev/null
+++ b/DolphinEnglishLearnStudent/ViewModel/UserViewModel.swift
@@ -0,0 +1,55 @@
+//
+//  UserViewModel.swift
+//  DolphinEnglishLearnStudent
+//
+//  Created by 无故事王国 on 2024/5/30.
+//
+
+import Foundation
+import UserDefaultsStore
+import HandyJSON
+
+struct UserInfoModel:HandyJSON,Identifiable,Codable{
+				static let idKey = \UserInfoModel.id
+				var id: Int = 0
+				var account: String = ""
+				var birthday: String = ""
+				var createBy: String = ""
+				var createTime: String = ""
+				var disabled: Bool = false
+				var gender: Int = 0
+				var headImg: String = ""
+				var insertTime: String = ""
+				var integral: Int = 0
+				var isVip: Int = 0
+				var name: String = ""
+				var openId: String = ""
+				var password: String = ""
+				var phone: String = ""
+				var state: Int = 0
+				var updateBy: String = ""
+				var updateTime: String = ""
+				var vipEndTime: String = ""
+				var vipPayTime: String = ""
+
+}
+
+class UserViewModel{
+				private static let userInfo = UserDefaultsStore<UserInfoModel>(uniqueIdentifier: "UserInfoModel")!
+
+				static func saveUserInfo(_ model:UserInfoModel){
+								do{
+												try UserViewModel.userInfo.save(model)
+								}catch{
+
+								}
+				}
+
+				static func getUserInfo()->UserInfoModel?{
+								return UserViewModel.userInfo.allObjects().first
+				}
+
+				static func clearUserInfo(){
+								UserViewModel.userInfo.deleteAll()
+				}
+}
diff --git a/Podfile b/Podfile
index 35aa517..08b97b2 100644
--- a/Podfile
+++ b/Podfile
@@ -13,5 +13,6 @@
 #  pod 'Alamofire' # 网络请求框架
   pod 'SVProgressHUD' # 提示框组件
   pod 'CryptoSwift' # 常用加密算法
+	pod 'Alamofire' # 网络请求框架
 
 end

--
Gitblit v1.7.1