├── .gitignore ├── Podfile ├── Podfile.lock ├── README.md ├── TQGO.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── yxy.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── yxy.xcuserdatad │ └── xcschemes │ ├── TQGO.xcscheme │ └── xcschememanagement.plist ├── TQGO.xcworkspace ├── contents.xcworkspacedata ├── xcshareddata │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── yxy.xcuserdatad │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── TQGO ├── Category │ ├── Date+Common.swift │ ├── DispatchQueue+common.swift │ ├── NSObject+Common.swift │ ├── Notification.Name+YXYCommon.swift │ ├── String+Common.swift │ ├── UIButton+YXYCommon.swift │ ├── UIColor+YXYCommon.swift │ ├── UIDevice+Common.swift │ ├── UIImage+YYCommon.swift │ ├── UISegmentControll+YXYCommon.swift │ ├── UITableViewCell+RXCommon.swift │ ├── UITextField+YYCommon.swift │ ├── UIView+Common.swift │ ├── UIViewController+RXCommon.swift │ └── UIViewController+YXYCommon.swift ├── Class │ ├── Base │ │ ├── AppDelegate.swift │ │ ├── BaseNavigationController.swift │ │ ├── BaseTabBarVC.swift │ │ ├── BaseTableView.swift │ │ ├── BaseVC.swift │ │ ├── Common.swift │ │ └── ProjectTabBarVC.swift │ ├── CreditPayModule │ │ └── Controller │ │ │ └── CreditPayVC.swift │ ├── LoginRegisterModule │ │ ├── Controller │ │ │ ├── LoginVC.swift │ │ │ └── RegisterVC.swift │ │ └── ViewModel │ │ │ ├── LoginVM.swift │ │ │ └── RegisterVM.swift │ ├── PersonalCenterModule │ │ ├── Controller │ │ │ └── PersonalCenterVC.swift │ │ ├── Model │ │ │ └── UserInfo.swift │ │ └── View │ │ │ └── MyHeaderCell.swift │ ├── PromotionModule │ │ ├── Controller │ │ │ ├── GoodsDetailVC.swift │ │ │ ├── PromotionSubVC.swift │ │ │ └── PromotionVC.swift │ │ ├── Model │ │ │ ├── MenuModel.swift │ │ │ ├── PromosModel.swift │ │ │ └── PromotionModel.swift │ │ └── View │ │ │ └── PromotionSubCell.swift │ ├── ShopCartModule │ │ └── Controller │ │ │ └── ShopCartVC.swift │ └── UnicomAreaModule │ │ ├── Controller │ │ └── UnicomAreaVC.swift │ │ ├── Model │ │ ├── GoodsModel.swift │ │ ├── SlideShowModel.swift │ │ └── UnicomIndexModel.swift │ │ └── View │ │ ├── ADCell.swift │ │ ├── DiscountAreaCell.swift │ │ ├── HotCollectionViewCell.swift │ │ ├── HotGoodsCell.swift │ │ └── UnicomMenuCell.swift ├── Info.plist ├── Macro │ ├── AppConstant.swift │ ├── Macro.swift │ └── TQGO-Bridging-Header.h ├── Model │ └── APIModel │ │ └── APIResultModel.swift ├── Resource │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── icon-20@2x.png │ │ │ ├── icon-20@3x.png │ │ │ ├── icon-29@2x.png │ │ │ ├── icon-29@3x.png │ │ │ ├── icon-40@2x.png │ │ │ ├── icon-40@3x.png │ │ │ ├── icon-60@2x.png │ │ │ ├── icon-60@3x.png │ │ │ └── icon_1024.png │ │ ├── Contents.json │ │ ├── LanchIcon │ │ │ ├── Contents.json │ │ │ └── icon_launch.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_launch@2x.png │ │ │ │ └── icon_launch@3x.png │ │ ├── MyImage │ │ │ ├── Contents.json │ │ │ ├── icon_arrow_right_white.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_arrow_right_white@2x.png │ │ │ │ └── icon_arrow_right_white@3x.png │ │ │ ├── icon_header.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_header@2x.png │ │ │ │ └── icon_header@3x.png │ │ │ ├── icon_phone_num.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_phone_num@2x.png │ │ │ │ └── icon_phone_num@3x.png │ │ │ ├── icon_secure_close.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_secure_close@2x.png │ │ │ │ └── icon_secure_close@3x.png │ │ │ ├── icon_secure_visible.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_secure_visible@2x.png │ │ │ │ └── icon_secure_visible@3x.png │ │ │ ├── icon_security_lock.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_security_lock@2x.png │ │ │ │ └── icon_security_lock@3x.png │ │ │ └── icon_verity_code.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_verity_code@2x.png │ │ │ │ └── icon_verity_code@3x.png │ │ ├── TabbarImage │ │ │ ├── Contents.json │ │ │ ├── icon_tabbar_default_credit.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_tabbar_default_credit@2x.png │ │ │ │ └── icon_tabbar_default_credit@3x.png │ │ │ ├── icon_tabbar_default_personalCenter.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_tabbar_default_personalCenter@2x.png │ │ │ │ └── icon_tabbar_default_personalCenter@3x.png │ │ │ ├── icon_tabbar_default_promotion.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_tabbar_default_promotion@2x.png │ │ │ │ └── icon_tabbar_default_promotion@3x.png │ │ │ ├── icon_tabbar_default_unicom.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_tabbar_default_unicom@2x.png │ │ │ │ └── icon_tabbar_default_unicom@3x.png │ │ │ ├── icon_tabbar_selected_credit.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_tabbar_selected_credit@2x.png │ │ │ │ └── icon_tabbar_selected_credit@3x.png │ │ │ ├── icon_tabbar_selected_personalCenter.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_tabbar_selected_personalCenter@2x.png │ │ │ │ └── icon_tabbar_selected_personalCenter@3x.png │ │ │ ├── icon_tabbar_selected_promotion.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_tabbar_selected_promotion@2x.png │ │ │ │ └── icon_tabbar_selected_promotion@3x.png │ │ │ └── icon_tabbar_selected_unicom.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_tabbar_selected_unicom@2x.png │ │ │ │ └── icon_tabbar_selected_unicom@3x.png │ │ └── UnicomImage │ │ │ ├── Contents.json │ │ │ ├── icon_flag_blue.imageset │ │ │ ├── Contents.json │ │ │ ├── icon_flag_blue@2x.png │ │ │ └── icon_flag_blue@3x.png │ │ │ ├── icon_gift_area.imageset │ │ │ ├── Contents.json │ │ │ ├── icon_gift_area@2x.png │ │ │ └── icon_gift_area@3x.png │ │ │ ├── icon_goods_default.imageset │ │ │ ├── Contents.json │ │ │ ├── icon_goods_default@2x.png │ │ │ └── icon_goods_default@3x.png │ │ │ ├── icon_home_banner_default.imageset │ │ │ ├── Contents.json │ │ │ ├── icon_home_banner_default@2x.png │ │ │ └── icon_home_banner_default@3x.png │ │ │ ├── icon_phone_area.imageset │ │ │ ├── Contents.json │ │ │ ├── icon_phone_area@2x.png │ │ │ └── icon_phone_area@3x.png │ │ │ └── icon_search.imageset │ │ │ ├── Contents.json │ │ │ ├── icon_search@2x.png │ │ │ └── icon_search@3x.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ └── BimineData │ │ ├── UnicomAreaDiscountZone.plist │ │ ├── UnicomAreaRecommGoods.plist │ │ ├── UnicomBanner.plist │ │ ├── goodsJJYX.plist │ │ ├── goodsMZXH.plist │ │ ├── goodsPJZX.plist │ │ ├── homeBanner.plist │ │ └── menu.plist └── Tool │ ├── NetworkManager │ ├── NetworkManager.swift │ ├── NetworkManagerLoginRegister.swift │ ├── NetworkManagerPromotion.swift │ └── NetworkManagerUnicom.swift │ ├── RealmTool │ └── RealmManager.swift │ ├── Regex │ └── Regex.swift │ └── ViewTool │ ├── YXYBanner │ └── YXYBanner.swift │ └── YXYPageView │ ├── YXYMenuTitleView.swift │ ├── YXYPageContentView.swift │ └── YXYPageView.swift ├── TQGOTests ├── Info.plist └── TQGOTests.swift └── TQGOUITests ├── Info.plist └── TQGOUITests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .DS_Store 3 | UserInterfaceState.xcuserstate 4 | # Xcode 5 | .DS_Store 6 | */build/* 7 | *.pbxuser 8 | !default.pbxuser 9 | *.mode1v3 10 | !default.mode1v3 11 | *.mode2v3 12 | !default.mode2v3 13 | *.perspectivev3 14 | !default.perspectivev3 15 | xcuserdata 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | *.hmap 20 | *.xccheckout 21 | *.xcworkspace 22 | !default.xcworkspace 23 | Report.xml 24 | #CocoaPods 25 | Pods 26 | !Podfile -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '10.0' 2 | 3 | target 'TQGO' do 4 | use_frameworks! 5 | 6 | pod 'MJRefresh', '~> 3.2.2' 7 | 8 | #pod 'RealmSwift', '~> 4.1.0' 9 | #pod 'SwiftyJSON', '~> 5.0.0' 10 | #pod 'Kingfisher', '~> 5.9.0' 11 | #pod 'Alamofire', '~> 5.0.0-rc.3' 12 | #pod 'SnapKit', '~> 5.0.1' 13 | #pod 'HandyJSON', '~> 5.0.1' 14 | #pod 'RxSwift', '~> 5.0.1' 15 | #pod 'RxCocoa', '~> 5.0.1' 16 | #pod 'Toast-Swift', '~> 5.0.0' 17 | 18 | target 'TQGOTests' do 19 | inherit! :search_paths 20 | # Pods for testing 21 | end 22 | 23 | target 'TQGOUITests' do 24 | inherit! :search_paths 25 | # Pods for testing 26 | end 27 | 28 | end 29 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MJRefresh (3.2.2) 3 | 4 | DEPENDENCIES: 5 | - MJRefresh (~> 3.2.2) 6 | 7 | SPEC REPOS: 8 | https://github.com/CocoaPods/Specs.git: 9 | - MJRefresh 10 | 11 | SPEC CHECKSUMS: 12 | MJRefresh: 72a46ecaa2a0feaf48fc5198dff95f25f8bb27c6 13 | 14 | PODFILE CHECKSUM: 0d9159dd8014ff4b30edff92a7b714ed6ec6ad36 15 | 16 | COCOAPODS: 1.11.3 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftProject 2 | ![演示](https://upload-images.jianshu.io/upload_images/3066088-22ba8970c4f15fa3.gif) 3 | 4 | > swift项目实战 5 | 6 | #支持# 7 | 8 | **iOS 13.2 、swift5.1** 9 | 10 | >[简书](https://www.jianshu.com/p/ac7e9959646f) 11 | 12 | >拉取项目后,需自行根据podfile文件拉取pod,此过程需等待一会 13 | 14 | >网络请求部分:网络层封装的接口通信为笔者自行书写,包括公共参数、加密、加签过程,此部分需根据自己项目与后台协定方式为准,为模仿真实网络请求过程,设置Alamofire的超时时间为0.2s,且数据为本地plist文件读取。 15 | 16 | >本项目进行了关键数据脱敏,所以忽略相关数据 17 | 18 | >登录功能:MVVM+RxSwift 19 | 20 | >[使用Swift Package Manager管理第三方库](https://www.jianshu.com/p/b9ba7154f4c2) 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /TQGO.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TQGO.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TQGO.xcodeproj/project.xcworkspace/xcuserdata/yxy.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO.xcodeproj/project.xcworkspace/xcuserdata/yxy.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /TQGO.xcodeproj/xcuserdata/yxy.xcuserdatad/xcschemes/TQGO.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 52 | 58 | 59 | 60 | 61 | 62 | 72 | 74 | 80 | 81 | 82 | 83 | 89 | 91 | 97 | 98 | 99 | 100 | 102 | 103 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /TQGO.xcodeproj/xcuserdata/yxy.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | TQGO.xcscheme 8 | 9 | orderHint 10 | 9 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 9A70491320F2FD5600982DCB 16 | 17 | primary 18 | 19 | 20 | 9A70492720F2FD5800982DCB 21 | 22 | primary 23 | 24 | 25 | 9A70493220F2FD5800982DCB 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /TQGO.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /TQGO.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /TQGO.xcworkspace/xcuserdata/yxy.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 9 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /TQGO/Category/Date+Common.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Date+Common.swift 3 | // TQGO q 123 4 | // 5 | // Created by YXY on 2018/7/11. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 不规范协助 12 | // 1 13 | enum kTimeFormat:String{ 14 | case format_default = "yyyy-MM-dd HH:mm:ss" 15 | case format_yyMdHm = "yy-MM-dd HH:mm" 16 | case format_yyyyMdHm = "yyyy-MM-dd HH:mm" 17 | case format_yMd = "yyyy-MM-dd" 18 | case format_MdHms = "MM-dd HH:mm:ss" 19 | case format_MdHm = "MM-dd HH:mm" 20 | case format_Hms = "HH:mm:ss" 21 | case format_Hm = "HH:mm" 22 | case format_Md = "MM-dd" 23 | case format_yyMd = "yy-MM-dd" 24 | case format_YYMMdd = "yyyyMMdd" 25 | case format_yyyyMdHms = "yyyyMMddHHmmss" 26 | case format_yyyyMdHmsS = "yyyy-MM-dd HH:mm:ss.SSS" 27 | case format_yyyyMMddHHmmssSSS = "yyyyMMddHHmmssSSS" 28 | case format_yMdWithSlash = "yyyy/MM/dd" 29 | case format_yM = "yyyy-MM" 30 | case format_yMdChangeSeparator = "yyyy.MM.dd" 31 | } 32 | // 2 33 | extension Date{ 34 | 35 | } 36 | //3 37 | //4 38 | -------------------------------------------------------------------------------- /TQGO/Category/DispatchQueue+common.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DispatchQueue+common.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/3/25. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | // pick 12 | extension DispatchQueue{ 13 | private static var _onceTracker = [String]() 14 | /// 单例 仅创建一次 15 | /// 16 | /// - Parameters: 17 | /// - token: token 18 | /// - block: 代码块 19 | public class func once(token: String, block:()->Void) { 20 | objc_sync_enter(self) 21 | defer { objc_sync_exit(self) } 22 | if _onceTracker.contains(token) { 23 | return 24 | } 25 | _onceTracker.append(token) 26 | block() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TQGO/Category/NSObject+Common.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NSObject+Common.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/20. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension NSObject{ 13 | 14 | /// 模型转JSONString 15 | var modelToJSONString : String { 16 | let jsonData = try? JSONSerialization.data(withJSONObject: self, options: []) 17 | let jsonStr = String(data: jsonData!, encoding: String.Encoding.utf8) 18 | return jsonStr! 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TQGO/Category/Notification.Name+YXYCommon.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Notification.Name+YXYCommon.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/11/15. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | extension Notification.Name{ 13 | 14 | // 通知key 避免key重复 15 | private enum kNotify_Key:String { 16 | case ShopcartNum //购物车角标数 17 | case RefreshData // 商品兑换成功或失败后刷新数据 18 | case RefreshGift // 一次性领取礼包后刷新数据 19 | case LoginOut // 退出登录后刷新数据 20 | case Login //登录后刷新数据 21 | case ChangeCity// 切换城市后刷新数据 22 | case RefreshGood // 兑换商品后刷新商品列表数据 23 | case WXpay // 微信支付处理数据 24 | case CityCode// 当前选择的城市编码 25 | case CurrentCity //// 当前选择的城市名称 26 | case LocationCity// 当前定位的城市名称 27 | case LocationCityCode /// 当前定位的城市编码 28 | case IsHiddenrechargeButton // 0 不可购买 1可购买 29 | case OrderNo // 下单流水号 30 | case More // 领取礼包点击查看更多 31 | case safeName // 32 | case safeIDNO // 33 | case LeaveTop //= "kLeaveTop" //首页滑动通知 34 | } 35 | public static let kLeaveTop = Notification.Name("com.techwis.\(kNotify_Key.LeaveTop)") 36 | public static let kShopcartNum = Notification.Name("com.techwis.\(kNotify_Key.ShopcartNum)") 37 | } 38 | -------------------------------------------------------------------------------- /TQGO/Category/String+Common.swift: -------------------------------------------------------------------------------- 1 | // 2 | // String+Common.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/11. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension String{ 13 | 14 | var md5 : String{ 15 | let str = self.cString(using: String.Encoding.utf8) 16 | let strLen = CC_LONG(self.lengthOfBytes(using: String.Encoding.utf8)) 17 | let digestLen = Int(CC_MD5_DIGEST_LENGTH) 18 | let result = UnsafeMutablePointer.allocate(capacity: digestLen) 19 | CC_MD5(str!, strLen, result) 20 | let hash = NSMutableString() 21 | for i in 0 ..< digestLen { 22 | hash.appendFormat("%02x", result[i]) 23 | } 24 | // result.deinitialize() 25 | result.deinitialize(count: 1) 26 | return String(format: hash as String) 27 | } 28 | 29 | static func nowTimeWithFormat(format:String) -> String { 30 | let dateFormatter:DateFormatter = DateFormatter() 31 | dateFormatter.dateFormat = format 32 | dateFormatter.locale = Locale(identifier: kDate_Location) 33 | return dateFormatter.string(from: Date()) 34 | } 35 | 36 | /// 获取一段字符串的宽度 37 | /// 38 | /// - Parameter fontSize: 字体大小 39 | /// - Returns: 字符串宽度 40 | func width(fontSize:CGFloat) -> CGFloat { 41 | return self.size(withAttributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: fontSize)]).width 42 | } 43 | 44 | } 45 | 46 | //MARK: 字符串截取 47 | extension String{ 48 | /// 从某个位置开始截取: 49 | /// - Parameter index: 起始位置 50 | public func substring(from index: Int) -> String { 51 | if(self.count > index){ 52 | let startIndex = self.index(self.startIndex,offsetBy: index) 53 | let subString = self[startIndex.. String { 63 | if(self.count > index){ 64 | let endindex = self.index(self.startIndex, offsetBy: index) 65 | let subString = self[self.startIndex.. String{ 75 | var string = String() 76 | if(rangs.location >= 0) && (count > (rangs.location + rangs.length)){ 77 | let startIndex = self.index(self.startIndex,offsetBy: rangs.location) 78 | let endIndex = self.index(self.startIndex,offsetBy: (rangs.location + rangs.length)) 79 | let subString = self[startIndex.. Bool { 91 | let pre :NSPredicate = NSPredicate(format: "SELF MATCHES %@", argumentArray: [regex]) 92 | return pre.evaluate(with: self) 93 | } 94 | 95 | /// 手机号分服务商 96 | func isMobileNumberClassification() ->Bool{ 97 | /** 98 | 15 * 手机号码 99 | 16 * 移动:134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188,1705 100 | 17 * 联通:130,131,132,152,155,156,185,186,1709 101 | 18 * 电信:133,1349,153,180,189,1700 102 | 19 */ 103 | // NSString * MOBILE = @"^1((3//d|5[0-35-9]|8[025-9])//d|70[059])\\d{7}$";//总况 104 | /** 105 | 23 10 * 中国移动:China Mobile 106 | 24 11 * 134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188,1705 107 | 25 12 */ 108 | let CM = "^((13[4-9])|(147)|(15[0-2,7-9])|(17[2,8])|(18[2-4,7-8]))\\d{8}|(1705)\\d{7}$"; 109 | // NSString *CM = @"^((13[4-9])|(147)|(15[0-2,7-9])|(178)|(18[2-4,7-8]))\\d{8}|(1705)\\d{7}$"; 110 | // NSString * CM = @"^1(34[0-8]|(3[5-9]|5[017-9]|78|8[278])\\d|705)\\d{7}$"; 111 | /** 112 | 28 15 * 中国联通:China Unicom 113 | 29 16 * 130,131,132,152,155,156,185,186,1709 114 | 30 17 */ 115 | let CU = "^((13[0-2])|(145)|(15[5-6])|(17[1,5,6])|(18[5,6]))\\d{8}|(1709)\\d{7}$"; 116 | // NSString *CU = @"^((13[0-2])|(145)|(15[5-6])|(176)|(18[5,6]))\\d{8}|(1709)\\d{7}$"; 117 | // NSString * CU = @"^1((3[0-2]|5[256]|8[56])\\d|709)\\d{7}$"; 118 | /** 119 | 33 20 * 中国电信:China Telecom 120 | 34 21 * 133,1349,153,180,189,1700 121 | 35 22 */ 122 | let CT = "^((133)|(149)|(153)|(17[3,7])|(18[0,1,9]))\\d{8}$"; 123 | // NSString *CT = @"^((133)|(153)|(177)|(18[0,1,9]))\\d{8}$"; 124 | // NSString * CT = @"^1((33|53|8[09])\\d|349|700)\\d{7}$"; 125 | /** 126 | 40 25 * 大陆地区固话及小灵通 127 | 41 26 * 区号:010,020,021,022,023,024,025,027,028,029 128 | 42 27 * 号码:七位或八位 129 | 43 28 */ 130 | let PHS = "^0(10|2[0-5789]|\\d{3})\\d{7,8}$"; 131 | // NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE]; 132 | 133 | if ( isValidateByRegex(regex: CM) || isValidateByRegex(regex:CU) || isValidateByRegex(regex:CT) || isValidateByRegex(regex:PHS)){ 134 | return true 135 | }else { 136 | return false 137 | } 138 | } 139 | } 140 | 141 | //MARK: file 142 | extension String{ 143 | /// 判断文件是否存在 144 | /// 145 | /// - Returns: 存在true 不存在false 146 | func fileExist() -> Bool { 147 | return FileManager.default.fileExists(atPath: self as String) 148 | } 149 | 150 | /// 创建文件夹 151 | func fileCreateDirectory() { 152 | try! FileManager.default.createDirectory(at: NSURL(fileURLWithPath:self , isDirectory: true, relativeTo: nil) as URL, withIntermediateDirectories: true, attributes: nil) 153 | } 154 | 155 | /// 拼接路径 156 | /// 157 | /// - Parameter byAppendingPaths: 要拼接的文件名 158 | /// - Returns: 拼接后的路径 159 | func fileByAppendingPaths(byAppendingPaths: String) -> String { 160 | 161 | return (self as NSString).strings(byAppendingPaths: [byAppendingPaths]).first! 162 | } 163 | 164 | /// 读取本地数据 165 | func getLocalPlistData() -> NSArray? { 166 | let path = Bundle.main.path(forResource: self, ofType: "plist") 167 | return NSArray(contentsOfFile: path!) 168 | } 169 | } 170 | 171 | ////MARK: 实现NSRange与Range的相互转换 172 | //extension String { 173 | // 174 | // //Range转换为NSRange 175 | // func nsRange(from range: Range) -> NSRange { 176 | // let from = range.lowerBound.samePosition(in: utf16) 177 | // let to = range.upperBound.samePosition(in: utf16) 178 | // return NSRange(location: utf16.distance(from: utf16.startIndex, to: from ?? 0), 179 | // length: utf16.distance(from: from, to: to)) 180 | // } 181 | // 182 | // //Range转换为NSRange 183 | // func range(from nsRange: NSRange) -> Range? { 184 | // guard 185 | // let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, 186 | // limitedBy: utf16.endIndex), 187 | // let to16 = utf16.index(from16, offsetBy: nsRange.length, 188 | // limitedBy: utf16.endIndex), 189 | // let from = String.Index(from16, within: self), 190 | // let to = String.Index(to16, within: self) 191 | // else { return nil } 192 | // return from ..< to 193 | // } 194 | //} 195 | -------------------------------------------------------------------------------- /TQGO/Category/UIButton+YXYCommon.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIButton+YXYCommon.swift 3 | // TQGO 4 | // UIButton通用分类 5 | // Created by YXY on 2019/10/22. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | 13 | enum YXYButtonEdgeInsetsStyle { 14 | case YXYButtonEdgeInsetsStyleTop // image在上,label在下 15 | case YXYButtonEdgeInsetsStyleLeft // image在左,label在右 16 | case YXYButtonEdgeInsetsStyleBottom // image在下,label在上 17 | case YXYButtonEdgeInsetsStyleRight // image在右,label在左 18 | } 19 | //MARK: title image 位置布局 20 | extension UIButton{ 21 | 22 | /// 调整文字和图片相对位置 23 | /// - Parameter style: 显示样式 24 | /// - Parameter imageTitleSpace: 间距 25 | func layoutButtonWithEdgeInsetsStyle(style:YXYButtonEdgeInsetsStyle,imageTitleSpace:CGFloat) { 26 | let imageWith:CGFloat = imageView?.frame.width ?? 0; 27 | let imageHeight:CGFloat = imageView?.frame.height ?? 0; 28 | 29 | var labelWidth:CGFloat = 0.0; 30 | var labelHeight:CGFloat = 0.0; 31 | 32 | if (kSystemVersion >= 8.0) { 33 | // 由于iOS8中titleLabel的size为0,用下面的这种设置 34 | labelWidth = titleLabel?.intrinsicContentSize.width ?? 0; 35 | labelHeight = titleLabel?.intrinsicContentSize.height ?? 0; 36 | } else { 37 | labelWidth = titleLabel?.frame.width ?? 0; 38 | labelHeight = titleLabel?.frame.height ?? 0; 39 | } 40 | 41 | // 2. 声明全局的imageEdgeInsets和labelEdgeInsets 42 | var imageEdgeInsets: UIEdgeInsets = UIEdgeInsets.zero; 43 | var labelEdgeInsets: UIEdgeInsets = UIEdgeInsets.zero; 44 | 45 | // 3. 根据style和space得到imageEdgeInsets和labelEdgeInsets的值 46 | switch style { 47 | case .YXYButtonEdgeInsetsStyleTop: 48 | imageEdgeInsets = UIEdgeInsets(top: -labelHeight-imageTitleSpace/2.0, left: 0, bottom: 0, right: -labelWidth) 49 | labelEdgeInsets = UIEdgeInsets(top: 0, left: -imageWith, bottom: -imageHeight-imageTitleSpace/2.0, right: 0) 50 | case .YXYButtonEdgeInsetsStyleLeft: 51 | imageEdgeInsets = UIEdgeInsets(top:0, left:-imageTitleSpace/2.0, bottom:0, right: imageTitleSpace/2.0); 52 | labelEdgeInsets = UIEdgeInsets(top:0,left: imageTitleSpace/2.0, bottom:0, right: -imageTitleSpace/2.0); 53 | case .YXYButtonEdgeInsetsStyleBottom: 54 | imageEdgeInsets = UIEdgeInsets(top:0, left:0, bottom:-labelHeight-imageTitleSpace/2.0, right: -labelWidth); 55 | labelEdgeInsets = UIEdgeInsets(top:-imageHeight-imageTitleSpace/2.0,left: -imageWith, bottom:0, right: 0); 56 | case .YXYButtonEdgeInsetsStyleRight: 57 | imageEdgeInsets = UIEdgeInsets(top:0,left: labelWidth+imageTitleSpace/2.0, bottom:0, right: -labelWidth-imageTitleSpace/2.0); 58 | labelEdgeInsets = UIEdgeInsets(top:0, left:-imageWith-imageTitleSpace/2.0, bottom:0, right: imageWith+imageTitleSpace/2.0); 59 | } 60 | 61 | // 4. 赋值 62 | titleEdgeInsets = labelEdgeInsets; 63 | self.imageEdgeInsets = imageEdgeInsets; 64 | } 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /TQGO/Category/UIColor+YXYCommon.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor+YXYCommon.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/10/23. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | extension UIColor { 12 | 13 | public func asImage(_ size:CGSize) -> UIImage? { 14 | 15 | var resultImage:UIImage? = nil 16 | 17 | let rect = CGRect(x:0, y:0, width: size.width, height: size.height) 18 | UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale) 19 | guard let context = UIGraphicsGetCurrentContext() else { 20 | return resultImage 21 | } 22 | 23 | context.setFillColor(self.cgColor) 24 | context.fill(rect) 25 | resultImage = UIGraphicsGetImageFromCurrentImageContext() 26 | UIGraphicsEndImageContext() 27 | return resultImage 28 | 29 | } 30 | 31 | } 32 | 33 | 34 | -------------------------------------------------------------------------------- /TQGO/Category/UIDevice+Common.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIDevice+Common.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/11. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | 13 | extension UIDevice { 14 | /// 获取设备具体详细的型号 15 | var modelName: String { 16 | var systemInfo = utsname() 17 | uname(&systemInfo) 18 | let machineMirror = Mirror(reflecting: systemInfo.machine) 19 | let identifier = machineMirror.children.reduce("") { identifier, element in 20 | guard let value = element.value as? Int8, value != 0 else { return identifier } 21 | return identifier + String(UnicodeScalar(UInt8(value))) 22 | } 23 | 24 | // struct utsname systemInfo; 25 | // uname(&systemInfo); 26 | // NSString *platform = [NSString stringWithCString:systemInfo.machine 27 | // encoding:NSUTF8StringEncoding]; 28 | 29 | switch identifier { 30 | 31 | case "iPhone3,1", "iPhone3,2", "iPhone3,3": return "iPhone 4" 32 | case "iPhone4,1": return "iPhone 4s" 33 | case "iPhone5,1", "iPhone5,2": return "iPhone 5" 34 | case "iPhone5,3", "iPhone5,4": return "iPhone 5c" 35 | case "iPhone6,1", "iPhone6,2": return "iPhone 5s" 36 | case "iPhone7,2": return "iPhone 6" 37 | case "iPhone7,1": return "iPhone 6 Plus" 38 | case "iPhone8,1": return "iPhone 6s" 39 | case "iPhone8,2": return "iPhone 6s Plus" 40 | case "iPhone9,1": return "iPhone 7 (CDMA)" 41 | case "iPhone9,3": return "iPhone 7 (GSM)" 42 | case "iPhone9,2": return "iPhone 7 Plus (CDMA)" 43 | case "iPhone9,4": return "iPhone 7 Plus (GSM)" 44 | case "iPhone10,1","iPhone10,4": return "iPhone 8" 45 | case "iPhone10,2","iPhone10,5": return "iPhone 8 Plus" 46 | 47 | case "iPhone10,3","iPhone10,6": return "iPhone X" 48 | case "iPhone11,8": return "iPhone XR" 49 | case "iPhone11,2": return "iPhone Xs" 50 | case "iPhone11,4","iPhone11,6": return "iPhone XsMax" 51 | case "iPhone12,1": return "iPhone 11" 52 | case "iPhone12,3": return "iPhone 11 Pro" 53 | case "iPhone12,5": return "iPhone 11 Pro Max" 54 | 55 | case "iPad1,1": return "iPad 1" 56 | case "iPad2,1": return "iPad 2" 57 | case "iPad2,2": return "iPad 2" 58 | case "iPad2,3": return "iPad 2" 59 | case "iPad2,4": return "iPad 2" 60 | case "iPad3,1": return "iPad 3rd" 61 | case "iPad3,2": return "iPad 3rd" 62 | case "iPad3,3": return "iPad 3rd" 63 | case "iPad3,4": return "iPad 4th" 64 | case "iPad3,5": return "iPad 4th" 65 | case "iPad3,6": return "iPad 4th" 66 | case "iPad6,11": return "iPad 5th" 67 | case "iPad6,12": return "iPad 5th" 68 | case "iPad7,5": return "iPad 6th" 69 | case "iPad7,6": return "iPad 6th" 70 | case "iPad7,11": return "iPad 7th" 71 | case "iPad7,12": return "iPad 7th" 72 | 73 | case "iPad2,5": return "iPad Mini" 74 | case "iPad2,6": return "iPad Mini" 75 | case "iPad2,7": return "iPad Mini" 76 | case "iPad4,4": return "iPad Mini 2" 77 | case "iPad4,5": return "iPad Mini 2" 78 | case "iPad4,6": return "iPad Mini 2" 79 | case "iPad4,7": return "iPad Mini 3" 80 | case "iPad4,8": return "iPad Mini 3" 81 | case "iPad4,9": return "iPad Mini 3" 82 | case "iPad5,1": return "iPad Mini 4" 83 | case "iPad5,2": return "iPad Mini 4" 84 | case "iPad11,1": return "iPad Mini 5" 85 | case "iPad11,2": return "iPad Mini 5" 86 | 87 | case "iPad4,1": return "iPad Air" 88 | case "iPad4,2": return "iPad Air" 89 | case "iPad4,3": return "iPad Air" 90 | case "iPad5,3": return "iPad Air 2" 91 | case "iPad5,4": return "iPad Air 2" 92 | case "iPad11,3": return "iPad Air 3rd" 93 | case "iPad11,4": return "iPad Air 3rd" 94 | 95 | case "iPad6,7": return "iPad Pro 12.9-inch 1st" 96 | case "iPad6,8": return "iPad Pro 12.9-inch 1st" 97 | case "iPad6,3": return "iPad Pro 9.7-inch" 98 | case "iPad6,4": return "iPad Pro 9.7-inch" 99 | case "iPad7,1": return "iPad Pro 12.9-inch 2nd" 100 | case "iPad7,2": return "iPad Pro 12.9-inch 2nd" 101 | case "iPad7,3": return "iPad Pro 10.5-inch" 102 | case "iPad7,4": return "iPad Pro 10.5-inch" 103 | case "iPad8,5": return "iPad Pro 12.9-inch 3rd" 104 | case "iPad8,6": return "iPad Pro 12.9-inch 3rd" 105 | case "iPad8,7": return "iPad Pro 12.9-inch 3rd" 106 | case "iPad8,8": return "iPad Pro 12.9-inch 3rd" 107 | case "iPad8,1": return "iPad Pro 11-inch" 108 | case "iPad8,2": return "iPad Pro 11-inch" 109 | case "iPad8,3": return "iPad Pro 11-inch" 110 | case "iPad8,4": return "iPad Pro 11-inch" 111 | 112 | case "iPod1,1": return "iPod Touch 1st" 113 | case "iPod2,1": return "iPod Touch 2nd" 114 | case "iPod3,1": return "iPod Touch 3rd" 115 | case "iPod4,1": return "iPod Touch 4th" 116 | case "iPod5,1": return "iPod Touch 5th" 117 | case "iPod7,1": return "iPod Touch 6th" 118 | 119 | case "i386", "x86_64": return "iPhone Simulator" 120 | 121 | default: return identifier 122 | } 123 | } 124 | } 125 | 126 | -------------------------------------------------------------------------------- /TQGO/Category/UIImage+YYCommon.swift: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // UIImage+YYCommon.swift 4 | // TQGO 5 | // 6 | // Created by YXY on 2019/10/23. 7 | // Copyright © 2019 Techwis. All rights reserved. 8 | // 9 | 10 | import Foundation 11 | import Photos 12 | import UIKit 13 | extension UIImage{ 14 | 15 | 16 | /// 旋转image 17 | /// - Parameter orientation: 旋转方向 18 | func imageRotation(orientation:UIImage.Orientation) ->UIImage{ 19 | 20 | var rotate: Double = 0.0; 21 | var rect : CGRect = CGRect.zero 22 | var translateX:CGFloat = 0; 23 | var translateY: CGFloat = 0; 24 | var scaleX :CGFloat = 1.0; 25 | var scaleY :CGFloat = 1.0; 26 | 27 | switch (orientation) { 28 | case .left: 29 | rotate = Double.pi/2; 30 | rect = CGRect(x: 0, y: 0, width: self.size.height, height: self.size.width) 31 | translateX = 0 32 | translateY = -(rect.size.width) 33 | scaleY = rect.size.width / rect.size.height 34 | scaleX = rect.size.height / rect.size.width 35 | break 36 | case .right: 37 | rotate = 3 * Double.pi/2; 38 | rect = CGRect(x: 0, y: 0, width: self.size.height, height: self.size.width) 39 | translateX = -(rect.size.height) 40 | translateY = 0 41 | scaleY = rect.size.width / rect.size.height 42 | scaleX = rect.size.height / rect.size.width 43 | break 44 | case .down: 45 | rotate = Double.pi; 46 | rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height) 47 | translateX = -(rect.size.width) 48 | translateY = -(rect.size.height) 49 | break 50 | default: 51 | rotate = 0.0; 52 | rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height) 53 | translateX = 0; 54 | translateY = 0; 55 | break; 56 | } 57 | 58 | UIGraphicsBeginImageContext(rect.size) 59 | let context:CGContext? = UIGraphicsGetCurrentContext() 60 | //做CTM变换 61 | context!.translateBy(x: 0, y: rect.size.height) 62 | context!.scaleBy(x: 1.0, y: -1.0) 63 | context!.rotate(by: CGFloat(rotate)); 64 | context!.translateBy(x: translateX, y: translateY); 65 | context!.scaleBy(x: scaleX, y: scaleY); 66 | //绘制图片 67 | context?.draw(self.cgImage!, in: CGRect(x: 0, y: 0, width: rect.size.width, height: rect.size.height), byTiling: false) 68 | let newPic:UIImage? = UIGraphicsGetImageFromCurrentImageContext(); 69 | UIGraphicsEndImageContext() 70 | return newPic! 71 | } 72 | 73 | 74 | /// 切圆角 75 | /// - Parameter radius: 角度 76 | func cornerRadius(radius: CGFloat) -> UIImage{ 77 | let rect = CGRect(origin: CGPoint.zero, size: size) 78 | let bezierPath = UIBezierPath(roundedRect:rect , cornerRadius: radius) 79 | UIGraphicsBeginImageContextWithOptions(rect.size, false, UIScreen.main.scale); 80 | let context = UIGraphicsGetCurrentContext() 81 | context?.addPath(bezierPath.cgPath); 82 | context?.clip() 83 | draw(in: rect) 84 | context?.drawPath(using: CGPathDrawingMode.fillStroke) 85 | let output : UIImage? = UIGraphicsGetImageFromCurrentImageContext() 86 | UIGraphicsEndImageContext() 87 | return output! 88 | 89 | 90 | } 91 | } 92 | 93 | 94 | extension UIImage{ 95 | 96 | /// 保存图片至相册 97 | /// - Parameter albumName: 相册名字 98 | func savePhoto(albumName:String) { 99 | var assetsID:String? 100 | PHPhotoLibrary.shared().performChanges({ 101 | assetsID = PHAssetCreationRequest.creationRequestForAsset(from: self).placeholderForCreatedAsset?.localIdentifier 102 | }) { (success, error) in 103 | if success == false {return} 104 | let assetCollection = self.createAssetCollection(albumName: albumName) 105 | PHPhotoLibrary.shared().performChanges({ 106 | guard assetsID != nil else{ 107 | return 108 | } 109 | let asset = PHAsset.fetchAssets(withLocalIdentifiers: [assetsID!], options: nil) 110 | guard assetCollection != nil else{ 111 | return 112 | } 113 | PHAssetCollectionChangeRequest(for:assetCollection!)?.addAssets(asset) 114 | }) { (success, error) in 115 | 116 | } 117 | } 118 | } 119 | 120 | /// 获取指定名字相册 存在直接返回 不存在则创建 121 | /// - Parameter albumName: 相册名字 122 | func createAssetCollection(albumName:String) -> PHAssetCollection? { 123 | let assetCollections = PHAssetCollection.fetchAssetCollections(with: PHAssetCollectionType.album, subtype: PHAssetCollectionSubtype.albumRegular, options: nil) 124 | for i in 0.. { 14 | var prepareForReuseKey: Int8 = 0 15 | if let prepareForReuseOB = objc_getAssociatedObject(base, &prepareForReuseKey) as? Observable { 16 | return prepareForReuseOB 17 | } 18 | let prepareForReuseOB = Observable.of( 19 | sentMessage(#selector(Base.prepareForReuse)).map { _ in } 20 | , deallocated) 21 | .merge() 22 | objc_setAssociatedObject(base, &prepareForReuseKey, prepareForReuseOB, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) 23 | 24 | return prepareForReuseOB 25 | } 26 | // 提供一个重用垃圾回收袋 27 | public var reuseBag: DisposeBag { 28 | MainScheduler.ensureExecutingOnScheduler() 29 | var prepareForReuseBag: Int8 = 0 30 | if let bag = objc_getAssociatedObject(base, &prepareForReuseBag) as? DisposeBag { 31 | return bag 32 | } 33 | 34 | let bag = DisposeBag() 35 | objc_setAssociatedObject(base, &prepareForReuseBag, bag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) 36 | 37 | _ = sentMessage(#selector(Base.prepareForReuse)) 38 | .subscribe(onNext: { [weak base] _ in 39 | let newBag = DisposeBag() 40 | guard let base = base else {return} 41 | objc_setAssociatedObject(base, &prepareForReuseBag, newBag, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) 42 | }) 43 | return bag 44 | } 45 | } 46 | 47 | /* 48 | 处理cell响应button事件时的 cell复用导致序列重复订阅响应 49 | 方式一: 50 | 重用响应prepareForReuse,只要发现我们的cell已发生重用,通过RxSwift就会接受到一个重用序列的响应,起到绑定效果 51 | 这里还合并了cell的销毁序列,毕竟cell都销毁了也就没有任何响应的意义 52 | cell.button.rx.tap.takeUntil(cell.rx.prepareForReuse) 53 | .subscribe(onNext: { () in 54 | print("点击了 \(indexPath)") 55 | }) 56 | 通过takeUntil限定了button的点击响应能力 57 | 58 | 59 | 方式二: 60 | cell.button.rx.tap 61 | .subscribe(onNext: { () in 62 | print("点击了 \(indexPath)") 63 | }) 64 | .disposed(by: cell.rx.reuseBag) 65 | 66 | 作者:Cooci_和谐学习_不急不躁 67 | 链接:https://www.jianshu.com/p/1c186afdae3b 68 | 来源:简书 69 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 70 | 71 | 方式三: 基类封装 72 | class LGCustomCell: UITableViewCell{ 73 | var disposeBag = DisposeBag() 74 | override func prepareForReuse() { 75 | super.prepareForReuse() 76 | 77 | disposeBag = DisposeBag() 78 | } 79 | } 80 | 81 | 作者:Cooci_和谐学习_不急不躁 82 | 链接:https://www.jianshu.com/p/1c186afdae3b 83 | 来源:简书 84 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 85 | */ 86 | -------------------------------------------------------------------------------- /TQGO/Category/UITextField+YYCommon.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITextField+YYCommon.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/10/23. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | extension UITextField{ 12 | 13 | func leftViewWithImgName(imgName:String , size:CGSize){ 14 | 15 | let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 60, height: self.frame.height)) 16 | let y = (self.frame.height - size.height)/2; 17 | let imgV = UIImageView(frame: CGRect(x: 0, y: y, width: size.width, height: size.height)) 18 | containerView.addSubview(imgV) 19 | self.leftViewMode = UITextField.ViewMode.always 20 | imgV.contentMode = UIView.ContentMode.left; 21 | imgV.image = kImage(name: imgName) 22 | self.leftView = containerView 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /TQGO/Category/UIView+Common.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Common.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/11. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | //MARK: Frame 13 | extension UIView { 14 | public var x: CGFloat{ 15 | get{ 16 | return self.frame.origin.x 17 | } 18 | set{ 19 | var r = self.frame 20 | r.origin.x = newValue 21 | self.frame = r 22 | } 23 | } 24 | 25 | public var y: CGFloat{ 26 | get{ 27 | return self.frame.origin.y 28 | } 29 | set{ 30 | var r = self.frame 31 | r.origin.y = newValue 32 | self.frame = r 33 | } 34 | } 35 | /// 右边界的x值 36 | public var rightX: CGFloat{ 37 | get{ 38 | return self.x + self.width 39 | } 40 | set{ 41 | var r = self.frame 42 | r.origin.x = newValue - frame.width 43 | self.frame = r 44 | } 45 | } 46 | /// 下边界的y值 47 | public var bottomY: CGFloat{ 48 | get{ 49 | return self.y + self.height 50 | } 51 | set{ 52 | var r = self.frame 53 | r.origin.y = newValue - frame.height 54 | self.frame = r 55 | } 56 | } 57 | 58 | public var centerX : CGFloat{ 59 | get{ 60 | return self.center.x 61 | } 62 | set{ 63 | self.center = CGPoint(x: newValue, y: self.center.y) 64 | } 65 | } 66 | 67 | public var centerY : CGFloat{ 68 | get{ 69 | return self.center.y 70 | } 71 | set{ 72 | self.center = CGPoint(x: self.center.x, y: newValue) 73 | } 74 | } 75 | 76 | public var width: CGFloat{ 77 | get{ 78 | return self.frame.width 79 | } 80 | set{ 81 | var r = self.frame 82 | r.size.width = newValue 83 | self.frame = r 84 | } 85 | } 86 | public var height: CGFloat{ 87 | get{ 88 | return self.frame.height 89 | } 90 | set{ 91 | var r = self.frame 92 | r.size.height = newValue 93 | self.frame = r 94 | } 95 | } 96 | 97 | 98 | public var origin: CGPoint{ 99 | get{ 100 | return self.frame.origin 101 | } 102 | set{ 103 | self.x = newValue.x 104 | self.y = newValue.y 105 | } 106 | } 107 | 108 | public var size: CGSize{ 109 | get{ 110 | return self.frame.size 111 | } 112 | set{ 113 | self.width = newValue.width 114 | self.height = newValue.height 115 | } 116 | } 117 | 118 | } 119 | 120 | extension UIView{ 121 | /// 获取视图根控制器 122 | func viewController() -> UIViewController? { 123 | var next: UIResponder? = self.next 124 | 125 | repeat { 126 | if (next?.isKind(of: UIViewController.self) == true) { 127 | return next as? UIViewController 128 | } 129 | next = next?.next 130 | }while (next != nil) 131 | return nil 132 | } 133 | // extension UIView { 134 | // //返回该view所在VC 135 | // func firstViewController() -> UIViewController? { 136 | // for view in sequence(first: self.superview, next: { $0?.superview }) { 137 | // if let responder = view?.next { 138 | // if responder.isKind(of: UIViewController.self){ 139 | // return responder as? UIViewController 140 | // } 141 | // } 142 | // } 143 | // return nil 144 | // } 145 | // } 146 | 147 | /// 截图 148 | func snapshotImage() -> UIImage { 149 | UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0) 150 | layer.render(in: UIGraphicsGetCurrentContext()!) 151 | let snap : UIImage? = UIGraphicsGetImageFromCurrentImageContext() 152 | UIGraphicsEndImageContext() 153 | return snap! 154 | } 155 | 156 | 157 | /// 可设置指定位置圆角 158 | /// - Parameter corners: 圆角位置 159 | /// - Parameter radius: 角度 160 | func cornerRadius(corners: UIRectCorner = .allCorners , radius: CGFloat) { 161 | layoutIfNeeded() 162 | let maskPath = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius)) 163 | let maskLayer = CAShapeLayer() 164 | maskLayer.frame = bounds 165 | maskLayer.path = maskPath.cgPath 166 | layer.mask = maskLayer 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /TQGO/Category/UIViewController+RXCommon.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+RXCommon.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/11/5. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension Reactive where Base: UIViewController { 13 | /// 用于 `startAnimating()` 和 `stopAnimating()` 方法的 binder 14 | public var isLoadingAnimating: Binder { 15 | return Binder(self.base, binding: { (vc, active) in 16 | vc.loadingAnimating(isAnimating: active) 17 | }) 18 | } 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /TQGO/Category/UIViewController+YXYCommon.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+YXYCommon.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/11/5. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIViewController{ 13 | 14 | func loadingAnimating(isAnimating:Bool) { 15 | isAnimating ? self.view.makeToastActivity(ToastPosition.center) : self.view.hideToastActivity() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TQGO/Class/Base/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RealmSwift 11 | 12 | @UIApplicationMain 13 | class AppDelegate: UIResponder, UIApplicationDelegate { 14 | 15 | var window: UIWindow? 16 | 17 | internal func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // 配置Realm 19 | RealmManager.config() 20 | window = UIWindow(frame:UIScreen.main.bounds) 21 | window?.rootViewController = ProjectTabBarVC(); 22 | window?.makeKeyAndVisible() 23 | 24 | // 配置Toast显示位置 25 | ToastManager.shared.position = .center 26 | return true 27 | } 28 | 29 | func applicationWillResignActive(_ application: UIApplication) { 30 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 31 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 32 | } 33 | 34 | func applicationDidEnterBackground(_ application: UIApplication) { 35 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 36 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 37 | } 38 | 39 | func applicationWillEnterForeground(_ application: UIApplication) { 40 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 41 | } 42 | 43 | func applicationDidBecomeActive(_ application: UIApplication) { 44 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 45 | } 46 | 47 | func applicationWillTerminate(_ application: UIApplication) { 48 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /TQGO/Class/Base/BaseNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseNavigationController.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BaseNavigationController: UINavigationController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | } 17 | 18 | override func didReceiveMemoryWarning() { 19 | super.didReceiveMemoryWarning() 20 | // Dispose of any resources that can be recreated. 21 | } 22 | 23 | override func pushViewController(_ viewController: UIViewController, animated: Bool) { 24 | if(viewControllers.count > 0){ 25 | // 隐藏底部tabBar 26 | viewController.hidesBottomBarWhenPushed = true 27 | } 28 | super.pushViewController(viewController, animated: animated) 29 | } 30 | 31 | override func popViewController(animated: Bool) -> UIViewController? { 32 | //判断即将到栈底 33 | if (viewControllers.count == 0) { 34 | //显示自定义的tabBar 35 | tabBarController?.tabBar.isHidden = false; 36 | } 37 | // pop出栈 38 | return super.popViewController(animated: animated) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /TQGO/Class/Base/BaseTabBarVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTabBarVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BaseTabBarVC: UITabBarController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | // Do any additional setup after loading the view. 17 | } 18 | 19 | override func didReceiveMemoryWarning() { 20 | super.didReceiveMemoryWarning() 21 | // Dispose of any resources that can be recreated. 22 | } 23 | 24 | 25 | /* 26 | // MARK: - Navigation 27 | 28 | // In a storyboard-based application, you will often want to do a little preparation before navigation 29 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 30 | // Get the new view controller using segue.destinationViewController. 31 | // Pass the selected object to the new view controller. 32 | } 33 | */ 34 | 35 | } 36 | -------------------------------------------------------------------------------- /TQGO/Class/Base/BaseTableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseTableView.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/4/9. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BaseTableView: UITableView { 12 | 13 | /* 14 | // Only override draw() if you perform custom drawing. 15 | // An empty implementation adversely affects performance during animation. 16 | override func draw(_ rect: CGRect) { 17 | // Drawing code 18 | } 19 | */ 20 | 21 | 22 | } 23 | 24 | // 实现识别多手势代理 25 | extension BaseTableView:UIGestureRecognizerDelegate{ 26 | func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { 27 | return true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TQGO/Class/Base/BaseVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BaseVC: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | // Do any additional setup after loading the view. 17 | } 18 | 19 | override func didReceiveMemoryWarning() { 20 | super.didReceiveMemoryWarning() 21 | // Dispose of any resources that can be recreated. 22 | } 23 | 24 | override func viewWillAppear(_ animated: Bool) { 25 | super.viewWillAppear(animated) 26 | if title == "我的" || title == "联通专区" { 27 | navigationController?.navigationBar.isHidden = true 28 | } 29 | } 30 | 31 | override func viewDidDisappear(_ animated: Bool) { 32 | super.viewDidDisappear(animated) 33 | if title == "我的" || title == "联通专区" { 34 | navigationController?.navigationBar.isHidden = false 35 | } 36 | } 37 | 38 | /* 39 | // MARK: - Navigation 40 | 41 | // In a storyboard-based application, you will often want to do a little preparation before navigation 42 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 43 | // Get the new view controller using segue.destinationViewController. 44 | // Pass the selected object to the new view controller. 45 | } 46 | */ 47 | 48 | } 49 | -------------------------------------------------------------------------------- /TQGO/Class/Base/Common.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Common.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/12/13. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Contacts 11 | class Common { 12 | 13 | /// 通讯录授权 14 | static func getContactsAuthStatus() -> Bool { 15 | var authorizedMsg :String? 16 | var isAuthorized = false 17 | 18 | switch CNContactStore.authorizationStatus(for: CNEntityType.contacts) { 19 | case CNAuthorizationStatus.notDetermined:do { 20 | authorizedMsg = "用户未确定是否授权" 21 | let contactStore = CNContactStore() 22 | let semaphore = DispatchSemaphore(value: 0) 23 | contactStore.requestAccess(for: CNEntityType.contacts) { (granted, error) in 24 | if (error != nil) { 25 | isAuthorized = false 26 | DLog("contact 授权 error:\(String(describing: error))"); 27 | }else if(granted == false){ 28 | isAuthorized = false 29 | }else { 30 | isAuthorized = true 31 | } 32 | semaphore.signal() 33 | } 34 | semaphore.wait() 35 | } 36 | case CNAuthorizationStatus.restricted: 37 | authorizedMsg = "iOS 设备上一些许可配置阻止程序与通讯录数据库进行交互" 38 | isAuthorized = false 39 | case CNAuthorizationStatus.denied: 40 | authorizedMsg = "用户明确的拒绝了你的程序对通讯录的访问" 41 | isAuthorized = false 42 | case CNAuthorizationStatus.authorized: 43 | authorizedMsg = "default 未知信息" 44 | isAuthorized = true 45 | default: 46 | authorizedMsg = "default 未知信息" 47 | isAuthorized = false 48 | } 49 | DLog("在iOS 9及以上设备上,通讯录授权信息:\(authorizedMsg!)\(isAuthorized))"); 50 | return isAuthorized 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /TQGO/Class/Base/ProjectTabBarVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ProjectTabBarVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ProjectTabBarVC: UITabBarController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | 16 | let promVC = PromotionVC() 17 | let creditPay = CreditPayVC() 18 | let pcVC = PersonalCenterVC() 19 | let unicomAreaVC = UnicomAreaVC() 20 | let shopCartVC = ShopCartVC() 21 | 22 | let baseNav_1 = BaseNavigationController(rootViewController: promVC) 23 | let baseNav_2 = BaseNavigationController(rootViewController: unicomAreaVC) 24 | let baseNav_3 = BaseNavigationController(rootViewController: creditPay) 25 | let baseNav_4 = BaseNavigationController(rootViewController: shopCartVC) 26 | let baseNav_5 = BaseNavigationController(rootViewController: pcVC) 27 | 28 | let barItem_1 = UITabBarItem(title: "促销", image: UIImage(named:"icon_tabbar_default_promotion"), selectedImage: UIImage(named: "icon_tabbar_selected_promotion")) 29 | let barItem_2 = UITabBarItem(title: "联通专区", image: UIImage(named:"icon_tabbar_default_promotion"), selectedImage: UIImage(named: "icon_tabbar_selected_promotion")) 30 | let barItem_3 = UITabBarItem(title: "信用付", image: UIImage(named:"icon_tabbar_default_credit"), selectedImage: UIImage(named: "icon_tabbar_selected_credit")) 31 | let barItem_4 = UITabBarItem(title: "购物车", image: UIImage(named:"icon_tabbar_default_personalCenter"), selectedImage: UIImage(named: "icon_tabbar_selected_personalCenter")) 32 | let barItem_5 = UITabBarItem(title: "我的", image: UIImage(named:"icon_tabbar_default_personalCenter"), selectedImage: UIImage(named: "icon_tabbar_selected_personalCenter")) 33 | 34 | baseNav_1.tabBarItem = barItem_1 35 | baseNav_2.tabBarItem = barItem_2 36 | baseNav_3.tabBarItem = barItem_3 37 | baseNav_4.tabBarItem = barItem_4 38 | baseNav_5.tabBarItem = barItem_5 39 | viewControllers = [baseNav_1,baseNav_2,baseNav_3,baseNav_4,baseNav_5] 40 | 41 | } 42 | 43 | override func didReceiveMemoryWarning() { 44 | super.didReceiveMemoryWarning() 45 | // Dispose of any resources that can be recreated. 46 | } 47 | 48 | 49 | /* 50 | // MARK: - Navigation 51 | 52 | // In a storyboard-based application, you will often want to do a little preparation before navigation 53 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 54 | // Get the new view controller using segue.destinationViewController. 55 | // Pass the selected object to the new view controller. 56 | } 57 | */ 58 | 59 | } 60 | -------------------------------------------------------------------------------- /TQGO/Class/CreditPayModule/Controller/CreditPayVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CreditPayVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/10/11. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CreditPayVC: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | self.title = "信用付" 16 | view.backgroundColor = .white 17 | // Do any additional setup after loading the view. 18 | } 19 | 20 | override func didReceiveMemoryWarning() { 21 | super.didReceiveMemoryWarning() 22 | // Dispose of any resources that can be recreated. 23 | } 24 | 25 | 26 | /* 27 | // MARK: - Navigation 28 | 29 | // In a storyboard-based application, you will often want to do a little preparation before navigation 30 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 31 | // Get the new view controller using segue.destinationViewController. 32 | // Pass the selected object to the new view controller. 33 | } 34 | */ 35 | 36 | } 37 | -------------------------------------------------------------------------------- /TQGO/Class/LoginRegisterModule/Controller/RegisterVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RegisterVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/10/28. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class RegisterVC: UIViewController { 12 | 13 | let registerVM = RegisterVM() 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | title = "注册" 18 | view.backgroundColor = .white 19 | 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /TQGO/Class/LoginRegisterModule/ViewModel/LoginVM.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoginVM.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/10/29. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | 13 | class LoginVM { 14 | 15 | 16 | let phoneNumOB : Observable 17 | var phoneNumStrOB : Observable 18 | let passwordOB : Observable 19 | let passwordStrOB : Observable 20 | let securityCodeOB: Observable 21 | let securityCodeStrOB: Observable 22 | let loginEnableOB: Observable 23 | var requestErrorOB: ReplaySubject = ReplaySubject.create(bufferSize: 1) 24 | let loading : PublishSubject = PublishSubject() 25 | var disposeBag :DisposeBag? 26 | 27 | init(phoneNum: Observable,password: Observable,securityCode:Observable,segment:Observable) { 28 | phoneNumStrOB = phoneNum.map{ 29 | $0.count > kLimitPhone ? $0.substring(to: kLimitPhone) : $0 30 | }.share(replay: 1) 31 | 32 | phoneNumOB = phoneNum 33 | .map { $0.count == kLimitPhone && $0.isMobileNumberClassification() } 34 | .share(replay: 1) 35 | 36 | passwordStrOB = password 37 | .map { $0.count > kLimitPassword ? $0.substring(to: kLimitPassword) : $0 } 38 | .share(replay: 1) 39 | 40 | passwordOB = password 41 | .map { $0.count < kLimitPassword && $0.count >= 8 } 42 | .share(replay: 1) 43 | 44 | securityCodeStrOB = securityCode.map{ 45 | $0.count > kLimitSecurityCode ? $0.substring(to: kLimitSecurityCode) : $0 46 | }.share(replay: 1) 47 | 48 | securityCodeOB = securityCode 49 | .map { $0.count == kLimitSecurityCode} 50 | .share(replay: 1) 51 | 52 | let loginPasswordEnableOB = Observable.combineLatest(phoneNumOB, passwordOB,segment) { $0 && $1 && ($2 == 0) } 53 | .share(replay: 1) 54 | let loginsecurityCodeEnableOB = Observable.combineLatest(phoneNumOB, securityCodeOB,segment) { $0 && $1 && ($2 == 1)} 55 | .share(replay: 1) 56 | loginEnableOB = Observable.combineLatest(loginPasswordEnableOB, loginsecurityCodeEnableOB) { $0 || $1 }.share(replay: 1) 57 | } 58 | 59 | //MARK: 登录请求 60 | func loginRequest() { 61 | var phoneNo = "" 62 | var loginPwd = "" 63 | loading.onNext(true) 64 | phoneNumStrOB.subscribe(onNext: { (str) in 65 | phoneNo = str 66 | }).disposed(by: disposeBag!) 67 | passwordStrOB.subscribe(onNext: { (str) in 68 | loginPwd = str 69 | }).disposed(by: disposeBag!) 70 | 71 | let param = ["phoneNo":phoneNo,"loginPwd":loginPwd.md5,"loginType":"0"] 72 | NetworkManager.loadData(api: APIInterfaceLoginRegister.userLogin(params:param), completionClosure: {[weak self] (response) -> (Void) in 73 | 74 | self?.loading.onNext(false) 75 | 76 | let flag = response.returnCode == KErrorCode.KErrorCode_SUCCESSE.rawValue ? true : false 77 | self?.requestErrorOB.onNext(flag ? APIError.apiError_done : APIError.apiError_serverMessage(response.returnMsg ?? "")) 78 | guard flag == true else{return} 79 | // 存储用户信息 80 | guard let model = UserInfo.deserialize(from: response.toJSONString(), designatedPath: "data") else {return} 81 | let realm = RealmManager.instance 82 | try? realm.write { 83 | realm.add(model, update: Realm.UpdatePolicy.all) 84 | } 85 | 86 | }) {[weak self] (fail) -> (Void) in 87 | // 因未配置真正请求 所以请求必定失败 以下操作为模拟请求成功 88 | self?.loading.onNext(false) 89 | self?.requestErrorOB.onNext(APIError.apiError_done) 90 | 91 | 92 | // 此处为真正的请求失败后需做的做操 93 | // self?.loading.onNext(false) 94 | // self?.requestErrorOB.onNext(APIError.apiError_serverMessage("网络异常请重试")) 95 | } 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /TQGO/Class/LoginRegisterModule/ViewModel/RegisterVM.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewModel.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/10/28. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | class RegisterVM { 13 | let phoneNumOB = Observable.create { (observer) -> Disposable in 14 | 15 | 16 | return Disposables.create() 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TQGO/Class/PersonalCenterModule/Controller/PersonalCenterVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PersonalCenterVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PersonalCenterVC: BaseVC { 12 | 13 | lazy var tableView:UITableView = { 14 | let tableView = UITableView() 15 | tableView.delegate = self 16 | tableView.dataSource = self 17 | tableView.register(MyHeaderCell.self, forCellReuseIdentifier:"k") 18 | tableView.separatorStyle = .none 19 | view.addSubview(tableView) 20 | tableView.snp.makeConstraints { (make) in 21 | make.edges.equalToSuperview() 22 | make.top.equalToSuperview().offset(-kNabBarHeight) 23 | } 24 | return tableView 25 | }() 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | title = "我的" 30 | view.backgroundColor = .white 31 | tableView.backgroundColor = .white 32 | 33 | 34 | } 35 | 36 | override func didReceiveMemoryWarning() { 37 | super.didReceiveMemoryWarning() 38 | // Dispose of any resources that can be recreated. 39 | } 40 | 41 | } 42 | 43 | 44 | extension PersonalCenterVC:UITableViewDataSource,UITableViewDelegate{ 45 | 46 | func numberOfSections(in tableView: UITableView) -> Int { 47 | return 1 48 | } 49 | 50 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 51 | return 1 52 | } 53 | 54 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 55 | 56 | return kSafeAreaBottomHeight > 0 ? 150+24.0 :150.0 57 | } 58 | 59 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 60 | 61 | return tableView.dequeueReusableCell(withIdentifier: "k", for: indexPath) 62 | } 63 | 64 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 65 | 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /TQGO/Class/PersonalCenterModule/Model/UserInfo.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UserInfo.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RealmSwift 11 | 12 | enum kUnicomStatus:NSInteger { 13 | case kUnicomStatus_open = 0 ,// 开通 14 | kUnicomStatus_unopen // 未开通 15 | } 16 | 17 | class UserInfo:Object,HandyJSON { 18 | 19 | @objc dynamic var userStatus:String? // 用户状态 1:银卡 2:金卡 20 | @objc dynamic var userNo:String?// 用户号 21 | @objc dynamic var phoneNo:String? // 手机号 22 | @objc dynamic var integral:String?// 余额 23 | @objc dynamic var currency:String?// T币额度 24 | @objc dynamic var unicomeStatus:String?// 0:开启联通专区 1:未开启联通专区 25 | @objc dynamic var realType:String?// 实名状态 0:未认证 1:认证 26 | @objc dynamic var userToken:String? 27 | @objc dynamic var firstBuyStatus:String?//0: 未人脸识别 1: 已做过人脸识别 28 | @objc dynamic var receiveStatus:String?// 0 未领取 1:已领取 礼包领取状态 29 | @objc dynamic var openCreditPayStatus:String?// 0: 未开通 1: 已开通 信用付 30 | @objc dynamic var creditUsableMoney:String?// 授信可用额度 31 | @objc dynamic var creditStatus:String?// 授信状态 0.失败。1成功。2,未处理 3,处理中 4.授信过期 5待人工审核 32 | @objc dynamic var forzenStatus:String?// 冻结状态 0:冻结 1:未冻结 33 | @objc dynamic var userName:String?// 用户姓名 34 | @objc dynamic var idNo:String?// 身份证号 35 | @objc dynamic var totalCreditAmount:String?// 总额度 36 | @objc dynamic var alreadyUseAmount:String?// 已使用额度 37 | @objc dynamic var forzenCreditAmount:String?// 冻结额度 38 | @objc dynamic var thisMonthRefundAmount:String?// 本月应还 39 | @objc dynamic var nextMonthRefundAmount:String?//下月应还 40 | @objc dynamic var waitPayOrderNums:String?//代付款订单数 41 | @objc dynamic var lastMonthLeftAmout:String?// 上月未还账单金额 42 | @objc dynamic var maxRefundAmount:String?//最大还款金额 43 | 44 | 45 | override class func primaryKey()->String?{ 46 | return "userNo"; 47 | } 48 | 49 | //重写 Object.ignoredProperties() 可以防止 Realm 存储数据模型的某个属性 50 | // override static func ignoredProperties() -> [String] { 51 | // return ["tempID"] 52 | // } 53 | } 54 | 55 | extension UserInfo{ 56 | //MARK: 清空用户信息 57 | static func clearUserInfo(userNo:String?){ 58 | let realm = RealmManager.instance 59 | realm.delete(UserInfo.instance!) 60 | } 61 | 62 | static var instance:UserInfo? = { 63 | let realm = RealmManager.instance 64 | return realm.objects(UserInfo.self).last 65 | }() 66 | 67 | } 68 | -------------------------------------------------------------------------------- /TQGO/Class/PersonalCenterModule/View/MyHeaderCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MyHeaderCell.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/10/21. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MyHeaderCell: UITableViewCell { 12 | let disposeBag = DisposeBag() 13 | 14 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 15 | super.init(style: style, reuseIdentifier: reuseIdentifier) 16 | contentView.backgroundColor = KCOLOR_Base.font_blue 17 | setupView() 18 | } 19 | 20 | required init?(coder: NSCoder) { 21 | fatalError("init(coder:) has not been implemented") 22 | } 23 | 24 | func setupView() { 25 | let iconImgV = UIImageView() 26 | iconImgV.image = UIImage(named: "icon_header") 27 | contentView.addSubview(iconImgV) 28 | iconImgV.snp.makeConstraints { (make) in 29 | make.left.equalToSuperview().offset(15) 30 | make.bottom.equalToSuperview().offset(-32) 31 | } 32 | 33 | let loginBtn = UIButton(type: UIButton.ButtonType.custom) 34 | loginBtn.isHidden = false 35 | loginBtn.setTitle("立即登录", for: UIControl.State.normal) 36 | loginBtn.setImage(kImage(name: "icon_arrow_right_white"), for: UIControl.State.normal) 37 | loginBtn.titleLabel?.font = kFont(size: 17) 38 | loginBtn.setTitleColor(.white, for: UIControl.State.normal) 39 | loginBtn.rx.tap.subscribe(onNext: {[weak self] (make) in 40 | self?.viewController()?.navigationController?.pushViewController(LoginVC(), animated: true) 41 | }).disposed(by: disposeBag) 42 | 43 | contentView.addSubview(loginBtn) 44 | loginBtn.snp.makeConstraints { (make) in 45 | 46 | make.left.equalTo(iconImgV.snp_rightMargin).offset(16) 47 | make.centerY.equalTo(iconImgV) 48 | } 49 | loginBtn.layoutButtonWithEdgeInsetsStyle(style: YXYButtonEdgeInsetsStyle.YXYButtonEdgeInsetsStyleRight, imageTitleSpace: 6) 50 | 51 | } 52 | 53 | override func setSelected(_ selected: Bool, animated: Bool) { 54 | super.setSelected(selected, animated: animated) 55 | 56 | // Configure the view for the selected state 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /TQGO/Class/PromotionModule/Controller/GoodsDetailVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GoodsDetailVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/1/15. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol GoodsDetailDelegate { 12 | func callback() 13 | } 14 | 15 | class GoodsDetailVC: UIViewController { 16 | 17 | var delegate:GoodsDetailDelegate? 18 | 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | view.backgroundColor = .white 23 | title = "商品详情" 24 | self.delegate?.callback() 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /TQGO/Class/PromotionModule/Controller/PromotionSubVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PromotionSubVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/3/22. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | 12 | let kPromotionSubCell_id = "kPromotionSubCell_id" 13 | 14 | class PromotionSubVC: UIViewController { 15 | 16 | var promotionModel:PromotionModel? 17 | var menuCode:String? 18 | var taskId :String? 19 | var vcCanScroll = false 20 | 21 | lazy var collectionView: UICollectionView = { 22 | 23 | var layout = UICollectionViewFlowLayout() 24 | 25 | var height:CGFloat = 213+34+8+12; 26 | if(kScreenWidth <= 320) { 27 | height = 213-28+40; 28 | }else if(kScreenWidth >= 414){ 29 | height = 213+34+20+8; 30 | } 31 | layout.itemSize = CGSize(width: (kScreenWidth-15*3)/2.0, height: height) 32 | layout.minimumInteritemSpacing = 15 33 | layout.minimumLineSpacing = 0 34 | layout.sectionInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15); 35 | 36 | let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: view.width, height: kScreenHeight - kSafeAreaTopHeight - kSafeAreaBottomHeight), collectionViewLayout: layout) 37 | collectionView.backgroundColor = .white 38 | collectionView.bounces = false; 39 | collectionView.delegate = self 40 | collectionView.dataSource = self 41 | collectionView.register(PromotionSubCell.self, forCellWithReuseIdentifier:kPromotionSubCell_id) 42 | 43 | return collectionView 44 | }() 45 | 46 | override func viewDidLoad() { 47 | super.viewDidLoad() 48 | view.backgroundColor = .white 49 | view.addSubview(collectionView) 50 | loadData() 51 | } 52 | /// 请求数据 53 | func loadData() { 54 | let params = ["userNo": "01645200948672000591", 55 | "area":"110000", 56 | "taskId":taskId ?? "a3e17811155f699c451b", 57 | "menuCode": menuCode!] 58 | NetworkManager.loadData(api: APIInterfacePromotion.queryPromoIndex(params:params ), completionClosure: { [weak self] (respone) -> (Void) in 59 | 60 | if respone.returnCode == KErrorCode.KErrorCode_SUCCESSE.rawValue{ 61 | self!.promotionModel = respone.data as? PromotionModel 62 | self!.collectionView.reloadData() 63 | }else{ 64 | self!.readDataFromLocal() 65 | } 66 | }) {[weak self] (fail) -> (Void) in 67 | self!.readDataFromLocal() 68 | } 69 | } 70 | 71 | // 读取本地数据 72 | func readDataFromLocal(){ 73 | DispatchQueue.global().async { 74 | let tempArr = JSONDeserializer.deserializeModelArrayFrom(array: "goods\(self.menuCode!)".getLocalPlistData()) as! Array 75 | let tempModel = PromotionModel() 76 | tempModel.activityGoods = tempArr 77 | self.promotionModel = tempModel 78 | DispatchQueue.main.async { 79 | self.collectionView.reloadData() 80 | } 81 | } 82 | } 83 | 84 | } 85 | 86 | extension PromotionSubVC:UICollectionViewDelegate,UICollectionViewDataSource{ 87 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 88 | return self.promotionModel?.activityGoods?.count ?? 0 89 | } 90 | 91 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 92 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kPromotionSubCell_id, for: indexPath) as! PromotionSubCell 93 | let model = self.promotionModel?.activityGoods?[indexPath.row] 94 | cell.model = model 95 | return cell 96 | } 97 | 98 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 99 | navigationController?.pushViewController(GoodsDetailVC(), animated: true) 100 | } 101 | } 102 | 103 | extension PromotionSubVC{ 104 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 105 | if vcCanScroll == false { 106 | scrollView.contentOffset = CGPoint(x: 0, y: 0) 107 | } 108 | if scrollView.contentOffset.y <= 0 { 109 | vcCanScroll = false 110 | scrollView.contentOffset = CGPoint(x: 0, y: 0) 111 | //到顶通知父视图改变状态 112 | NotificationCenter.default.post(name:.kLeaveTop, object: nil) 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /TQGO/Class/PromotionModule/Controller/PromotionVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PromotionVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import RealmSwift 11 | import MJRefresh 12 | 13 | private let kSlideViewH = (kScreenWidth * 135/375) 14 | private let kPageViewCell_id = "kPageViewCell_id" 15 | private let kADCell_id = "kADCell_id" 16 | 17 | class PromotionVC: UIViewController { 18 | var promotionModel:PromotionModel? 19 | var pageView:YXYPageContentView? 20 | var menuTitleView:YXYMenuTitleView? 21 | var canScroll = true 22 | 23 | lazy var tableView:BaseTableView = { 24 | let tableView = BaseTableView(frame: view.bounds, style: UITableView.Style.plain) 25 | tableView.backgroundColor = .white 26 | tableView.delegate = self 27 | tableView.dataSource = self 28 | tableView.bounces = true 29 | tableView.showsVerticalScrollIndicator = false 30 | tableView.register(ADCell.self, forCellReuseIdentifier: kADCell_id) 31 | tableView.register(UITableViewCell.self, forCellReuseIdentifier: kPageViewCell_id) 32 | view.addSubview(tableView) 33 | return tableView 34 | }() 35 | 36 | override func viewDidLoad() { 37 | super.viewDidLoad() 38 | view.backgroundColor = .white 39 | title = "促销" 40 | 41 | kNotife.addObserver(self, selector: #selector(changeScrollStatus), name: .kLeaveTop, object: nil) 42 | // navigationController?.navigationBar.isTranslucent = false 43 | // if #available(iOS 13.0, *) { 44 | // navigationController?.navigationBar.showsLargeContentViewer = false 45 | // } else { 46 | // // Fallback on earlier versions 47 | // } 48 | // tableView.mj_header?.ignoredScrollViewContentInsetTop = 164 49 | tableView.backgroundColor = .white 50 | // tableView.mj_header = MJRefreshNormalHeader(refreshingBlock: { 51 | // [unowned self] in 52 | // self.tableView.mj_header?.endRefreshing() 53 | // }) 54 | loadData() 55 | } 56 | 57 | func loadData() { 58 | var params = ["area":"110000", 59 | "taskId": "", 60 | "menuCode": ""] 61 | if let userNo = UserInfo.instance?.userNo { 62 | params.updateValue(userNo, forKey: kUserNo) 63 | } 64 | 65 | NetworkManager.loadData(api: APIInterfacePromotion.queryPromoIndex(params:params), completionClosure: { [weak self] (respone) -> (Void) in 66 | if respone.returnCode == KErrorCode.KErrorCode_SUCCESSE.rawValue{ 67 | if let model = PromotionModel.deserialize(from: respone.toJSONString(), designatedPath: "data") { 68 | self?.promotionModel = model 69 | self?.tableView.reloadData() 70 | } 71 | }else{ 72 | self?.readDataFromLocal() 73 | } 74 | }) {[weak self] (fail) -> (Void) in 75 | self?.readDataFromLocal() 76 | } 77 | } 78 | 79 | /// 子线程读取本地数据 主线程刷新 80 | func readDataFromLocal(){ 81 | let tempModel = PromotionModel() 82 | DispatchQueue.global().async { 83 | let tempArr = JSONDeserializer.deserializeModelArrayFrom(array: "menu".getLocalPlistData()) as! Array 84 | tempModel.menus = tempArr 85 | let tempArrBanner = JSONDeserializer.deserializeModelArrayFrom(array: "homeBanner".getLocalPlistData()) as! Array 86 | tempModel.banners = tempArrBanner 87 | self.promotionModel = tempModel 88 | DispatchQueue.main.async { 89 | self.tableView.reloadData() 90 | } 91 | } 92 | } 93 | 94 | deinit { 95 | NotificationCenter.default.removeObserver(self) 96 | } 97 | override func didReceiveMemoryWarning() { 98 | super.didReceiveMemoryWarning() 99 | // Dispose of any resources that can be recreated. 100 | } 101 | 102 | } 103 | 104 | extension PromotionVC:UITableViewDelegate,UITableViewDataSource{ 105 | 106 | func numberOfSections(in tableView: UITableView) -> Int { 107 | return 2 108 | } 109 | 110 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 111 | if section == 0{ 112 | return 1 113 | }else{ 114 | return 1 115 | } 116 | 117 | } 118 | 119 | func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { 120 | if section == 0{ 121 | return 0 122 | }else{ 123 | return 40 124 | } 125 | } 126 | 127 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 128 | if indexPath.section == 0 { 129 | return kSlideViewH 130 | }else{ 131 | return kScreenHeight 132 | } 133 | } 134 | 135 | func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { 136 | if section == 0 { 137 | return nil 138 | } 139 | var titleArr = [String]() 140 | promotionModel?.menus?.forEach({ (menu) in 141 | if let title = menu.name{ 142 | titleArr.append(title) 143 | } 144 | }) 145 | menuTitleView = YXYMenuTitleView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 40), titleArr: titleArr) 146 | menuTitleView!.menuMoveDelegate = self 147 | menuTitleView!.indicatorType = .YXYIndicatorTypeCustom 148 | menuTitleView!.indicatorExtension = 30; 149 | 150 | return menuTitleView 151 | } 152 | 153 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 154 | if indexPath.section == 0 { 155 | let adCell = tableView.dequeueReusableCell(withIdentifier: kADCell_id, for: indexPath) as! ADCell 156 | if self.promotionModel?.banners?.isEmpty == false{ 157 | adCell.setSlideArr(banner: self.promotionModel?.banners) 158 | } 159 | 160 | return adCell 161 | }else{ 162 | let contentCell = tableView.dequeueReusableCell(withIdentifier:kPageViewCell_id , for: indexPath) 163 | var subVCArr = [PromotionSubVC]() 164 | _ = promotionModel?.menus?.map({ (model) in 165 | let vc = PromotionSubVC() 166 | vc.title = model.code 167 | vc.menuCode = model.code 168 | vc.taskId = promotionModel?.promos?.first?.taskId 169 | subVCArr.append(vc) 170 | }) 171 | pageView?.removeFromSuperview() 172 | pageView = YXYPageContentView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: kScreenHeight), subVCArr:subVCArr, parentVC: self) 173 | contentCell.contentView.addSubview(pageView!) 174 | pageView!.pageContenViewDelegate = self 175 | return contentCell 176 | } 177 | } 178 | } 179 | 180 | extension PromotionVC:YXYMenuMoveProtocol,YXYContenViewProtocol{ 181 | func pageContenViewDidScroll(fromIndex: NSInteger, toIndex: NSInteger) { 182 | menuTitleView!.selectIndex = toIndex 183 | } 184 | 185 | func menuMoveProtocol(formIndex: NSInteger, toIndex: NSInteger) { 186 | pageView!.contentViewCurrentIndex = toIndex 187 | } 188 | } 189 | 190 | 191 | extension PromotionVC{ 192 | @objc func changeScrollStatus(){ 193 | canScroll = true; 194 | _ = pageView?.subVCArr.map({ (vc) in 195 | vc.vcCanScroll = false 196 | }) 197 | } 198 | 199 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 200 | 201 | let bottomCellOffset = tableView.rect(forSection: 1).origin.y 202 | if (scrollView.contentOffset.y) >= bottomCellOffset { 203 | scrollView.contentOffset = CGPoint(x: 0, y: bottomCellOffset) 204 | if (canScroll) { 205 | canScroll = false; 206 | _ = pageView?.subVCArr.map({ (vc) in 207 | vc.vcCanScroll = true 208 | }) 209 | } 210 | }else{ 211 | if (!canScroll) { 212 | //子视图没到顶部 213 | scrollView.contentOffset = CGPoint(x: 0, y: bottomCellOffset) 214 | } 215 | } 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /TQGO/Class/PromotionModule/Model/MenuModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MenuModel.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/3/20. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | class MenuModel: HandyJSON { 11 | var code:String? 12 | var name:String? 13 | required init() {} 14 | } 15 | -------------------------------------------------------------------------------- /TQGO/Class/PromotionModule/Model/PromosModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PromosModel.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/3/20. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | class PromosModel: HandyJSON { 11 | var taskId:String? 12 | var taskTitleName:String? 13 | var taskTagName:String? 14 | required init() {} 15 | } 16 | 17 | -------------------------------------------------------------------------------- /TQGO/Class/PromotionModule/Model/PromotionModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PromotionModel.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/3/20. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | //import Foundation 10 | 11 | class PromotionModel: HandyJSON { 12 | var promos:Array? 13 | var banners:Array? 14 | var menus:Array? 15 | var activityGoods:Array? 16 | required init() {} 17 | 18 | func mapping(mapper: HelpingMapper) { 19 | // mapper.specify(property: &promos, name: "id") 20 | // mapper <<< self.promos <-- "id" 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /TQGO/Class/PromotionModule/View/PromotionSubCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PromotionSubCell.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/3/22. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class PromotionSubCell: UICollectionViewCell { 12 | 13 | var icon:UIImageView! 14 | var flagTwoLabel:UILabel! 15 | var goodsNameLabel:UILabel! 16 | var flagOneLabel:UILabel! 17 | var specialPriceLabel:UILabel! 18 | var buyGoodsBtn:UIButton! 19 | var officialPriceLabel:UILabel! 20 | var salesCountLabel:UILabel! 21 | 22 | var model:GoodsModel?{ 23 | didSet{ 24 | 25 | icon.kf.setImage(with: URL(string: (model?.imgUrl ?? "")), placeholder: UIImage.init(named: "icon_goods_default"), options: nil, progressBlock: nil) { (result) in 26 | 27 | } 28 | salesCountLabel.text = "月销" + (model?.goodsSell ?? "") + "件" 29 | goodsNameLabel.text = model?.goodsName ?? "" 30 | var tagArr = [String]() 31 | if (model?.tags?.isEmpty == false) { 32 | flagOneLabel.isHidden = false; 33 | flagTwoLabel.isHidden = false; 34 | tagArr = (model?.tags?.components(separatedBy:",")) ?? [] 35 | if (tagArr.count > 1) { 36 | self.flagOneLabel.text = " " + (tagArr.last ?? "") + " " 37 | self.flagTwoLabel.text = " " + (tagArr.first ?? "") + " " 38 | }else if (tagArr.count > 0) { 39 | self.flagOneLabel.text = " " + (tagArr.first ?? "") + " " 40 | } 41 | }else{ 42 | flagOneLabel.isHidden = true; 43 | flagTwoLabel.isHidden = true; 44 | } 45 | 46 | let attStr = NSMutableAttributedString(string: ("¥" + (model?.payPrice ?? ""))) 47 | attStr.addAttributes([NSAttributedString.Key.font : UIFont.systemFont(ofSize: 10)], range: NSRange(location: 0, length: 1)) 48 | attStr.addAttributes([NSAttributedString.Key.font : UIFont.systemFont(ofSize: 16)], range: NSMakeRange(1, attStr.length-1)) 49 | 50 | specialPriceLabel.attributedText = attStr; 51 | let newPrice = NSMutableAttributedString(string: ("¥" + (model?.payPrice ?? ""))) 52 | newPrice.addAttributes([.font : UIFont.systemFont(ofSize: 10)], range: NSMakeRange(0, newPrice.length)) 53 | newPrice.addAttributes([.strikethroughStyle:2], range: NSMakeRange(0, newPrice.length)) 54 | officialPriceLabel.attributedText = newPrice; 55 | } 56 | } 57 | 58 | override init(frame: CGRect) { 59 | super.init(frame:frame) 60 | setupView() 61 | } 62 | 63 | required init?(coder aDecoder: NSCoder) { 64 | fatalError("init(coder:) has not been implemented") 65 | } 66 | 67 | func setupView() -> Void { 68 | // 商品图片 69 | icon = UIImageView(); 70 | self.contentView.addSubview(icon) 71 | icon.snp.makeConstraints { (make) in 72 | make.left.right.equalTo(self.contentView) 73 | make.top.equalTo(9) 74 | make.height.equalTo(icon.snp.width) 75 | } 76 | 77 | // 商品名 78 | goodsNameLabel = UILabel() 79 | goodsNameLabel.textColor = KCOLOR_Base.font_black 80 | goodsNameLabel.font = UIFont.systemFont(ofSize: 14) 81 | goodsNameLabel.lineBreakMode = .byTruncatingTail 82 | self.contentView.addSubview(goodsNameLabel) 83 | goodsNameLabel.snp.makeConstraints { (make) in 84 | make.left.equalToSuperview().offset(5) 85 | make.right.equalToSuperview().offset(-5) 86 | make.top.equalTo(icon.snp.bottom).offset(9) 87 | } 88 | 89 | //特价 90 | specialPriceLabel = UILabel() 91 | specialPriceLabel.textColor = KCOLOR_Base.font_red; 92 | self.contentView.addSubview(specialPriceLabel); 93 | specialPriceLabel.snp.makeConstraints { (make) in 94 | make.left.equalTo(goodsNameLabel); 95 | make.top.equalTo(goodsNameLabel.snp.bottom).offset(15-2); 96 | } 97 | 98 | // 标签一 99 | flagOneLabel = UILabel() 100 | flagOneLabel.layer.cornerRadius = 8 101 | flagOneLabel.layer.masksToBounds = true 102 | flagOneLabel.font = UIFont.systemFont(ofSize: 10) 103 | flagOneLabel.textColor = KCOLOR_Base.font_blue 104 | flagOneLabel.backgroundColor = KRGBHEXCOLOR(rgbValue: 0xE8F3FF) 105 | self.contentView.addSubview(flagOneLabel) 106 | flagOneLabel.snp.makeConstraints { (make) in 107 | make.right.equalTo(goodsNameLabel); 108 | make.centerY.equalTo(specialPriceLabel) 109 | make.height.equalTo(18) 110 | if (kScreenWidth <= 375) { 111 | make.width.lessThanOrEqualTo(70) 112 | }else{ 113 | make.width.lessThanOrEqualTo(80) 114 | } 115 | } 116 | 117 | // // 标签二 118 | flagTwoLabel = UILabel() 119 | flagTwoLabel.layer.cornerRadius = 8 120 | flagTwoLabel.layer.masksToBounds = true 121 | flagTwoLabel.font = UIFont.systemFont(ofSize: 10) 122 | flagTwoLabel.textColor = KRGBHEXCOLOR(rgbValue:0xff6c6c) 123 | flagTwoLabel.backgroundColor = kRGBCOLOR(r: 253, g: 240, b: 240) 124 | self.contentView.addSubview(flagTwoLabel) 125 | flagTwoLabel.snp.makeConstraints { (make) in 126 | make.right.equalTo(flagOneLabel.snp.left).offset(-5) 127 | make.top.equalTo(flagOneLabel) 128 | make.height.equalTo(flagOneLabel) 129 | if (kScreenWidth <= 375) { 130 | make.width.lessThanOrEqualTo(70) 131 | }else{ 132 | make.width.lessThanOrEqualTo(80) 133 | } 134 | } 135 | 136 | // 官方价格 137 | officialPriceLabel = UILabel() 138 | officialPriceLabel.font = UIFont.systemFont(ofSize: 10) 139 | officialPriceLabel.textColor = KCOLOR_Base.font_textField; 140 | officialPriceLabel.textAlignment = .center 141 | self.contentView.addSubview(officialPriceLabel) 142 | officialPriceLabel.snp.makeConstraints { (make) in 143 | make.top.equalTo(specialPriceLabel.snp.bottom).offset(8-2) 144 | make.left.equalTo(specialPriceLabel) 145 | } 146 | 147 | // 月销量 148 | salesCountLabel = UILabel() 149 | salesCountLabel.textColor = KCOLOR_Base.font_textField; 150 | salesCountLabel.font = UIFont.systemFont(ofSize: 10) 151 | self.contentView.addSubview(salesCountLabel) 152 | salesCountLabel.snp.makeConstraints { (make) in 153 | make.top.equalTo(officialPriceLabel); 154 | make.right.equalTo(goodsNameLabel); 155 | } 156 | } 157 | 158 | } 159 | -------------------------------------------------------------------------------- /TQGO/Class/ShopCartModule/Controller/ShopCartVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShopCartVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/8. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ShopCartVC: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | view.backgroundColor = .white 16 | title = "购物车" 17 | // Do any additional setup after loading the view. 18 | } 19 | 20 | 21 | /* 22 | // MARK: - Navigation 23 | 24 | // In a storyboard-based application, you will often want to do a little preparation before navigation 25 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 26 | // Get the new view controller using segue.destination. 27 | // Pass the selected object to the new view controller. 28 | } 29 | */ 30 | 31 | } 32 | -------------------------------------------------------------------------------- /TQGO/Class/UnicomAreaModule/Controller/UnicomAreaVC.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UnicomAreaVC.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import MJRefresh 11 | 12 | private let kUnicomADCell_id = "kUnicomADCell_id" 13 | private let kUnicomMenuCell_id = "kUnicomMenuCell_id" 14 | private let kHotGoodsCell_id = "kHotGoodsCell_id" 15 | private let kDiscountAreaCell_id = "kDiscountAreaCell_id" 16 | 17 | class UnicomAreaVC: UIViewController,UITextFieldDelegate,GoodsDetailDelegate{ 18 | 19 | var navbarView:UIView? 20 | var searchTF:UITextField? 21 | var unicomIndexModel:UnicomIndexModel? 22 | 23 | lazy var tableView : UITableView = { 24 | let tableView = UITableView() 25 | tableView.separatorStyle = .none 26 | tableView.dataSource = self 27 | tableView.delegate = self 28 | tableView.register(ADCell.self, forCellReuseIdentifier: kUnicomADCell_id) 29 | tableView.register(UnicomMenuCell.self, forCellReuseIdentifier: kUnicomMenuCell_id) 30 | tableView.register(HotGoodsCell.self, forCellReuseIdentifier: kHotGoodsCell_id) 31 | tableView.register(DiscountAreaCell.self, forCellReuseIdentifier: kDiscountAreaCell_id) 32 | view.addSubview(tableView) 33 | tableView.snp.makeConstraints({ make in 34 | make.top.equalTo(navbarView!.snp.bottom) 35 | make.left.right.bottom.equalToSuperview() 36 | }) 37 | return tableView 38 | }() 39 | 40 | override func viewDidLoad() { 41 | super.viewDidLoad() 42 | title = "联通专区" 43 | view.backgroundColor = .white 44 | addSearchNav() 45 | tableView.backgroundColor = .white 46 | tableView.mj_header = MJRefreshNormalHeader(refreshingBlock: { 47 | self.loadData() 48 | }) 49 | loadData() 50 | } 51 | 52 | func loadData() -> Void { 53 | 54 | let dict = [kUserNo:"YXY" , "area": "110000"] 55 | NetworkManager.loadData(api: APIInterfaceUnicom.queryUnicomZoneIndex(params: dict), completionClosure: {[weak self] (respone) -> (Void) in 56 | self!.tableView.mj_header?.endRefreshing() 57 | if respone.returnCode == KErrorCode.KErrorCode_SUCCESSE.rawValue{ 58 | self!.unicomIndexModel = respone.data as? UnicomIndexModel 59 | self!.tableView.reloadData() 60 | 61 | }else{ 62 | self!.readDataFromLocal() 63 | } 64 | }) {[weak self] (fail) -> (Void) in 65 | self!.tableView.mj_header?.endRefreshing() 66 | self!.readDataFromLocal() 67 | } 68 | } 69 | 70 | /// 读取本地数据 71 | func readDataFromLocal(){ 72 | let homeDiscountZone = Bundle.main.path(forResource: "UnicomAreaDiscountZone", ofType: "plist") 73 | let menuArrDiscountZone = NSArray(contentsOfFile: homeDiscountZone!) 74 | let tempArrDiscountZone = JSONDeserializer.deserializeModelArrayFrom(array: menuArrDiscountZone) as! Array 75 | let tempModel = UnicomIndexModel() 76 | tempModel.discountZone = tempArrDiscountZone 77 | 78 | let homeRecommGoods = Bundle.main.path(forResource: "UnicomAreaRecommGoods", ofType: "plist") 79 | let menuArrRecommGoods = NSArray(contentsOfFile: homeRecommGoods!) 80 | let tempArrRecommGoods = JSONDeserializer.deserializeModelArrayFrom(array: menuArrRecommGoods) as! Array 81 | tempModel.recommGoods = tempArrRecommGoods 82 | 83 | let homeBanner = Bundle.main.path(forResource: "UnicomBanner", ofType: "plist") 84 | let menuArrBanner = NSArray(contentsOfFile: homeBanner!) 85 | let tempArrBanner = JSONDeserializer.deserializeModelArrayFrom(array: menuArrBanner) as! Array 86 | tempModel.banners = tempArrBanner 87 | self.unicomIndexModel = tempModel 88 | self.tableView.reloadData() 89 | } 90 | 91 | override func viewWillAppear(_ animated: Bool) { 92 | super.viewWillAppear(animated) 93 | navigationController?.setNavigationBarHidden(true, animated: false) 94 | } 95 | override func viewWillDisappear(_ animated: Bool) { 96 | super.viewWillDisappear(animated) 97 | navigationController?.setNavigationBarHidden(false, animated: false) 98 | } 99 | 100 | override func didReceiveMemoryWarning() { 101 | super.didReceiveMemoryWarning() 102 | // Dispose of any resources that can be recreated. 103 | } 104 | func addSearchNav() -> Void { 105 | 106 | var y = 20.0; 107 | if kSafeAreaBottomHeight != 0{ 108 | y = 44.0; 109 | } 110 | navbarView = UIView.init(frame: CGRect(x: 0.0, y: y, width:Double(CGFloat(kScreenWidth)), height: 44.0)) 111 | navbarView!.backgroundColor = .white 112 | 113 | // 搜索框 114 | let radiusValue:CGFloat = 15; 115 | searchTF = UITextField(); 116 | searchTF!.delegate = self ; 117 | searchTF!.font = UIFont.systemFont(ofSize: 14); 118 | searchTF!.textColor = KCOLOR_Base.font_textField; 119 | searchTF!.backgroundColor = KRGBHEXCOLOR(rgbValue:0xf3f3f3); 120 | searchTF!.layer.cornerRadius = radiusValue; 121 | searchTF!.placeholder = "商品搜索"; 122 | let bgV:UIView = UIView(frame: CGRect(x: 0, y: 0, width: 36, height: 30)) 123 | bgV.backgroundColor = KRGBHEXCOLOR(rgbValue:0xf3f3f3); 124 | bgV.layer.cornerRadius = radiusValue; 125 | bgV.layer.masksToBounds = true; 126 | 127 | let imageV = UIImageView(image: UIImage.init(imageLiteralResourceName:"icon_search" )) 128 | bgV.addSubview(imageV) 129 | imageV.snp.makeConstraints { (make) in 130 | make.centerX.equalTo(bgV); 131 | make.centerY.equalTo(bgV); 132 | } 133 | 134 | searchTF!.leftView = bgV; 135 | searchTF!.leftViewMode = .always; 136 | navbarView!.addSubview(searchTF!) 137 | searchTF!.snp.makeConstraints { (make) in 138 | make.left.equalTo(15); 139 | make.centerY.equalTo(navbarView!); 140 | make.right.equalTo(-15); 141 | make.height.equalTo(30); 142 | } 143 | view.addSubview(navbarView!); 144 | } 145 | } 146 | 147 | extension UnicomAreaVC:UITableViewDelegate,UITableViewDataSource{ 148 | 149 | func numberOfSections(in tableView: UITableView) -> Int { 150 | return 4 151 | } 152 | 153 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 154 | if section == 0 || section == 1 || section == 2 { 155 | return 1 156 | }else{ 157 | return unicomIndexModel?.discountZone?.count ?? 0 158 | } 159 | } 160 | 161 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 162 | if indexPath.section == 0 { 163 | let adCell = tableView.dequeueReusableCell(withIdentifier: kUnicomADCell_id, for: indexPath) as! ADCell 164 | let count = self.unicomIndexModel?.banners?.count 165 | if count ?? 0 > 0 { 166 | adCell.setSlideArr(banner: (self.unicomIndexModel?.banners!)!) 167 | } 168 | return adCell 169 | }else if indexPath.section == 1 { 170 | let menuCell = tableView.dequeueReusableCell(withIdentifier: kUnicomMenuCell_id, for: indexPath) 171 | return menuCell 172 | }else if indexPath.section == 2 { 173 | let hotcell = tableView.dequeueReusableCell(withIdentifier: kHotGoodsCell_id, for: indexPath) as? HotGoodsCell 174 | if (unicomIndexModel?.recommGoods?.count) != nil{ 175 | hotcell?.setDataArr(dataArr:(unicomIndexModel?.recommGoods)!) 176 | } 177 | return hotcell! 178 | }else{ 179 | let discountCell = tableView.dequeueReusableCell(withIdentifier: kDiscountAreaCell_id, for: indexPath) as? DiscountAreaCell 180 | if (unicomIndexModel?.discountZone?.count) != nil{ 181 | discountCell?.setModel(goodsModel: (unicomIndexModel?.discountZone![indexPath.row])!) 182 | } 183 | return discountCell! 184 | } 185 | } 186 | 187 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 188 | tableView.deselectRow(at: indexPath, animated: true) 189 | let goodsDetailVC = GoodsDetailVC() 190 | goodsDetailVC.delegate = self 191 | self.navigationController?.pushViewController(goodsDetailVC, animated: true) 192 | } 193 | 194 | func callback() { 195 | DLog("++++++++++++++++++____________+++++++++++++++++") 196 | } 197 | 198 | } 199 | -------------------------------------------------------------------------------- /TQGO/Class/UnicomAreaModule/Model/GoodsModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GoodsModel.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/28. 6 | // Copyright © 2018 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | enum KGoodsType:String{ 12 | case KGoodsType_GiftBag = "0"// 打包商品 礼包商品 13 | case KGoodsType_Virtual = "1"// 虚拟商品 14 | case KGoodsType_Entity = "2"// 实物商品 15 | case KGoodsType_3C = "3"// 3商品 16 | } 17 | 18 | enum KHideStatus:String{ 19 | case KHideStatus_hide = "0"// 隐藏 20 | case KHideStatus_show = "1"// 显示 21 | } 22 | 23 | 24 | enum kShopcartstatus:String{ 25 | case kShopcartstatus_normal = "0"// 0 有货 26 | case kShopcartstatus_wait = "1"// 1 补货中 27 | case kShopcartstatus_notEnough = "2"// 2 库存不足 28 | case kShopcartstatus_invalid = "3"// 已下架 29 | } 30 | 31 | 32 | class GoodsModel:HandyJSON{ 33 | var goodsCode : String? 34 | var goodsName : String? 35 | var goodsType : String? 36 | var payPrice : String? 37 | var goodsNums : String? 38 | var goodsSell : String? 39 | var thumbnailUrl : String? 40 | var indexUrl : String? 41 | var hideStatus : String? 42 | var officialPrice : String? 43 | var imgUrl : String? 44 | var tags : String? 45 | var price : String? 46 | var tag : String? 47 | var goodsArea : String? 48 | var homeTitle : String? 49 | var homeContent : String? 50 | var cityStr : String? 51 | var menuCode : String? 52 | var bigPictureUrl : String? 53 | var goodsClassifyCode : String? 54 | var alreadySpec : String? 55 | var count : String? 56 | var goodsImgUrl : String? 57 | var taskId : String? 58 | var stock : String? 59 | var status : String? 60 | var isSelected : String? 61 | var token : String? 62 | var amount : String? 63 | var goodsImg : String? 64 | var unicomZoneType : String? 65 | 66 | required init() {} 67 | } 68 | -------------------------------------------------------------------------------- /TQGO/Class/UnicomAreaModule/Model/SlideShowModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SlideShowModel.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/28. 6 | // Copyright © 2018 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | //import HandyJSON 11 | 12 | class SlideShowModel: HandyJSON { 13 | var imgUrl:String? // 图片路径 14 | var contentTitle:String?// 内容标题 15 | var descriptionInfo:String?// 描述 16 | var linkUrl:String? 17 | var showType:String?// 展示类型 18 | var endTime:String?// 结束时间 19 | var beginTime:String?// 开始时间 20 | var state:String?// 状态 0:下线 1上线 21 | var urlType:String?// 链接类型 1:内链接 2:外链接 22 | var bannerName:String?//标题 23 | var openType:String?// 1: APP内(各功能内跳转) 2: 外链(H5,其他外部链接) 24 | var openUrl:String?// 打开链接 25 | required init() {} 26 | } 27 | -------------------------------------------------------------------------------- /TQGO/Class/UnicomAreaModule/Model/UnicomIndexModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UnicomIndexModel.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/28. 6 | // Copyright © 2018 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | //import HandyJSON 11 | 12 | 13 | 14 | class UnicomIndexModel: HandyJSON { 15 | var banners:Array? 16 | var recommGoods:Array? 17 | var discountZone:Array? 18 | required init() {} 19 | } 20 | -------------------------------------------------------------------------------- /TQGO/Class/UnicomAreaModule/View/ADCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ADCell.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/12. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ADCell: UITableViewCell { 12 | var cycleScrollView:YXYBanner? 13 | 14 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 15 | super.init(style: style, reuseIdentifier: reuseIdentifier) 16 | self.setupView() 17 | } 18 | 19 | func setupView() -> Void { 20 | cycleScrollView = YXYBanner() 21 | contentView.addSubview(cycleScrollView!) 22 | cycleScrollView?.placeholderImage = UIImage(named: "icon_home_banner_default") 23 | cycleScrollView!.snp.makeConstraints { (make) in 24 | make.size.equalTo(CGSize(width: kScreenWidth, height: kScreenWidth*150/375)) 25 | make.edges.equalToSuperview() 26 | } 27 | } 28 | 29 | required init?(coder aDecoder: NSCoder) { 30 | fatalError("init(coder:) has not been implemented") 31 | } 32 | 33 | override func setSelected(_ selected: Bool, animated: Bool) { 34 | super.setSelected(selected, animated: animated) 35 | 36 | // Configure the view for the selected state 37 | } 38 | // 39 | func setSlideArr(banner:[SlideShowModel]?) -> Void { 40 | var urlsArr : [String] = [] 41 | if banner?.count != 0{ 42 | for model in banner! { 43 | if model.imgUrl?.isEmpty == false{ 44 | urlsArr.append(model.imgUrl!) 45 | } 46 | } 47 | } 48 | 49 | self.cycleScrollView!.imageURLStringsGroup = urlsArr 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /TQGO/Class/UnicomAreaModule/View/DiscountAreaCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DiscountAreaCell.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/30. 6 | // Copyright © 2018 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class DiscountAreaCell: UITableViewCell { 12 | var iconImgV :UIImageView? 13 | var goodsNameLabel : UILabel? 14 | var goodsDescLabel :UILabel? 15 | var specialPriceLabel : UILabel? 16 | var counLabel : UILabel? 17 | 18 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 19 | super.init(style: style, reuseIdentifier: reuseIdentifier) 20 | setupView() 21 | } 22 | 23 | required init?(coder aDecoder: NSCoder) { 24 | fatalError("init(coder:) has not been implemented") 25 | } 26 | 27 | func setupView() -> Void { 28 | iconImgV = UIImageView() 29 | contentView.addSubview(iconImgV!) 30 | iconImgV?.snp.makeConstraints { (make) in 31 | make.top.equalToSuperview().offset(16) 32 | make.left.equalToSuperview().offset(15) 33 | make.bottom.equalToSuperview().offset(-16) 34 | make.size.equalTo(CGSize(width: 130, height: 104)) 35 | } 36 | 37 | goodsNameLabel = UILabel() 38 | goodsNameLabel?.textColor = KCOLOR_Base.font_black 39 | goodsNameLabel?.font = .systemFont(ofSize: 14) 40 | contentView.addSubview(goodsNameLabel!) 41 | goodsNameLabel?.snp.makeConstraints({ (make) in 42 | make.top.equalTo(iconImgV!).offset(10) 43 | make.left.equalTo(iconImgV!.snp.right).offset(15) 44 | make.right.equalToSuperview().offset(-21) 45 | }) 46 | 47 | goodsDescLabel = UILabel() 48 | goodsDescLabel?.textColor = KCOLOR_Base.font_gray 49 | goodsDescLabel?.font = .systemFont(ofSize: 12) 50 | contentView.addSubview(goodsDescLabel!) 51 | goodsDescLabel?.snp.makeConstraints({ (make) in 52 | make.top.equalTo(goodsNameLabel!.snp.bottom).offset(8) 53 | make.left.equalTo(goodsNameLabel!) 54 | make.right.equalTo(goodsNameLabel!) 55 | }) 56 | 57 | counLabel = UILabel() 58 | counLabel?.textColor = KCOLOR_Base.font_gray 59 | counLabel?.font = .systemFont(ofSize: 10) 60 | contentView.addSubview(counLabel!) 61 | counLabel?.snp.makeConstraints({ (make) in 62 | make.top.equalTo(goodsDescLabel!.snp.bottom).offset(16) 63 | make.left.equalTo(goodsDescLabel!) 64 | }) 65 | 66 | specialPriceLabel = UILabel() 67 | specialPriceLabel?.textColor = KCOLOR_Base.font_red 68 | specialPriceLabel?.font = .systemFont(ofSize: 10) 69 | contentView.addSubview(specialPriceLabel!) 70 | specialPriceLabel?.snp.makeConstraints({ (make) in 71 | make.top.equalTo(counLabel!.snp.bottom).offset(8) 72 | make.left.equalTo(counLabel!) 73 | }) 74 | 75 | let view = UIView() 76 | view.backgroundColor = KCOLOR_Base.line 77 | contentView.addSubview(view) 78 | view.snp.makeConstraints { (make) in 79 | make.right.equalToSuperview().offset(-15) 80 | make.left.equalToSuperview().offset(15) 81 | make.bottom.equalToSuperview() 82 | make.height.equalTo(0.5) 83 | } 84 | 85 | 86 | } 87 | 88 | func setModel(goodsModel:GoodsModel) -> Void { 89 | iconImgV?.kf.setImage(with: URL(string: goodsModel.imgUrl!), placeholder: UIImage(named: "icon_goods_default"), options: nil, progressBlock: nil, completionHandler: { (result) in 90 | 91 | }) 92 | goodsNameLabel?.text = goodsModel.goodsName 93 | goodsDescLabel?.text = goodsModel.tag 94 | specialPriceLabel?.text = goodsModel.payPrice 95 | counLabel?.text = goodsModel.goodsSell 96 | } 97 | 98 | 99 | 100 | override func awakeFromNib() { 101 | super.awakeFromNib() 102 | // Initialization code 103 | } 104 | 105 | override func setSelected(_ selected: Bool, animated: Bool) { 106 | super.setSelected(selected, animated: animated) 107 | 108 | // Configure the view for the selected state 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /TQGO/Class/UnicomAreaModule/View/HotCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HotCollectionViewCell.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/20. 6 | // Copyright © 2018 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class HotCollectionViewCell: UICollectionViewCell { 12 | var goodsNameLabel:UILabel? 13 | var goodsDescLabel:UILabel? 14 | var goodsImg:UIImageView? 15 | 16 | override init(frame: CGRect) { 17 | super.init(frame: frame) 18 | setupView() 19 | } 20 | 21 | required init?(coder aDecoder: NSCoder) { 22 | fatalError("init(coder:) has not been implemented") 23 | } 24 | 25 | func setupView() -> Void { 26 | goodsImg = UIImageView() 27 | contentView.addSubview(goodsImg!) 28 | goodsImg?.snp.makeConstraints { (make) in 29 | make.top.equalToSuperview().offset(8) 30 | make.right.equalToSuperview().offset(-15) 31 | make.bottom.equalToSuperview().offset(-8) 32 | make.size.equalTo(CGSize(width: 56, height: 56)) 33 | } 34 | 35 | goodsNameLabel = UILabel() 36 | goodsNameLabel?.textColor = KCOLOR_Base.font_black 37 | goodsNameLabel?.font = .systemFont(ofSize: 14) 38 | contentView.addSubview(goodsNameLabel!) 39 | goodsNameLabel?.snp.makeConstraints({ (make) in 40 | make.top.equalToSuperview().offset(11) 41 | make.left.equalToSuperview().offset(15) 42 | make.right.equalTo(goodsImg!.snp.left) 43 | }) 44 | 45 | goodsDescLabel = UILabel() 46 | goodsDescLabel?.textColor = KCOLOR_Base.font_gray 47 | goodsDescLabel?.font = .systemFont(ofSize: 12) 48 | contentView.addSubview(goodsDescLabel!) 49 | goodsDescLabel?.snp.makeConstraints({ (make) in 50 | make.top.equalTo(goodsNameLabel!.snp.bottom).offset(8) 51 | make.left.equalTo(goodsNameLabel!) 52 | make.right.equalTo(goodsImg!.snp.left) 53 | }) 54 | } 55 | 56 | func setModel(goodsModel:GoodsModel) -> Void { 57 | goodsImg?.kf.setImage(with: URL(string: goodsModel.imgUrl!), placeholder: UIImage(named: "icon_goods_default"), options: nil, progressBlock: nil, completionHandler: { (result) in 58 | 59 | }) 60 | goodsNameLabel?.text = goodsModel.goodsName 61 | goodsDescLabel?.text = goodsModel.tag 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /TQGO/Class/UnicomAreaModule/View/HotGoodsCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HotGoodsCell.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/19. 6 | // Copyright © 2018 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | let kHotCollectionViewCell_id = "kHotCollectionViewCell_id" 12 | 13 | class HotGoodsCell: UITableViewCell { 14 | var dataArr:Array? 15 | 16 | lazy var collectionView:UICollectionView = { 17 | 18 | let layout = UICollectionViewFlowLayout() 19 | layout.itemSize = CGSize(width: kScreenWidth/2, height: 80) 20 | // layout.headerReferenceSize = CGSize(width: kScreenWidth, height: 48+8) 21 | layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 22 | layout.minimumLineSpacing = 0; 23 | layout.minimumInteritemSpacing = 0; 24 | let collectionView = UICollectionView(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 80*2), collectionViewLayout: layout) 25 | collectionView.register(HotCollectionViewCell.self, forCellWithReuseIdentifier: kHotCollectionViewCell_id) 26 | collectionView.backgroundColor = UIColor.white 27 | 28 | return collectionView 29 | }() 30 | 31 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 32 | super.init(style:style , reuseIdentifier: reuseIdentifier) 33 | self.setupView() 34 | } 35 | 36 | required init?(coder aDecoder: NSCoder) { 37 | fatalError("init(coder:) has not been implemented") 38 | } 39 | 40 | func setupView() -> Void { 41 | 42 | let containerView = UIView() 43 | containerView.backgroundColor = .white 44 | contentView.addSubview(containerView) 45 | containerView.snp.makeConstraints { (make) in 46 | make.edges.equalToSuperview() 47 | make.height.equalTo(80*2) 48 | } 49 | containerView.addSubview(collectionView) 50 | collectionView.delegate = self 51 | collectionView.dataSource = self 52 | } 53 | 54 | override func setSelected(_ selected: Bool, animated: Bool) { 55 | super.setSelected(selected, animated: animated) 56 | 57 | // Configure the view for the selected state 58 | } 59 | 60 | } 61 | 62 | extension HotGoodsCell:UICollectionViewDelegate,UICollectionViewDataSource{ 63 | 64 | func setDataArr(dataArr:Array) -> Void { 65 | self.dataArr = dataArr 66 | collectionView.reloadData() 67 | } 68 | func numberOfSections(in collectionView: UICollectionView) -> Int { 69 | return 1 70 | } 71 | 72 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 73 | let num = self.dataArr?.count ?? 0 74 | return num 75 | } 76 | 77 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 78 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: kHotCollectionViewCell_id, for: indexPath) as? HotCollectionViewCell 79 | cell?.setModel(goodsModel: dataArr![indexPath.row]) 80 | return cell! 81 | } 82 | } 83 | 84 | 85 | -------------------------------------------------------------------------------- /TQGO/Class/UnicomAreaModule/View/UnicomMenuCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UnicomMenuCell.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/13. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class UnicomMenuCell: UITableViewCell { 12 | 13 | var giftlabel:UILabel? 14 | var giftDescLabel:UILabel? 15 | var giftImagV : UIImageView? 16 | 17 | var phonelabel:UILabel? 18 | var phoneDescLabel:UILabel? 19 | var phoneImagV : UIImageView? 20 | 21 | 22 | override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { 23 | super.init(style:style , reuseIdentifier: reuseIdentifier) 24 | self.setupView() 25 | } 26 | 27 | required init?(coder aDecoder: NSCoder) { 28 | fatalError("init(coder:) has not been implemented") 29 | } 30 | 31 | 32 | func setupView() -> Void { 33 | giftlabel = UILabel() 34 | giftlabel?.text = "礼包专区" 35 | giftlabel?.textColor = KCOLOR_Base.font_black 36 | giftlabel?.font = .systemFont(ofSize: 16) 37 | contentView.addSubview(giftlabel!) 38 | giftlabel?.snp.makeConstraints({ (make) in 39 | make.top.equalToSuperview().offset(16) 40 | make.centerX.equalToSuperview().offset(-kScreenWidth/4) 41 | }) 42 | giftDescLabel = UILabel() 43 | giftDescLabel?.text = "礼包随心选" 44 | giftDescLabel?.textColor = KCOLOR_Base.font_gray 45 | giftDescLabel?.font = .systemFont(ofSize: 12) 46 | contentView.addSubview(giftDescLabel!) 47 | giftDescLabel?.snp.makeConstraints({ (make) in 48 | make.top.equalTo(giftlabel!.snp.bottom).offset(8) 49 | make.centerX.equalTo(giftlabel!) 50 | }) 51 | 52 | giftImagV = UIImageView() 53 | giftImagV?.image = UIImage.init(imageLiteralResourceName: "icon_gift_area") 54 | contentView.addSubview(giftImagV!) 55 | giftImagV?.snp.makeConstraints({ (make) in 56 | make.top.equalTo(giftDescLabel!.snp.bottom).offset(16) 57 | make.bottom.equalToSuperview().offset(-5) 58 | make.size.equalTo(CGSize(width: 110, height: 60)) 59 | make.centerX.equalTo(giftDescLabel!) 60 | }) 61 | 62 | phonelabel = UILabel() 63 | phonelabel?.text = "手机专区" 64 | phonelabel?.textColor = KCOLOR_Base.font_black 65 | phonelabel?.font = .systemFont(ofSize: 16) 66 | contentView.addSubview(phonelabel!) 67 | phonelabel?.snp.makeConstraints({ (make) in 68 | make.top.equalToSuperview().offset(16) 69 | make.centerX.equalToSuperview().offset(kScreenWidth/4) 70 | }) 71 | phoneDescLabel = UILabel() 72 | phoneDescLabel?.text = "手机畅想购" 73 | phoneDescLabel?.textColor = KCOLOR_Base.font_gray 74 | phoneDescLabel?.font = .systemFont(ofSize: 12) 75 | contentView.addSubview(phoneDescLabel!) 76 | phoneDescLabel?.snp.makeConstraints({ (make) in 77 | make.top.equalTo(phonelabel!.snp.bottom).offset(8) 78 | make.centerX.equalTo(phonelabel!) 79 | }) 80 | 81 | phoneImagV = UIImageView() 82 | phoneImagV?.image = UIImage.init(imageLiteralResourceName: "icon_phone_area") 83 | contentView.addSubview(phoneImagV!) 84 | phoneImagV?.snp.makeConstraints({ (make) in 85 | make.top.equalTo(phoneDescLabel!.snp.bottom).offset(16) 86 | make.bottom.equalToSuperview().offset(-5) 87 | make.size.equalTo(CGSize(width: 110, height: 60)) 88 | make.centerX.equalTo(phoneDescLabel!) 89 | }) 90 | } 91 | 92 | override func setSelected(_ selected: Bool, animated: Bool) { 93 | super.setSelected(selected, animated: animated) 94 | 95 | // Configure the view for the selected state 96 | } 97 | 98 | 99 | } 100 | -------------------------------------------------------------------------------- /TQGO/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | 必买BEMINE 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 4.0.0 21 | CFBundleVersion 22 | 20 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UILaunchStoryboardName 31 | LaunchScreen 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | 40 | UISupportedInterfaceOrientations~ipad 41 | 42 | UIInterfaceOrientationPortrait 43 | UIInterfaceOrientationPortraitUpsideDown 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /TQGO/Macro/AppConstant.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppConstant.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/10. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | 13 | #if DEBUG 14 | 15 | let API_BASE = "http://www.YXY.com" // 测试 16 | 17 | #else 18 | let API_BASE = "http://www.YXY.com" // 正式 19 | #endif 20 | 21 | 22 | #if DEBUG 23 | 24 | 25 | let API_UAPKEY = "YXY"//测试 uapkey 26 | let API_SECRET_KEY = "key=YXY" //测试环境 商户签名秘钥- key 27 | 28 | let KDebugMode = true // debug 模式下,开启调试模式 29 | let KBuglyChannel = "Debug" 30 | let kDEBUGTYPE = true // 调试环境 31 | let kJPUSH_ISProduction = false // 极光推送环境变量 32 | let KBaiduMobStatLog_switch = true // 百度统计 测试环境开启日志输出 上线打开为yes 测试关闭为NO 33 | let kFUPayKey = "YXY" 34 | 35 | #else 36 | 37 | 38 | let API_UAPKEY = "YXY" //正式 uapkey 39 | let API_SECRET_KEY = "key=YXY" //正式环境 商户签名秘钥- key 40 | 41 | #endif 42 | 43 | let KFooterHeight = 48 44 | let kDeliveryTime = 1 // 预计发货时间 45 | let kArrivaTime = 5 // 预计到货时间 46 | let kUserNo = "kUserNo" 47 | 48 | // 接口通用参数配置 49 | let kPLATFORM_CODE = "YXY" // 平台编码 50 | let kIP = "YXY" // 真实来源 51 | let kAPI_ImageServer = "http://YXY/static" 52 | let KBuglyAppId = "YXY" // BuglyAppId 53 | let KWXAppId = "YXY"// WXAppId 54 | let KBaiduMobStatAppKey = "YXY" 55 | let KJPUSHAppKey = "YXY" 56 | let KAppScheme = "YXY" 57 | let KStagesPrice = "50" 58 | let kAES128KEY = "YXY" // AES128KEY 与向量kInitVector值相同 59 | 60 | // 百度统计时间ID 61 | enum KBaiduMobStatID:String{ 62 | case Promotion_Category_One = "Promotion_Category_One" 63 | case Promotion_Category_Two = "Promotion_Category_Two" 64 | case Banner = "Banner" 65 | case UnicomBanner = "UnicomBanner" 66 | case HotListView = "HotListView" 67 | case DiscountArea = "DiscountArea" 68 | case GoodsDetailShare = "GoodsDetailShare" 69 | case ViewTextDetailShare = "ViewTextDetailShare" 70 | case GoodsDetailBuy = "GoodsDetailBuy" 71 | case GiftCardExchange = "GiftCardExchange" 72 | case Recharge = "Recharge" 73 | case Login = "Login" 74 | case Register = "Register" 75 | case GetGiftBag = "GetGiftBag" 76 | case PhoneMenu = "PhoneMenu" 77 | case GiftBagMenu = "GiftBagMenu" 78 | case GoodsSearch = "GoodsSearch" 79 | case SubmitOrder = "SubmitOrder" 80 | case CreditPayList = "CreditPayList" 81 | case MakeSurePay = "MakeSurePay" 82 | case AuthActivate = "AuthActivate" 83 | case Repay = "Repay" 84 | } 85 | 86 | // 基础配色 87 | struct KCOLOR_Base { 88 | static let viewBackground = KRGBHEXCOLOR(rgbValue:0xf7f7f7) // f5f5f5 89 | static let font_golden = KRGBHEXCOLOR(rgbValue:0xd2aa60) 90 | static let statusBar = kRGBCOLOR(r:0,g:11,b:15) 91 | static let font_red = KRGBHEXCOLOR(rgbValue:0xff6c6c) 92 | static let line = KRGBHEXCOLOR(rgbValue:0xe7e8ed) 93 | static let font_black = KRGBHEXCOLOR(rgbValue:0x3a404c) 94 | static let font_blue = KRGBHEXCOLOR(rgbValue:0x3b9afe) 95 | static let font_gray = KRGBHEXCOLOR(rgbValue:0x92969f) 96 | static let font_textField = KRGBHEXCOLOR(rgbValue:0xb9bdc6) 97 | } 98 | 99 | 100 | -------------------------------------------------------------------------------- /TQGO/Macro/Macro.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Macro.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/7/10. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import SnapKit 12 | 13 | @_exported import RxSwift 14 | @_exported import RxCocoa 15 | @_exported import RealmSwift 16 | @_exported import HandyJSON 17 | @_exported import SwiftyJSON 18 | @_exported import Kingfisher 19 | @_exported import Toast 20 | 21 | let kScreenHeight = UIScreen.main.bounds.height 22 | let kScreenWidth = UIScreen.main.bounds.width 23 | let kSafeAreaBottomHeight:CGFloat = (((kScreenHeight == 812.0 ) || (kScreenHeight == 896.0)) ? 34 : 0) 24 | let kSafeAreaTopHeight:CGFloat = (((kScreenHeight == 812.0 ) || (kScreenHeight == 896.0)) ? 88 : 64) 25 | let kSystemVersion = (UIDevice.current.systemVersion as NSString).floatValue 26 | let kStatusBarHeight = UIApplication.shared.statusBarFrame.height 27 | let kMainScreenScale = UIScreen.main.scale 28 | let kNavgationHeight = (CGFloat(kStatusBarHeight) + CGFloat(kNabBarHeight)) 29 | let kUserDefaults = UserDefaults.standard 30 | let kNotife = NotificationCenter.default 31 | let kAppVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") 32 | let kUUID = UIDevice.current.identifierForVendor?.uuidString.replacingOccurrences(of: "-", with: "") 33 | let kDate_Location = "zh_CN" 34 | let kTabbarHeight = 49 35 | let kNabBarHeight = 44 36 | let kLineHeight = 0.5 37 | let kSectionHeight:CGFloat = 48 38 | let kMarginHeight = 8 39 | let kLimitPhone = 11 40 | let kLimitPassword = 16 41 | let kLimitSecurityCode = 4 42 | 43 | //获取命名空间,在info.plist文件里就是Executable file 44 | let nameSpace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String 45 | //拼接成固定格式 46 | func YXYClassFromString(name:String) -> AnyClass{ 47 | return NSClassFromString(nameSpace + "." + name)! 48 | } 49 | 50 | // 文件夹路径 51 | struct kDirectoryPath { 52 | static let Documents = NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask, true).last 53 | static let Library = NSSearchPathForDirectoriesInDomains(.libraryDirectory,.userDomainMask, true).last 54 | static let Tmp = NSTemporaryDirectory() 55 | static let Caches = NSSearchPathForDirectoriesInDomains(.cachesDirectory,.userDomainMask, true).last 56 | } 57 | 58 | // 打印内容,并包含类名和打印所在行数 59 | func DLog(_ message : T,file : String = #file,function:String = #function, lineNumber : Int = #line) { 60 | #if DEBUG 61 | let fileName = (file as NSString).lastPathComponent 62 | let functionStr = function.split(separator: "(").first 63 | print("\n**************自定义日志输出:\(fileName):\(functionStr ?? "")():[\(lineNumber)]************** \n\(message) \n**************************************************") 64 | #endif 65 | } 66 | 67 | func kImage(name:String) -> UIImage?{ 68 | return UIImage(named: name) 69 | } 70 | 71 | func kFont(size:CGFloat) -> UIFont{ 72 | return UIFont.systemFont(ofSize: size) 73 | } 74 | 75 | func kRGBCOLOR(r:CGFloat,g:CGFloat,b:CGFloat) -> UIColor{ 76 | return UIColor(red: r/255.0, green: g/255.0, blue: b/255.0, alpha: 1) 77 | } 78 | 79 | func kRGBACOLOR(r:CGFloat,g:CGFloat,b:CGFloat, a:CGFloat) -> UIColor{ 80 | return UIColor(red: r/255.0, green: g/255.0, blue: b/255.0, alpha: a) 81 | } 82 | 83 | //RGB 16进制转换 84 | func KRGBHEXCOLOR(rgbValue: UInt) -> UIColor { 85 | return UIColor( 86 | red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0, 87 | green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0, 88 | blue: CGFloat(rgbValue & 0x0000FF) / 255.0, 89 | alpha: CGFloat(1.0) 90 | ) 91 | } 92 | 93 | 94 | -------------------------------------------------------------------------------- /TQGO/Macro/TQGO-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | 6 | #import 7 | -------------------------------------------------------------------------------- /TQGO/Model/APIModel/APIResultModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // APIResultModel.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/28. 6 | // Copyright © 2018 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | //import HandyJSON 11 | 12 | class APIResultModel: HandyJSON { 13 | var data : Any? 14 | var returnCode : String? 15 | var returnMsg :String? 16 | 17 | required init() {} 18 | } 19 | 20 | enum KErrorCode:String{ 21 | 22 | case KErrorCode_SUCCESSE = "1000" // 成功 23 | case KErrorCode_CODE1001 = "1001" // 传入参数为空或不合法 24 | case KErrorCode_CODE1002 = "1002" // 数据异常 25 | case KErrorCode_CODE1003 = "1003" // 验签失败 26 | case KErrorCode_CODE1004 = "1004" // 组件编码错误 27 | 28 | case KErrorCode_CODE1005 = "1005" // 重复提交 29 | case KErrorCode_CODE1006 = "1006" // 商品售罄 30 | case KErrorCode_CODE1007 = "1007" // 商品已过期 31 | case KErrorCode_CODE1008 = "1008" // 商品已下线 32 | case KErrorCode_CODE1009 = "1009" // T币余额不足 33 | case KErrorCode_CODE1030 = "1030" // 无效卡 34 | case KErrorCode_CODE1031 = "1031" // 已失效 35 | 36 | case KErrorCode_CODE2000 = "2000" // 验证码发送失败 37 | case KErrorCode_CODE2001 = "2001" // 您已注册请登录 38 | case KErrorCode_CODE2002 = "2002" // 登录密码错误" 39 | case KErrorCode_CODE2003 = "2003" // 用户不存在 40 | case KErrorCode_CODE2004 = "2004" // 验证码错误 41 | case KErrorCode_CODE2005 = "2005" // 验证码超时 42 | case KErrorCode_CODE2006 = "2006" // 请注册之后再登陆 43 | case KErrorCode_CODE2007 = "2007" // 用户未实名 44 | 45 | case KErrorCode_CODE3000 = "3000" // 不支持该银行卡 46 | case KErrorCode_CODE3001 = "3001" // 绑卡失败 47 | case KErrorCode_CODE3002 = "3002" // 该银行卡已签约 48 | case KErrorCode_CODE3003 = "3003" // 银行验证失败 49 | case KErrorCode_CODE3004 = "3004" // 购买失败 50 | case KErrorCode_CODE3005 = "3005" // 购买金额不能大于剩余金额 51 | case KErrorCode_CODE3006 = "3006" // 加密错误 52 | case KErrorCode_CODE3007 = "3007" // 该证件号码已被实名 53 | case KErrorCode_CODE3008 = "3008" // 该银行卡未签约 54 | case KErrorCode_CODE3009 = "3009" // 该优惠劵不可用 55 | case KErrorCode_CODE3010 = "3010" // 该用户未绑定银行卡 56 | case KErrorCode_CODE3011 = "3011" // 该身份证已认证其他用户 57 | case KErrorCode_CODE3012 = "3012" // 身份证认证失败 58 | 59 | case KErrorCode_CODE4000 = "4000" // 产品已售罄 60 | case KErrorCode_CODE4001 = "4001" // 产品不存在 61 | case KErrorCode_CODE4002 = "4002" // 募集时间已结束 62 | 63 | case KErrorCode_CODE5001 = "5001" // 邀请人未参加邀请活动 64 | case KErrorCode_CODE5002 = "5002" // 活动已结束 65 | 66 | case KErrorCode_CODE6001 = "6001" // 请更新版本 67 | case KErrorCode_CODE6002 = "6002" // 已是最新版本 68 | 69 | case KErrorCode_CODE8001 = "8001" // 用户不在白名单内 70 | case KErrorCode_CODE8002 = "8002" // 用户在黑名单中 71 | case KErrorCode_CODE8003 = "8003" // 授信申请失败 72 | case KErrorCode_CODE8004 = "8004" // 启动活体识别验证失败 73 | 74 | case KErrorCode_CODE9998 = "9998" // 数据异常,请稍后 75 | case KErrorCode_CODE9999 = "9999" // 系统异常,请重试 76 | 77 | case KErrorCode_Login_INVALID = "9990" // 登录信息有误 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "icon-20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "icon-20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "icon-29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "icon-29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "icon-40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "icon-40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "icon-60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "icon-60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "1024x1024", 53 | "idiom" : "ios-marketing", 54 | "filename" : "icon_1024.png", 55 | "scale" : "1x" 56 | } 57 | ], 58 | "info" : { 59 | "version" : 1, 60 | "author" : "xcode" 61 | } 62 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/AppIcon.appiconset/icon_1024.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/LanchIcon/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/LanchIcon/icon_launch.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_launch@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_launch@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/LanchIcon/icon_launch.imageset/icon_launch@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/LanchIcon/icon_launch.imageset/icon_launch@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/LanchIcon/icon_launch.imageset/icon_launch@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/LanchIcon/icon_launch.imageset/icon_launch@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_arrow_right_white.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_arrow_right_white@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_arrow_right_white@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_arrow_right_white.imageset/icon_arrow_right_white@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_arrow_right_white.imageset/icon_arrow_right_white@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_arrow_right_white.imageset/icon_arrow_right_white@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_arrow_right_white.imageset/icon_arrow_right_white@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_header.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_header@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_header@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_header.imageset/icon_header@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_header.imageset/icon_header@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_header.imageset/icon_header@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_header.imageset/icon_header@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_phone_num.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_phone_num@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_phone_num@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_phone_num.imageset/icon_phone_num@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_phone_num.imageset/icon_phone_num@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_phone_num.imageset/icon_phone_num@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_phone_num.imageset/icon_phone_num@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_secure_close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_secure_close@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_secure_close@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_secure_close.imageset/icon_secure_close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_secure_close.imageset/icon_secure_close@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_secure_close.imageset/icon_secure_close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_secure_close.imageset/icon_secure_close@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_secure_visible.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_secure_visible@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_secure_visible@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_secure_visible.imageset/icon_secure_visible@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_secure_visible.imageset/icon_secure_visible@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_secure_visible.imageset/icon_secure_visible@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_secure_visible.imageset/icon_secure_visible@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_security_lock.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_security_lock@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_security_lock@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_security_lock.imageset/icon_security_lock@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_security_lock.imageset/icon_security_lock@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_security_lock.imageset/icon_security_lock@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_security_lock.imageset/icon_security_lock@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_verity_code.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_verity_code@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_verity_code@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_verity_code.imageset/icon_verity_code@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_verity_code.imageset/icon_verity_code@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/MyImage/icon_verity_code.imageset/icon_verity_code@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/MyImage/icon_verity_code.imageset/icon_verity_code@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_credit.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_tabbar_default_credit@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_tabbar_default_credit@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_credit.imageset/icon_tabbar_default_credit@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_credit.imageset/icon_tabbar_default_credit@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_credit.imageset/icon_tabbar_default_credit@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_credit.imageset/icon_tabbar_default_credit@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_personalCenter.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_tabbar_default_personalCenter@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_tabbar_default_personalCenter@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_personalCenter.imageset/icon_tabbar_default_personalCenter@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_personalCenter.imageset/icon_tabbar_default_personalCenter@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_personalCenter.imageset/icon_tabbar_default_personalCenter@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_personalCenter.imageset/icon_tabbar_default_personalCenter@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_promotion.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_tabbar_default_promotion@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_tabbar_default_promotion@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_promotion.imageset/icon_tabbar_default_promotion@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_promotion.imageset/icon_tabbar_default_promotion@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_promotion.imageset/icon_tabbar_default_promotion@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_promotion.imageset/icon_tabbar_default_promotion@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_unicom.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_tabbar_default_unicom@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_tabbar_default_unicom@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_unicom.imageset/icon_tabbar_default_unicom@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_unicom.imageset/icon_tabbar_default_unicom@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_unicom.imageset/icon_tabbar_default_unicom@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_default_unicom.imageset/icon_tabbar_default_unicom@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_credit.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_tabbar_selected_credit@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_tabbar_selected_credit@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_credit.imageset/icon_tabbar_selected_credit@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_credit.imageset/icon_tabbar_selected_credit@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_credit.imageset/icon_tabbar_selected_credit@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_credit.imageset/icon_tabbar_selected_credit@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_personalCenter.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_tabbar_selected_personalCenter@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_tabbar_selected_personalCenter@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_personalCenter.imageset/icon_tabbar_selected_personalCenter@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_personalCenter.imageset/icon_tabbar_selected_personalCenter@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_personalCenter.imageset/icon_tabbar_selected_personalCenter@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_personalCenter.imageset/icon_tabbar_selected_personalCenter@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_promotion.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_tabbar_selected_promotion@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_tabbar_selected_promotion@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_promotion.imageset/icon_tabbar_selected_promotion@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_promotion.imageset/icon_tabbar_selected_promotion@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_promotion.imageset/icon_tabbar_selected_promotion@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_promotion.imageset/icon_tabbar_selected_promotion@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_unicom.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_tabbar_selected_unicom@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_tabbar_selected_unicom@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | }, 22 | "properties" : { 23 | "template-rendering-intent" : "original" 24 | } 25 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_unicom.imageset/icon_tabbar_selected_unicom@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_unicom.imageset/icon_tabbar_selected_unicom@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_unicom.imageset/icon_tabbar_selected_unicom@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/TabbarImage/icon_tabbar_selected_unicom.imageset/icon_tabbar_selected_unicom@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_flag_blue.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_flag_blue@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_flag_blue@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_flag_blue.imageset/icon_flag_blue@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_flag_blue.imageset/icon_flag_blue@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_flag_blue.imageset/icon_flag_blue@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_flag_blue.imageset/icon_flag_blue@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_gift_area.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_gift_area@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_gift_area@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_gift_area.imageset/icon_gift_area@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_gift_area.imageset/icon_gift_area@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_gift_area.imageset/icon_gift_area@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_gift_area.imageset/icon_gift_area@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_goods_default.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_goods_default@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_goods_default@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_goods_default.imageset/icon_goods_default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_goods_default.imageset/icon_goods_default@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_goods_default.imageset/icon_goods_default@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_goods_default.imageset/icon_goods_default@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_home_banner_default.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_home_banner_default@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_home_banner_default@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_home_banner_default.imageset/icon_home_banner_default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_home_banner_default.imageset/icon_home_banner_default@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_home_banner_default.imageset/icon_home_banner_default@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_home_banner_default.imageset/icon_home_banner_default@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_phone_area.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_phone_area@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_phone_area@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_phone_area.imageset/icon_phone_area@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_phone_area.imageset/icon_phone_area@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_phone_area.imageset/icon_phone_area@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_phone_area.imageset/icon_phone_area@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_search.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "icon_search@2x.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "filename" : "icon_search@3x.png", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_search.imageset/icon_search@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_search.imageset/icon_search@2x.png -------------------------------------------------------------------------------- /TQGO/Resource/Assets.xcassets/UnicomImage/icon_search.imageset/icon_search@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FreeYXY/SwiftProject/4757db11655c36b1de7f2b1678ece499ddcb5d8f/TQGO/Resource/Assets.xcassets/UnicomImage/icon_search.imageset/icon_search@3x.png -------------------------------------------------------------------------------- /TQGO/Resource/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /TQGO/Resource/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /TQGO/Resource/BimineData/UnicomAreaDiscountZone.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | goodsCode 7 | JXPZ_358 8 | goodsName 9 | “匠心品质” 10 | goodsSell 11 | 2 12 | goodsType 13 | 0 14 | hideStatus 15 | 1 16 | imgUrl 17 | http://www.tequango.com/privilegeGo/image/1530849358155.jpg 18 | payPrice 19 | 358 20 | price 21 | 358 22 | tag 23 | 匠心之道,让家更有味道 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TQGO/Resource/BimineData/UnicomAreaRecommGoods.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | goodsCode 7 | HW_Mate10Pro 8 | goodsName 9 | 华为 Mate10 Pro 全网通 10 | goodsType 11 | 3 12 | hideStatus 13 | 1 14 | imgUrl 15 | http://www.tequango.com/privilegeGo/image/1514193683322.png 16 | tag 17 | 防溅抗水,卓越性能 18 | 19 | 20 | goodsCode 21 | HW_P20 22 | goodsName 23 | 华为 P20 AI智慧全面屏 全网通4G手机 双卡双待 24 | goodsType 25 | 3 26 | hideStatus 27 | 1 28 | imgUrl 29 | http://www.tequango.com/privilegeGo/image/1532488849868.jpg 30 | tag 31 | 高颜值,高性能 32 | 33 | 34 | goodsCode 35 | NXNW_180 36 | goodsName 37 | “暖心暖胃” 38 | goodsType 39 | 0 40 | hideStatus 41 | 1 42 | imgUrl 43 | http://www.tequango.com/privilegeGo/image/1530503853959.jpg 44 | tag 45 | 高颜值,超实用 46 | 47 | 48 | goodsCode 49 | LXWC_80 50 | goodsName 51 | “两小无猜” 52 | goodsType 53 | 0 54 | hideStatus 55 | 1 56 | imgUrl 57 | http://www.tequango.com/privilegeGo/image/1530512272780.jpg 58 | tag 59 | 甜美清新,便捷实用 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /TQGO/Resource/BimineData/UnicomBanner.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | bannerName 7 | 华为P20 8 | imgUrl 9 | http://www.tequango.com/privilegeGo/image/content/1537257775785.jpg 10 | openType 11 | 1 12 | openUrl 13 | HW_P20/3 14 | 15 | 16 | bannerName 17 | 华为荣耀10 18 | imgUrl 19 | http://www.tequango.com/privilegeGo/image/content/1526380127239.png 20 | openType 21 | 1 22 | openUrl 23 | HW_RY10/3 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TQGO/Resource/BimineData/homeBanner.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | bannerName 7 | cpb隔离专柜日版 8 | imgUrl 9 | http://www.tequango.com/privilegeGo/image/content/1551262998626.png 10 | openType 11 | 1 12 | openUrl 13 | RB_CPB_gls_black/2/eb4f99bb199bf4c9014e/MZXH 14 | 15 | 16 | bannerName 17 | club晚安粉-彩色玫瑰 18 | imgUrl 19 | http://www.tequango.com/privilegeGo/image/content/1551262911182.png 20 | openType 21 | 1 22 | openUrl 23 | club_waf_rose/2/eb4f99bb199bf4c9014e/MZXH 24 | 25 | 26 | bannerName 27 | 祖玛龙香水英国梨与小苍兰 28 | imgUrl 29 | http://www.tequango.com/privilegeGo/image/content/1533294325809.jpg 30 | openType 31 | 1 32 | openUrl 33 | HZP_mz_19220/2/eb4f99bb199bf4c9014e/MZXH 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /TQGO/Resource/BimineData/menu.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | code 7 | MZXH 8 | name 9 | 美妆洗护 10 | 11 | 12 | code 13 | PJZX 14 | name 15 | 配件专享 16 | 17 | 18 | code 19 | JJYX 20 | name 21 | 居家优享 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /TQGO/Tool/NetworkManager/NetworkManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkManager.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/14. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import Alamofire 11 | import UIKit 12 | 13 | typealias successClosure = (APIResultModel) -> (Void) 14 | typealias failClosure = (Any) -> (Void) 15 | 16 | public enum APIError { 17 | case apiError_done // 请求成功 18 | case apiError_netError(String) // 请求失败 网络 原因 19 | case apiError_serverMessage(String) // 请求失败 服务器原因 20 | } 21 | 22 | protocol APIInterfaceProtocol { 23 | var path:String {get} 24 | var parameters: [String: String]? { get } 25 | 26 | } 27 | 28 | class NetworkManager { 29 | 30 | private static var sharedSessionManager: SessionManager = { 31 | let configuration = URLSessionConfiguration.default 32 | configuration.timeoutIntervalForRequest = 0.2//请求超时时间 33 | return SessionManager(configuration: configuration) 34 | }() 35 | 36 | private static func commonAPIParameters()->Dictionary{ 37 | let userInfo = UserInfo.instance 38 | 39 | var parameters = [String : String]() 40 | parameters.updateValue(API_UAPKEY, forKey: "uapkey") 41 | parameters.updateValue(flowNumber(), forKey: "flowNo") 42 | parameters.updateValue(kPLATFORM_CODE, forKey: "platformCode") 43 | parameters.updateValue("2", forKey: "terminalType") 44 | parameters.updateValue(String.nowTimeWithFormat(format: kTimeFormat.format_yyyyMdHms.rawValue), forKey: "ts") 45 | parameters.updateValue(kIP, forKey: "ip") 46 | parameters.updateValue(kUUID!, forKey: "mac") 47 | parameters.updateValue("1", forKey: "dtype") 48 | parameters.updateValue(UIDevice.current.modelName, forKey: "brand") 49 | parameters.updateValue(kAppVersion as! String, forKey: "ver") 50 | if userInfo?.userNo != nil { 51 | parameters.updateValue("1", forKey: "userToken") 52 | } 53 | return parameters 54 | } 55 | 56 | // 生成随机数 yyyyMMddHHmmss+6位数 57 | private static func flowNumber()-> String { 58 | let timeSpan = String.nowTimeWithFormat(format:"yyyyMMddHHmmss") 59 | let randomNum = String(format: "%d", 100000 + (arc4random() % 100001)) 60 | let flowNumber = String(format: "%@%@", timeSpan,randomNum) 61 | return flowNumber 62 | } 63 | 64 | // 生成签名参数 65 | private static func SignParameters(params:[String:AnyObject])->Dictionary{//Dictionary 66 | //参数排序 67 | var parameters = params 68 | let keyArray = params.keys.sorted() 69 | var jointParamsStr = "" 70 | for key in keyArray { 71 | var val:AnyObject 72 | if key == "appMap" { 73 | val = ((params[key]! as! Dictionary) as NSObject).modelToJSONString as AnyObject 74 | val = (val as! String).replacingOccurrences(of: "\\/", with: "/") as AnyObject// 过滤AESBase64加密后带\字符的情况 75 | }else{ 76 | val = params[key]!; 77 | } 78 | let itemUrl = String(format: "%@=%@",key,val as! String) 79 | jointParamsStr = String(format: "%@%@|", jointParamsStr,itemUrl) 80 | } 81 | // 拼接商户的秘钥 82 | jointParamsStr = String(format: "%@%@", jointParamsStr,API_SECRET_KEY); 83 | DLog("\n************拼接商户的秘钥后的管道数据************:\n \(jointParamsStr)") 84 | // MD5加密 85 | let signStr = jointParamsStr.md5; 86 | parameters["sign"] = signStr as AnyObject 87 | DLog("\n************完成签名参数************:\n\(parameters)"); 88 | return parameters 89 | } 90 | 91 | private static func postRequest(interface:String,params:Dictionary,completion:@escaping successClosure,failed:@escaping failClosure){ 92 | // 构建全部参数 93 | var commonParas = commonAPIParameters() as [String : AnyObject] 94 | commonParas["operation"] = interface as AnyObject 95 | 96 | if params.isEmpty { 97 | commonParas.updateValue( "" as AnyObject, forKey: "appMap") 98 | }else{ 99 | commonParas["appMap"] = params as AnyObject 100 | } 101 | 102 | // 生成签名参数sign 103 | let paramDict = SignParameters(params: commonParas ) 104 | let headers: HTTPHeaders = [ 105 | "Accept": "application/json,text/json,text/javascript,text/plain,text/html", 106 | "Content-type" : "application/json" 107 | ] 108 | 109 | sharedSessionManager.request(API_BASE , 110 | method: .post, 111 | parameters: paramDict, 112 | encoding:JSONEncoding.default, 113 | headers:headers).responseJSON{ (response) in 114 | switch response.result { 115 | case .success(let value): 116 | DLog("接口路径:||-------------" + interface + "-------------||") 117 | DLog(JSON(value)) 118 | completion(APIResultModel.deserialize(from:value as? Dictionary) ?? APIResultModel()) 119 | return 120 | case .failure(let error): 121 | DLog(String(describing: error)) 122 | failed(error) 123 | 124 | return 125 | } 126 | } 127 | 128 | // Alamofire.request(API_BASE , 129 | // method: .post, 130 | // parameters: paramDict, 131 | // encoding:JSONEncoding.default, 132 | // headers:headers).responseString { (response) in 133 | // switch response.result { 134 | // case .success(let value): 135 | // if value.isEmpty{ 136 | // DLog(message: "-------请求结果为空------") 137 | // return 138 | // }else{ 139 | // let str = try? JSON(data: value.data(using: String.Encoding.utf8)!, options: JSONSerialization.ReadingOptions.mutableContainers) 140 | // DLog(message:"接口路径:||-------------" + interface + "-------------||") 141 | // DLog(message: str) 142 | // completion(APIResultModel.deserialize(from:value)!) 143 | // return 144 | // } 145 | // case .failure(let error): 146 | // DLog(message: String(describing: error)) 147 | // failed(error) 148 | // return 149 | // } 150 | // } 151 | } 152 | 153 | static func loadData(api:APIInterfaceProtocol,completionClosure: @escaping successClosure,failClosure:@escaping failClosure) -> Void { 154 | var paramsDict = [String:String]() 155 | _ = api.parameters?.map({ (key, value) in 156 | if !value.isEmpty { 157 | paramsDict.updateValue(value , forKey: key) 158 | } 159 | }) 160 | NetworkManager.postRequest(interface:api.path , params: paramsDict, completion: { (resopne) -> (Void) in 161 | completionClosure(resopne) 162 | }) { (fail) -> (Void) in 163 | failClosure(fail) 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /TQGO/Tool/NetworkManager/NetworkManagerLoginRegister.swift: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // NetworkManagerLoginRegister.swift 4 | // TQGO 5 | // 6 | // Created by YXY on 2019/10/31. 7 | // Copyright © 2019 Techwis. All rights reserved. 8 | // 9 | 10 | import Foundation 11 | 12 | 13 | enum APIInterfaceLoginRegister { 14 | case userLogin(params:[String:String]) 15 | 16 | } 17 | 18 | 19 | 20 | extension APIInterfaceLoginRegister:APIInterfaceProtocol{ 21 | 22 | var path:String{ 23 | switch self { 24 | case .userLogin(_): 25 | return "userLogin" 26 | } 27 | } 28 | var parameters: [String : String]?{ 29 | switch self { 30 | case .userLogin(let params): 31 | return params 32 | } 33 | } 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /TQGO/Tool/NetworkManager/NetworkManagerPromotion.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkManagerPromotion.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/3/19. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftyJSON 11 | 12 | 13 | enum APIInterfacePromotion { 14 | case queryPromoIndex(params:[String:String]) 15 | } 16 | 17 | extension APIInterfacePromotion:APIInterfaceProtocol{ 18 | var path:String{ 19 | switch self { 20 | case .queryPromoIndex: 21 | return "queryPromoIndex" 22 | } 23 | } 24 | 25 | var parameters: [String : String]?{ 26 | switch self { 27 | case .queryPromoIndex(let params): 28 | return params 29 | } 30 | } 31 | } 32 | 33 | -------------------------------------------------------------------------------- /TQGO/Tool/NetworkManager/NetworkManagerUnicom.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NetworkManagerUnicom.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2018/11/15. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import SwiftyJSON 11 | 12 | enum APIInterfaceUnicom { 13 | case queryUnicomZoneIndex(params:[String:String]) 14 | } 15 | 16 | extension APIInterfaceUnicom:APIInterfaceProtocol{ 17 | var path:String{ 18 | switch self { 19 | case .queryUnicomZoneIndex(_): 20 | return "queryUnicomZoneIndex" 21 | } 22 | } 23 | var parameters: [String : String]?{ 24 | switch self { 25 | case .queryUnicomZoneIndex(let params): 26 | return params 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TQGO/Tool/RealmTool/RealmManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RealmManager.swift 3 | // TQGO 4 | // realm工具类 5 | // Created by YXY on 2019/11/15. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | 12 | class RealmManager { 13 | //MARK: db路径 14 | static var url:URL = { 15 | let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first?.fileByAppendingPaths(byAppendingPaths: "/Realm") 16 | path?.fileCreateDirectory() 17 | let dbPath = path?.fileByAppendingPaths(byAppendingPaths:"/TQGODB.realm") 18 | return URL(string: dbPath!)! 19 | }() 20 | //MARK: realm单例 21 | static let instance :Realm = { 22 | 23 | let realm = try! Realm() 24 | DLog("realm数据库存储路径:\(realm.configuration.fileURL!.absoluteString)") 25 | return realm 26 | // 获取 Realm 文件的父目录 27 | // let folderPath = realm.configuration.fileURL!.deletingLastPathComponent().path 28 | // // 禁用此目录的文件保护 29 | // try? FileManager.default.setAttributes([FileAttributeKey.protectionKey : FileProtectionType.none], ofItemAtPath: folderPath) 30 | 31 | }() 32 | 33 | } 34 | 35 | extension RealmManager{ 36 | //MARK: 配置Realm 用于数据库迁移 37 | static func config () { 38 | 39 | Realm.Configuration.defaultConfiguration = Realm.Configuration( 40 | fileURL: url, 41 | schemaVersion: 1, 42 | migrationBlock: { migration, oldSchemaVersion in 43 | // We haven’t migrated anything yet, so oldSchemaVersion == 0 44 | if (oldSchemaVersion < 1) { 45 | // 1 46 | // Nothing to do! 47 | // Realm will automatically detect new properties and removed properties 48 | // And will update the schema on disk automatically 49 | // 2 50 | // 合并两个属性为一个新属性 51 | // migration.enumerateObjects(ofType: UserInfo.className()) { oldObject, newObject in 52 | // // combine name fields into a single field 53 | // let firstName = oldObject!["firstName"] as! String 54 | // let lastName = oldObject!["lastName"] as! String 55 | // newObject!["fullName"] = "\(firstName) \(lastName)" 56 | // } 57 | // 3 58 | // 属性重命名 59 | // The renaming operation should be done outside of calls to `enumerateObjects(ofType: _:)`. 60 | // migration.renameProperty(onType: UserInfo.className(), from: "yearsSinceBirth", to: "age") 61 | } 62 | }) 63 | 64 | 65 | Realm.asyncOpen { (realm, error) in 66 | if let _ = realm { 67 | print("Realm 服务器配置成功!") 68 | }else if let error = error { 69 | print("Realm 数据库配置失败:\(error.localizedDescription)") 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /TQGO/Tool/Regex/Regex.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Regex.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/11/22. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// 基于NSRegularExpression api 的正则处理工具类 12 | struct Regex { 13 | private let regularExpression: NSRegularExpression 14 | 15 | //使用正则表达式进行初始化 16 | public init(_ pattern: String, options: Options = []) throws { 17 | regularExpression = try NSRegularExpression( 18 | pattern: pattern, 19 | options: options.toNSRegularExpressionOptions 20 | ) 21 | } 22 | 23 | //正则匹配验证(true表示匹配成功) 24 | public func matches(_ string: String) -> Bool { 25 | return firstMatch(in: string) != nil 26 | } 27 | 28 | //获取第一个匹配结果 29 | public func firstMatch(in string: String) -> Match? { 30 | let firstMatch = regularExpression 31 | .firstMatch(in: string, options: [], 32 | range: NSRange(location: 0, length: string.utf16.count)) 33 | .map { Match(result: $0, in: string) } 34 | return firstMatch 35 | } 36 | 37 | //获取所有的匹配结果 38 | public func matches(in string: String) -> [Match] { 39 | let matches = regularExpression 40 | .matches(in: string, options: [], 41 | range: NSRange(location: 0, length: string.utf16.count)) 42 | .map { Match(result: $0, in: string) } 43 | return matches 44 | } 45 | 46 | //正则替换 47 | public func replacingMatches(in input: String, with template: String, 48 | count: Int? = nil) -> String { 49 | var output = input 50 | let matches = self.matches(in: input) 51 | let rangedMatches = Array(matches[0.. = { 112 | return Range(self.result.range, in: self.baseString)! 113 | }() 114 | 115 | //正则表达式中每个捕获组匹配的字符串 116 | public lazy var captures: [String?] = { 117 | let captureRanges = stride(from: 0, to: result.numberOfRanges, by: 1) 118 | .map(result.range) 119 | .dropFirst() 120 | .map { [unowned self] in 121 | Range($0, in: self.baseString) 122 | } 123 | 124 | return captureRanges.map { [unowned self] captureRange in 125 | if let captureRange = captureRange { 126 | return String(describing: self.baseString[captureRange]) 127 | } 128 | 129 | return nil 130 | } 131 | }() 132 | 133 | private let result: NSTextCheckingResult 134 | 135 | private let baseString: String 136 | 137 | //初始化 138 | internal init(result: NSTextCheckingResult, in string: String) { 139 | precondition( 140 | result.regularExpression != nil, 141 | "NSTextCheckingResult必需使用正则表达式" 142 | ) 143 | 144 | self.result = result 145 | self.baseString = string 146 | } 147 | 148 | //返回一个新字符串,根据“模板”替换匹配的字符串。 149 | public func string(applyingTemplate template: String) -> String { 150 | let replacement = result.regularExpression!.replacementString( 151 | for: result, 152 | in: baseString, 153 | offset: 0, 154 | template: template 155 | ) 156 | 157 | return replacement 158 | } 159 | 160 | //藐视信息 161 | public var description: String { 162 | return "Match<\"\(string)\">" 163 | } 164 | } 165 | } 166 | 167 | ////初始化正则工具类 下面样例验证一个邮箱地址的格式是否正确。 168 | //let pattern = "^([a-z0-9_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$" 169 | //let regex = try! Regex(pattern) 170 | // 171 | ////验证邮箱地址 172 | //let mailAddress = "admin@hangge.com" 173 | //if regex.matches(mailAddress) { 174 | // print("邮箱地址格式正确") 175 | //}else{ 176 | // print("邮箱地址格式有误") 177 | //} 178 | -------------------------------------------------------------------------------- /TQGO/Tool/ViewTool/YXYPageView/YXYMenuTitleView.swift: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // YXYMenuTitleView.swift 4 | // TQGO 5 | // 6 | // Created by YXY on 2019/3/21. 7 | // Copyright © 2019 Techwis. All rights reserved. 8 | // 9 | 10 | import Foundation 11 | import UIKit 12 | 13 | protocol YXYMenuMoveProtocol:class { 14 | func menuMoveProtocol(formIndex:NSInteger,toIndex:NSInteger) 15 | } 16 | 17 | 18 | enum YXYIndicatorType:NSInteger { 19 | case YXYIndicatorTypeDefault = 0,//默认与按钮长度相同 20 | YXYIndicatorTypeEqualTitle,//与文字长度相同 21 | YXYIndicatorTypeCustom,//自定义文字边缘延伸宽度 22 | YXYIndicatorTypeNone 23 | }//指示器类型枚举 24 | 25 | class YXYMenuTitleView: UIView { 26 | 27 | var indicatorType:YXYIndicatorType = .YXYIndicatorTypeDefault{ 28 | didSet{ 29 | moveIndicatorView() 30 | } 31 | } 32 | var titleArr: Array = [String]() 33 | var menuArr :Array = [UIButton]() 34 | var menuWidth:CGFloat = 60.0 35 | var selectIndex:NSInteger = 0{ 36 | didSet{ 37 | moveIndicatorView() 38 | } 39 | } 40 | var indicatorHeight:CGFloat = 2 41 | var indicatorExtension:CGFloat = 0 { 42 | didSet{ 43 | moveIndicatorView() 44 | } 45 | } 46 | 47 | weak var menuMoveDelegate:YXYMenuMoveProtocol? 48 | // 按钮间距离 49 | var menuMargin:CGFloat = 20{ 50 | didSet{ 51 | 52 | } 53 | } 54 | // 字体大小 55 | var menuFont:CGFloat = 14{ 56 | didSet{ 57 | 58 | } 59 | } 60 | 61 | lazy var menuScrollView: UIScrollView = { 62 | let menuScrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: self.width, height: self.height)) 63 | menuScrollView.showsHorizontalScrollIndicator = false 64 | menuScrollView.contentSize = CGSize(width: width, height: self.height) 65 | return menuScrollView 66 | }() 67 | 68 | lazy var indicatorView: UIView = { 69 | let indicatorView = UIView() 70 | indicatorView.backgroundColor = KCOLOR_Base.font_blue 71 | menuScrollView.addSubview(indicatorView) 72 | return indicatorView 73 | }() 74 | 75 | 76 | 77 | var menuScrollCount:CGFloat = 5 { 78 | didSet{ 79 | menuScrollView.contentSize = CGSize(width: menuScrollCount*menuWidth, height: self.height) 80 | } 81 | } 82 | 83 | override init(frame: CGRect) { 84 | super.init(frame: frame) 85 | 86 | } 87 | 88 | required init?(coder aDecoder: NSCoder) { 89 | fatalError("init(coder:) has not been implemented") 90 | } 91 | 92 | convenience init(frame:CGRect,titleArr:[String]) { 93 | self.init(frame:frame) 94 | self.backgroundColor = .white 95 | self.addSubview(self.menuScrollView) 96 | self.setupMenu(titleArr: titleArr) 97 | 98 | let line = UIView() 99 | line.backgroundColor = KCOLOR_Base.line 100 | self.addSubview(line) 101 | line.snp.makeConstraints { (make) in 102 | make.left.right.bottom.equalToSuperview() 103 | make.height.equalTo(0.5) 104 | } 105 | } 106 | 107 | override func layoutSubviews() { 108 | super.layoutSubviews() 109 | moveIndicatorView() 110 | } 111 | 112 | func moveIndicatorView(){ 113 | if menuArr.isEmpty { 114 | return 115 | } 116 | let selectedBtn = menuArr[selectIndex] 117 | let indicatorWidth:CGFloat = (selectedBtn.titleLabel?.text?.width(fontSize: menuFont))! 118 | 119 | UIView.animate(withDuration: 0.05, animations: { 120 | switch self.indicatorType { 121 | case .YXYIndicatorTypeDefault: 122 | self.indicatorView.frame = CGRect(x: selectedBtn.x, y: selectedBtn.bottomY-self.indicatorHeight, width: selectedBtn.width, height: self.indicatorHeight) 123 | break 124 | case .YXYIndicatorTypeEqualTitle: 125 | self.indicatorView.center = CGPoint(x: selectedBtn.centerX, y: selectedBtn.bottomY-self.indicatorHeight/2) 126 | self.indicatorView.bounds = CGRect(x: 0, y: 0,width:indicatorWidth , height: self.indicatorHeight) 127 | break 128 | case .YXYIndicatorTypeCustom: 129 | self.indicatorView.center = CGPoint(x: selectedBtn.centerX, y: selectedBtn.bottomY-self.indicatorHeight/2) 130 | self.indicatorView.bounds = CGRect(x: 0, y: 0,width:self.indicatorExtension , height: self.indicatorHeight) 131 | break 132 | case .YXYIndicatorTypeNone: 133 | self.indicatorView.frame = CGRect(x: 0, y: 0, width: 0, height: 0); 134 | break 135 | } 136 | }) { (finished) in 137 | 138 | } 139 | } 140 | 141 | func setupMenu(titleArr:[String]) { 142 | let _ = menuArr.map { (make) -> Void in 143 | make.removeFromSuperview() 144 | } 145 | menuArr.removeAll() 146 | if titleArr.isEmpty { 147 | return 148 | } 149 | var totalMenuWidth:CGFloat = 0 150 | for (_, val) in titleArr.enumerated() { 151 | let menuWidth = val.width(fontSize: menuFont) + menuMargin 152 | let menu = UIButton(type: UIButton.ButtonType.custom) 153 | menu.frame = CGRect(x: totalMenuWidth, y: 0.0, width: menuWidth, height: height) 154 | menu.setTitle(val, for: UIControl.State.normal) 155 | menu.setTitleColor(.black, for: .normal) 156 | menu.titleLabel?.font = UIFont.systemFont(ofSize: 14) 157 | menu.addTarget(self, action: #selector(menuAction), for: UIControl.Event.touchUpInside) 158 | menuScrollView.addSubview(menu) 159 | menuArr.append(menu) 160 | totalMenuWidth = totalMenuWidth + menuWidth 161 | } 162 | menuScrollView.contentSize.width = totalMenuWidth 163 | } 164 | 165 | @objc func menuAction(sender:UIButton){ 166 | let index = menuArr.firstIndex(of: sender) 167 | if selectIndex == index { 168 | return 169 | } 170 | if menuMoveDelegate != nil{ 171 | menuMoveDelegate?.menuMoveProtocol(formIndex: selectIndex, toIndex: index!) 172 | } 173 | selectIndex = index! 174 | moveIndicatorView() 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /TQGO/Tool/ViewTool/YXYPageView/YXYPageContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // YXYPageContentView.swift 3 | // TQGO 4 | // 5 | // Created by YXY on 2019/3/21. 6 | // Copyright © 2019 Techwis. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | protocol YXYContenViewProtocol:class { 12 | func pageContenViewDidScroll(fromIndex:NSInteger,toIndex:NSInteger) 13 | } 14 | 15 | let pageContentCollectionCell_id = "pageContentCollectionCell_id" 16 | 17 | class YXYPageContentView: UIView { 18 | var subVCArr:Array! 19 | private var parentVC:UIViewController! 20 | private var startOffsetX:CGFloat = 0; 21 | weak var pageContenViewDelegate:YXYContenViewProtocol? 22 | 23 | var contentViewCurrentIndex = 0{ 24 | didSet{ 25 | if (contentViewCurrentIndex < 0 || contentViewCurrentIndex > subVCArr.count-1) { 26 | return; 27 | } 28 | collectionView.scrollToItem(at: IndexPath(item: contentViewCurrentIndex, section: 0), at: .centeredHorizontally,animated: true) 29 | 30 | // [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForRow:contentViewCurrentIndex inSection:0] atScrollPosition:UICollectionViewScrollPositionNone animated:NO]; 31 | } 32 | } 33 | 34 | lazy var collectionView: UICollectionView = { 35 | 36 | var layout = UICollectionViewFlowLayout() 37 | layout.itemSize = self.bounds.size 38 | layout.minimumInteritemSpacing = 0 39 | layout.minimumLineSpacing = 0 40 | layout.scrollDirection = .horizontal 41 | 42 | let collectionView = UICollectionView(frame: self.bounds, collectionViewLayout: layout) 43 | collectionView.bounces = false; 44 | collectionView.delegate = self 45 | collectionView.dataSource = self 46 | collectionView.isPagingEnabled = true 47 | collectionView.backgroundColor = .white 48 | collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier:pageContentCollectionCell_id ) 49 | 50 | return collectionView 51 | }() 52 | 53 | convenience init(frame:CGRect,subVCArr:[PromotionSubVC],parentVC:UIViewController) { 54 | self.init(frame: frame) 55 | self.subVCArr = subVCArr 56 | self.parentVC = parentVC 57 | self.addSubview(self.collectionView) 58 | let _ = subVCArr.map { (vc) -> Void in 59 | self.parentVC.addChild(vc) 60 | } 61 | } 62 | } 63 | 64 | extension YXYPageContentView:UICollectionViewDelegate,UICollectionViewDataSource{ 65 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 66 | return subVCArr.count 67 | } 68 | 69 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 70 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: pageContentCollectionCell_id, for: indexPath) 71 | cell.addSubview((self.subVCArr?[indexPath.row].view)!) 72 | return cell 73 | 74 | } 75 | 76 | func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { 77 | startOffsetX = scrollView.contentOffset.x; 78 | 79 | } 80 | 81 | func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { 82 | let scrollView_W = scrollView.bounds.size.width; 83 | let currentOffsetX = scrollView.contentOffset.x; 84 | let startIndex = floor(startOffsetX/scrollView_W); 85 | let endIndex = floor(currentOffsetX/scrollView_W); 86 | if pageContenViewDelegate != nil { 87 | pageContenViewDelegate!.pageContenViewDidScroll(fromIndex: NSInteger(startIndex), toIndex: NSInteger(endIndex)) 88 | } 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /TQGO/Tool/ViewTool/YXYPageView/YXYPageView.swift: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // YXYPageView.swift 4 | // TQGO 5 | // 6 | // Created by YXY on 2019/3/21. 7 | // Copyright © 2019 Techwis. All rights reserved. 8 | // 9 | import UIKit 10 | 11 | class YXYPageView: UIView { 12 | 13 | lazy var segmentBarView: UIView = { 14 | let segmentBarView = UIView() 15 | return segmentBarView 16 | }() 17 | 18 | override init(frame: CGRect) { 19 | super.init(frame: frame) 20 | 21 | } 22 | 23 | required init?(coder aDecoder: NSCoder) { 24 | fatalError("init(coder:) has not been implemented") 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /TQGOTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TQGOTests/TQGOTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TQGOTests.swift 3 | // TQGOTests 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TQGO 11 | 12 | class TQGOTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | 28 | } 29 | 30 | func testPerformanceExample() { 31 | // This is an example of a performance test case. 32 | self.measure { 33 | // Put the code you want to measure the time of here. 34 | } 35 | } 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /TQGOUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /TQGOUITests/TQGOUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TQGOUITests.swift 3 | // TQGOUITests 4 | // 5 | // Created by YXY on 2018/7/9. 6 | // Copyright © 2018年 Techwis. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class TQGOUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | --------------------------------------------------------------------------------