younger_times
2023-07-13 c5579d0cb660bc6490fc932ad8e86248f57899d2
新增
21个文件已修改
1个文件已添加
726 ■■■■ 已修改文件
Podfile 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai.xcodeproj/project.pbxproj 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Config/Def.swift 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Config/Enums.swift 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Model/CommonModels.swift 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Network/OBSUploader.swift 276 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Network/Services.swift 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Activity/VC/ActivityDetailVC.xib 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/AddStudentVC.swift 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/AddStudentVC.xib 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/CourseDetailApplyVC.swift 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Course/VC/StudentCourseDetailVC.swift 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Home/VC/HomeVC.swift 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/TCell/StudentInfoTCell.swift 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/TCell/StudentInfoTCell.xib 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/View/CommonDatePickerView.swift 96 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/View/CommonDatePickerView.xib 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/View/StudentChooseView.swift 63 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Other/View/StudentChooseView.xib 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/RechargeRecordVC.swift 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/WelfareBillListVC.swift 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
WanPai/Root/Welfare/VC/WelfareFreeVC.swift 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
Podfile
@@ -14,6 +14,7 @@
  pod 'Alamofire'
  pod 'Lantern'
  pod 'SVProgressHUD'
  pod 'AliyunOSSiOS'
  post_install do |installer|
    installer.pods_project.targets.each do |target|
WanPai.xcodeproj/project.pbxproj
@@ -48,6 +48,7 @@
        13489E0A2A4C41A400155744 /* ProfileVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13489E082A4C41A400155744 /* ProfileVC.swift */; };
        13489E0B2A4C41A400155744 /* ProfileVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13489E092A4C41A400155744 /* ProfileVC.xib */; };
        134A750A2A5D0D64006D14AE /* RefreshModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134A75092A5D0D64006D14AE /* RefreshModel.swift */; };
        134BD50A2A5FF72900786819 /* OBSUploader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134BD5092A5FF72800786819 /* OBSUploader.swift */; };
        1353D5752A56CA0A00539FCA /* Services.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1353D5732A56CA0A00539FCA /* Services.swift */; };
        1353D5762A56CA0A00539FCA /* NetworkRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1353D5742A56CA0A00539FCA /* NetworkRequest.swift */; };
        1355ABFA2A4BE9FF002B25E4 /* WelfareCouponsSubListVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1355ABF92A4BE9FF002B25E4 /* WelfareCouponsSubListVC.swift */; };
@@ -294,6 +295,7 @@
        13489E082A4C41A400155744 /* ProfileVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileVC.swift; sourceTree = "<group>"; };
        13489E092A4C41A400155744 /* ProfileVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ProfileVC.xib; sourceTree = "<group>"; };
        134A75092A5D0D64006D14AE /* RefreshModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RefreshModel.swift; sourceTree = "<group>"; };
        134BD5092A5FF72800786819 /* OBSUploader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OBSUploader.swift; sourceTree = "<group>"; };
        1353D5732A56CA0A00539FCA /* Services.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Services.swift; sourceTree = "<group>"; };
        1353D5742A56CA0A00539FCA /* NetworkRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkRequest.swift; sourceTree = "<group>"; };
        1355ABF92A4BE9FF002B25E4 /* WelfareCouponsSubListVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelfareCouponsSubListVC.swift; sourceTree = "<group>"; };
@@ -578,6 +580,7 @@
        1353D5722A56CA0A00539FCA /* Network */ = {
            isa = PBXGroup;
            children = (
                134BD5092A5FF72800786819 /* OBSUploader.swift */,
                1353D5732A56CA0A00539FCA /* Services.swift */,
                1353D5742A56CA0A00539FCA /* NetworkRequest.swift */,
            );
@@ -1461,6 +1464,7 @@
                1376A6A12A4A7E1E00D4C851 /* CourseChargeTCell.swift in Sources */,
                13AFABC12A4AE3DC001FEA16 /* StudentRemarkListVC.swift in Sources */,
                8D6D58D12A39906F0003CFE6 /* ActivitySignupListSubVC.swift in Sources */,
                134BD50A2A5FF72900786819 /* OBSUploader.swift in Sources */,
                1375464B2A581716001FA77A /* HomeModel.swift in Sources */,
                8D70178D2A330E5700473C40 /* CourseDetailVC.swift in Sources */,
                1355ABFD2A4C15C7002B25E4 /* RechargeRecordVC.swift in Sources */,
@@ -1687,7 +1691,9 @@
                INFOPLIST_FILE = WanPai/Info.plist;
                INFOPLIST_KEY_CFBundleDisplayName = "玩湃生活";
                INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.sports";
                INFOPLIST_KEY_NSCameraUsageDescription = "WanPai需要使用使用使用相机,来上传学员头像、评论图片";
                INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "WanPai需要使用使用定位,来推荐、搜索您附近的门店";
                INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "WanPai需要使用使用使用相册,来上传学员头像、评论图片";
                INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
                INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
                INFOPLIST_KEY_UIMainStoryboardFile = Main;
@@ -1727,7 +1733,9 @@
                INFOPLIST_FILE = WanPai/Info.plist;
                INFOPLIST_KEY_CFBundleDisplayName = "玩湃生活";
                INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.sports";
                INFOPLIST_KEY_NSCameraUsageDescription = "WanPai需要使用使用使用相机,来上传学员头像、评论图片";
                INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "WanPai需要使用使用定位,来推荐、搜索您附近的门店";
                INFOPLIST_KEY_NSPhotoLibraryUsageDescription = "WanPai需要使用使用使用相册,来上传学员头像、评论图片";
                INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
                INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
                INFOPLIST_KEY_UIMainStoryboardFile = Main;
WanPai/Config/Def.swift
@@ -63,3 +63,11 @@
func alertSuccess(msg:String){
    SVProgressHUD.showSuccess(withStatus: msg)
}
func showHUD(_ text:String){
    SVProgressHUD.show(withStatus:text)
}
func hiddenHUD(){
    SVProgressHUD.dismiss()
}
WanPai/Config/Enums.swift
@@ -73,15 +73,22 @@
enum HomeItemType:Int,HandyJSONEnum{
        //1=报名玩湃课程,2=预约场地,3=报名赛事及活动,4=免费福利,5=线上课程积分,6=购买优惠门票,7=看视频得奖励,8=智慧球场)
    case none = 0
        ///报名玩湃课程
    case course = 1
        ///预约场地
    case booking = 2
        ///报名赛事及活动
    case activity = 3
        ///免费福利
    case welfare = 4
        ///线上课程积分
    case coin = 5
        ///购买优惠门票
    case ticket = 6
        /// 看视频得奖励
    case video = 7
        ///智慧球场
    case wisdomCourt = 8
    var defaultImg:UIImage{
@@ -142,6 +149,11 @@
    }
}
enum GenderType:Int,HandyJSONEnum{
    case  man = 1
    case  woman = 2
}
enum PaymentType:Int,HandyJSONEnum{
    case cash = 1 //现金
    case coin = 2 //玩湃币
WanPai/Model/CommonModels.swift
@@ -57,6 +57,17 @@
    var phone: String = ""
}
struct StudentProfileModel:HandyJSON{
    var birthday = ""
    var headImg = ""
    var height:Double = 0
    var idCard:String?
    var name = ""
    var phone:String?
    var sex:GenderType = .man
    var weight:Double = 0
}
struct CouponInfoModel:HandyJSON{
    ///有效时间
    var effectiveTime: String = ""
WanPai/Network/OBSUploader.swift
New file
@@ -0,0 +1,276 @@
//
//  OBSUploader.swift
//  QuanKeTong
//
//  Created by alvin_y on 2019/7/31.
//  Copyright © 2019 yang-wang. All rights reserved.
//
import UIKit
import RxSwift
import RxCocoa
import AliyunOSSiOS
import JQTools
import SwifterSwift
public extension UIImage{
    func uploadImgToService(name:String = String.jq_randomStr(len:10),scaleSize:CGSize? = nil)->Observable<String>{
        return OBSUploader.shared.uploadImage(key: name, image: self, scaleSize: scaleSize)
    }
}
public extension URL{
    func uploadVideoURLToService(name:String = String.jq_randomStr(len: 10))->Observable<String>{
        return OBSUploader.shared.uploadVideo(key: name, data: self)
    }
}
public extension Sequence where Iterator.Element == UIImage{
    func uploadImgToService(scaleSize:CGSize? = nil,needCompress:Bool? = nil)->Observable<[String]>{
        var keys = [String]()
        var imgs = [UIImage]()
        for (_,item) in enumerated() {
            keys.append(String.jq_randomStr(len: 10))
            imgs.append(item)
        }
        return OBSUploader.shared.uploadImage(keys: keys, image: imgs,scaleSize: scaleSize,needCompress:needCompress)
    }
}
public extension Sequence where Iterator.Element == URL{
    func uploadVideoToService(progress:OSSNetworkingUploadProgressBlock? = nil)->Observable<[String]>{
        var keys = [String]()
        var datas = [URL]()
        for (_,item) in enumerated() {
            keys.append(String.jq_randomStr(len: 10))
            datas.append(item)
        }
        return OBSUploader.shared.uploadVideo(keys: keys, video: datas,progress: progress)
    }
}
/// OBS上传文件
class OBSUploader: NSObject {
    struct Config {
        static var oss_domain = "https://we-park-life.oss-cn-beijing.aliyuncs.com/img"
        static var accessKeyId = "LTAI47eyqWWhBPXM"
        static var accessKeySecret = "orsYX78NvgXS9KbN7wCwRja1wkUwPc"
        static var bucketName = "we-park-life"
        static var endpoint = "oss-cn-beijing.aliyuncs.com"
    }
    static let shared = OBSUploader()
    lazy var credential: OSSCustomSignerCredentialProvider = OSSCustomSignerCredentialProvider(implementedSigner: { sign, error in
        var sign = OSSUtil.calBase64Sha1(withData: sign, withSecret: Config.accessKeySecret)
        if sign == nil {
            fatalError()
        }
        return "OSS \(Config.accessKeyId):\(sign!)"
    })!
    lazy var ossClient: OSSClient = OSSClient(endpoint: Config.endpoint, credentialProvider: credential)
    func uploadImage(keys: [String], image: [UIImage],scaleSize:CGSize? = nil,needCompress:Bool? = nil) -> Observable<[String]> {
        if keys.count == 0 {
            return Observable.just([])
        }
        var ob: [Observable<String>] = []
        let count = keys.count
        for i in 0..<count {
            ob.append(createTask(key: keys[i], image: image[i],scaleSize: scaleSize,needCompress:needCompress))
        }
        return Observable.zip(ob)
    }
    func uploadVideo(keys: [String], video: [URL],progress:OSSNetworkingUploadProgressBlock? = nil) -> Observable<[String]> {
        if keys.count == 0 {
            return Observable.just([])
        }
        var ob: [Observable<String>] = []
        let count = keys.count
        for i in 0..<count {
            ob.append(createTask(key: keys[i], url: video[i],progress: progress))
        }
        return Observable.zip(ob)
    }
    func uploadVideo(key:String,data:URL,progress:OSSNetworkingUploadProgressBlock? = nil) -> Observable<String>{
        if key.isEmpty {return Observable.just("")}
        var videoData:Data?
        do {
            videoData = try Data(contentsOf: data)
        } catch {
            return Observable.just("")
        }
            let client = ossClient
            return Observable<String>.create { ob in
                let put = OSSPutObjectRequest()
                put.bucketName = Config.bucketName
                put.objectKey = "\(key).mov"
                put.uploadingData = videoData!
                put.uploadProgress = { a,b,c in
                    progress?(a,b,c)
                }
                let task = client.putObject(put)
                task.continue({ r in
                    if r.error == nil {
                        ob.onNext("\(Config.oss_domain)/\(key).mov")
                    } else {
                        ob.onError(VideoUploadError.Failed)
                    }
                    return nil
                })
                return Disposables.create{}
            }.observe(on: MainScheduler.instance)
    }
    func uploadImage(key: String, image: UIImage,scaleSize:CGSize?) -> Observable<String> {
        if key.isEmpty {
            return Observable.just("")
        } else {
            let client = ossClient
            return Observable<String>.create{ ob in
                let put = OSSPutObjectRequest()
                put.bucketName = Config.bucketName
                put.objectKey = "\(key).png"
                if scaleSize != nil{
                    put.uploadingData = image.jq_scaled(to: scaleSize!).pngData()!
                }else{
                    put.uploadingData = image.pngData()!
                }
                let task = client.putObject(put)
                task.continue({ r in
                    if r.error == nil {
                        ob.onNext("\(Config.oss_domain)/\(key).png")
                    } else {
                        ob.onError(ImageUploadError.Failed)
                    }
                    return nil
                })
                return Disposables.create{
                }
            }.observe(on: MainScheduler.instance)
        }
    }
    /// 上传Data数据
    /// - Parameters:
    ///   - key: XXXX.png/Gif等
    ///   - data: 数据
    func uploadData(key:String,data:Data)->Observable<String>{
        if key.isEmpty{
            return Observable.just("")
        }else{
            let client = ossClient
            return Observable<String>.create{ ob in
                let put = OSSPutObjectRequest()
                put.bucketName = Config.bucketName
                put.objectKey = key
                put.uploadingData = data
                let task = client.putObject(put)
                task.continue({ r in
                    if r.error == nil {
                        ob.onNext("\(Config.oss_domain)/\(key)")
                    } else {
                        ob.onError(ImageUploadError.Failed)
                    }
                    return nil
                })
                return Disposables.create{
                }
            }.observe(on: MainScheduler.instance)
        }
    }
    func createTask(key: String, image: UIImage,scaleSize:CGSize? = nil,needCompress:Bool? = nil) -> Observable<String> {
        let client = ossClient
        return Observable<String>.create{ ob in
            let put = OSSPutObjectRequest()
            put.bucketName = Config.bucketName
            put.objectKey = "\(key).png"
            var img:UIImage?
            if scaleSize != nil{
                img = image.jq_scaled(to: scaleSize!)
            }else if needCompress != nil && needCompress!{
                img = image.jq_resizeImage()
            }else{
                img = image
            }
            put.uploadingData = img!.pngData()!
            let task = client.putObject(put)
            task.continue({ r in
                if r.error == nil {
                    ob.onNext("\(Config.oss_domain)/\(key).png")
                } else {
                    ob.onError(ImageUploadError.Failed)
                }
                return nil
            })
            return Disposables.create{
            }
        }.observe(on: MainScheduler.instance)
    }
    func createTask(key: String, url: URL,progress:OSSNetworkingUploadProgressBlock? = nil) -> Observable<String> {
        if key.isEmpty{return Observable.just("")}
        var videoData:Data?
        do {
            videoData = try Data(contentsOf: url)
        } catch {
            return Observable.just("")
        }
        let client = ossClient
        return Observable<String>.create{ ob in
            let put = OSSPutObjectRequest()
            put.bucketName = Config.bucketName
            put.objectKey = "\(key).mov"
            put.uploadingData = videoData!
            put.uploadProgress = { a,b,c in
                progress?(a,b,c)
            }
            let task = client.putObject(put)
            task.continue({ r in
                if r.error == nil {
                    ob.onNext("\(Config.oss_domain)/\(key).mov")
                } else {
                    ob.onError(ImageUploadError.Failed)
                }
                return nil
            })
            return Disposables.create{
            }
        }.observe(on: MainScheduler.instance)
    }
}
enum ImageUploadError: Error {
    case Failed
}
enum VideoUploadError:Error{
    case Failed
}
WanPai/Network/Services.swift
@@ -136,6 +136,29 @@
            .append(key: "price", value: "\(price)")
        return NetworkRequest.request(params: params, method: .post, progress: false)
    }
        /// 获取学员列表
    class func queryStudentList()->Observable<BaseResponse<[CourseDetailStudentModel]>>{
        let params = ParamsAppender.build(url: All_Url)
            .interface(url: "/account/api/student/queryStudentList")
        return NetworkRequest.request(params: params, method: .post, progress: false)
    }
        /// 添加学员
    class func addStudent(_ model:StudentProfileModel)->Observable<BaseResponse<SimpleModel>>{
        let params = ParamsAppender.build(url: All_Url)
            .interface(url: "/account/api/startCource/addData")
            .append(key: "birthday", value: model.birthday)
            .append(key: "headImg", value: model.headImg)
            .append(key: "height", value: model.height.string)
            .append(key: "idCard", value: model.idCard)
            .append(key: "name", value: model.name)
            .append(key: "phone", value: model.phone)
            .append(key: "sex", value: model.sex.rawValue)
            .append(key: "weight", value: model.weight.string)
        return NetworkRequest.request(params: params, method: .post, progress: false)
    }
}
    // MARK: -- 其他
WanPai/Root/Activity/VC/ActivityDetailVC.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_12" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
        <capability name="Named colors" minToolsVersion="9.0"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
@@ -542,8 +542,8 @@
                <constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="b8k-c2-Sjg" secondAttribute="bottom" constant="48" id="ALd-Ad-n3a"/>
                <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="b8k-c2-Sjg" secondAttribute="trailing" id="Rhl-P3-wPu"/>
                <constraint firstItem="lNv-6h-9fm" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="Rpd-eD-GWI"/>
                <constraint firstItem="b8k-c2-Sjg" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" id="Tak-Fe-kgU"/>
                <constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="lNv-6h-9fm" secondAttribute="trailing" id="U5X-Wh-bJU"/>
                <constraint firstItem="b8k-c2-Sjg" firstAttribute="top" secondItem="fnl-2z-Ty3" secondAttribute="top" id="c3T-5o-vuv"/>
                <constraint firstItem="b8k-c2-Sjg" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="jmS-ku-wrt"/>
            </constraints>
            <point key="canvasLocation" x="136.64122137404578" y="20.422535211267608"/>
@@ -552,7 +552,7 @@
    <resources>
        <image name="icon_local_mini" width="11" height="16"/>
        <namedColor name="FE6E0D">
            <color red="0.99599999189376831" green="0.4309999942779541" blue="0.050999999046325684" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
            <color red="0.99199998378753662" green="0.53299999237060547" blue="0.0080000003799796104" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
        </namedColor>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
WanPai/Root/Course/VC/AddStudentVC.swift
@@ -6,10 +6,23 @@
//
import UIKit
import QMUIKit
import JQTools
class AddStudentVC: BaseVC {
    @IBOutlet weak var img_profile: UIImageView!
    @IBOutlet weak var tf_name: UITextField!
    @IBOutlet weak var tf_gender: UITextField!
    @IBOutlet weak var tf_idCard: UITextField!
    @IBOutlet weak var tf_height: QMUITextField!
    @IBOutlet weak var tf_weight: QMUITextField!
    @IBOutlet weak var tf_phone: QMUITextField!
    @IBOutlet weak var tf_birthday: UITextField!
    var profileImg:UIImage?
    var studentModel = StudentProfileModel()
    
    var verifyIdCard:Bool = false
    
@@ -22,11 +35,111 @@
            self.tf_idCard.text = text
        }
        tf_idCard.inputView = idCardView
        let tap = UITapGestureRecognizer(target: self, action: #selector(userImgUploadAction))
        img_profile.isUserInteractionEnabled = true
        img_profile.addGestureRecognizer(tap)
    }
    override func setUI() {
        tf_birthday.delegate = self
        tf_gender.delegate = self
    }
    @objc func userImgUploadAction(){
        JQ_ImagePickerTool.getSharedInstance().singleImage({ [weak self] image in
            self?.img_profile.image = image
            self?.profileImg = image
        }, clipSize: CGSize(width: JQ_ScreenW, height: JQ_ScreenW))
    }
    
    
    @IBAction func completeAction(_ sender: UIButton) {
        guard profileImg != nil else {alertError(msg: "请上传学员头像");return}
        guard !tf_name.text!.isEmpty else {alertError(msg: tf_name.placeholder!);return}
        guard !tf_birthday.text!.isEmpty else {alertError(msg: "请选择生日");return}
        guard !tf_height.text!.isEmpty else {alertError(msg: tf_height.placeholder!);return}
        guard !tf_weight.text!.isEmpty else {alertError(msg: tf_weight.placeholder!);return}
        guard tf_height.text != "0" else {alertError(msg: "请输入正确的身高");return}
        guard tf_weight.text != "0" else {alertError(msg: "请输入正确的体重");return}
        if !tf_phone.isEmpty{
#if DEBUG
            guard tf_phone.text!.jq_isPhone else {alertError(msg: "请输入正确的手机号");return}
#endif
        }
        if !tf_idCard.isEmpty{
#if DEBUG
            guard tf_idCard.text!.jq_idCard() else {alertError(msg: "请输入正确的身份证号码");return}
#endif
        }
    
        studentModel.birthday = tf_birthday.text!
        studentModel.name = tf_name.text!
        studentModel.height = tf_height.text!.toDouble
        studentModel.weight = tf_weight.text!.toDouble
        studentModel.phone = tf_phone.text
        studentModel.idCard = tf_idCard.text
        studentModel.name = tf_name.text!
        if studentModel.headImg.isEmpty{
            showHUD("正在上传头像")
            profileImg!.uploadImgToService().subscribe(onNext: { [weak self] imgUrl in
                guard let weakSelf = self else { return }
                weakSelf.studentModel.headImg = imgUrl
                hiddenHUD()
                weakSelf.addStudent()
            }, onError: { error in
                hiddenHUD()
                alertError(msg: error.localizedDescription)
            }).disposed(by: disposeBag)
        }else{
            addStudent()
        }
    }
    private func addStudent(){
        Services.addStudent(studentModel).subscribe(onNext: { [weak self] data in
            guard let weakSelf = self else { return }
            alertSuccess(msg: "添加成功")
            DispatchQueue.main.asyncAfter(deadline: .now()+1) {
                weakSelf.navigationController?.popViewController()
            }
        }).disposed(by: disposeBag)
    }
    deinit{
        JQ_ImagePickerTool.destroy()
    }
}
extension AddStudentVC:UITextFieldDelegate{
    func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
        if textField == tf_birthday{
            CommonDatePickerView.show(before: 18, after: 0, type: .YMD) { year, month, day in
                textField.text = String(format: "%ld-%02ld-%02ld", year,month,day!)
            }
            return false
        }
        if textField == tf_gender{
            let alertVC = UIAlertController(title: "性别", message: nil, preferredStyle: .actionSheet)
            alertVC.addAction(UIAlertAction(title: "男", style: .default) { _ in
                self.tf_gender.text = "男"
            })
            alertVC.addAction(UIAlertAction(title: "女", style: .default) { _ in
                self.tf_gender.text = "女"
            })
            alertVC.addAction(UIAlertAction(title: "取消", style: .cancel))
            present(alertVC, animated: true)
            return false
        }
        return true
    }
}
 
WanPai/Root/Course/VC/AddStudentVC.xib
@@ -12,7 +12,14 @@
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AddStudentVC" customModule="WanPai" customModuleProvider="target">
            <connections>
                <outlet property="tf_idCard" destination="LD0-ej-DmH" id="cwL-wm-Ryg"/>
                <outlet property="img_profile" destination="5oh-CW-AiU" id="lde-3f-DOi"/>
                <outlet property="tf_birthday" destination="Gwh-N7-mRQ" id="Xsk-gB-nJj"/>
                <outlet property="tf_gender" destination="5l9-vJ-vil" id="Ch0-JK-GqD"/>
                <outlet property="tf_height" destination="Oj3-XX-8wG" id="K0c-bB-oPl"/>
                <outlet property="tf_idCard" destination="LD0-ej-DmH" id="Zob-2g-SgG"/>
                <outlet property="tf_name" destination="C9O-Cu-rp7" id="vcf-w1-Qts"/>
                <outlet property="tf_phone" destination="eT7-mO-3I8" id="1JO-Qe-MwA"/>
                <outlet property="tf_weight" destination="XDz-T3-HBc" id="POj-aw-Njj"/>
                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
            </connections>
        </placeholder>
@@ -372,6 +379,9 @@
                            <real key="value" value="20"/>
                        </userDefinedRuntimeAttribute>
                    </userDefinedRuntimeAttributes>
                    <connections>
                        <action selector="completeAction:" destination="-1" eventType="touchUpInside" id="xon-Wf-ldf"/>
                    </connections>
                </button>
            </subviews>
            <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
WanPai/Root/Course/VC/CourseDetailApplyVC.swift
@@ -102,7 +102,7 @@
    }
    
    @IBAction func studentAction(_ sender: QMUIButton) {
        StudentChooseView.show(itemType:.course) {
        StudentChooseView.show(itemType:.course,defaultStu: detailModel?.student) {
            
        } needAddClouse: { [weak self] () in
            let vc = AddStudentVC()
WanPai/Root/Course/VC/StudentCourseDetailVC.swift
@@ -131,7 +131,9 @@
    }
    @objc func datetimePickerAction(){
        CommonDatePickerView.show()
        CommonDatePickerView.show { year, month, day in
        }
    }
    required init?(coder: NSCoder) {
WanPai/Root/Home/VC/HomeVC.swift
@@ -148,41 +148,40 @@
extension HomeVC:UICollectionViewDelegate{
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if indexPath.row == 0{
//        let vc = JQ_CommonWebViewController(url: "https://whctw-qa.whitecoat.global/#/packageA/shares/index?booking_id=1b16387e-7dc4-4a0f-beb0-c919caf46fd2&token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoibWVtYmVyIiwibmFtZWlkIjoicnlwL2ZIK3Urck81TnBrQ3VtUnl1OW10dUUxb1JibXExUnVEbytjaXVaQWcxbTNLZzZ0S2daM1R1VDRqK3BIcyIsInJmci10a24iOiIwMDA2MDEwNjEwMjA4Ny1EOTU4ODk2My00QTZBLTRCMDgtQTQ0Ri1GODg1RkZCQTkzQ0MiLCJyZXF1ZXN0X3VwZGF0ZV9jb250YWN0X2luZm8iOiJGYWxzZSIsInJlcXVlc3RfYWN0aXZhdGVfYWNjb3VudCI6IkZhbHNlIiwiZm9yX2NoaWxkX3RoYXRfdHVybmVkXzIxIjoiRmFsc2UiLCJkZXZpY2VfaWQiOiIiLCJkZXZpY2VfdHlwZSI6IjEiLCJpc3MiOiJodHRwczovL3doY2FwaS1xYS53aGl0ZWNvYXQuZ2xvYmFsLyIsImF1ZCI6IjQxNGUxOTI3YTM4ODRmNjhhYmM3OWY3MjgzODM3ZmQxIiwiZXhwIjoxNzIwNjA1ODE3LCJuYmYiOjE2ODkwNjk4MTd9.T5hMybqAV7W_FuqX9WlPkZjgFBzkjw_XP5RGxlN2aUQ&device_id=raBw19aP3NkWnm8g93LOPmZ7iSffnu%3Ftoken%3DeyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoibWVtYmVyIiwibmFtZWlkIjoicnlwL2ZIK3Urck81TnBrQ3VtUnl1OW10dUUxb1JibXExUnVEbytjaXVaQWcxbTNLZzZ0S2daM1R1VDRqK3BIcyIsInJmci10a24iOiIwMDA2MDEwNjEwMjA4Ny1EOTU4ODk2My00QTZBLTRCMDgtQTQ0Ri1GODg1RkZCQTkzQ0MiLCJyZXF1ZXN0X3VwZGF0ZV9jb250YWN0X2luZm8iOiJGYWxzZSIsInJlcXVlc3RfYWN0aXZhdGVfYWNjb3VudCI6IkZhbHNlIiwiZm9yX2NoaWxkX3RoYXRfdHVybmVkXzIxIjoiRmFsc2UiLCJkZXZpY2VfaWQiOiIiLCJkZXZpY2VfdHlwZSI6IjEiLCJpc3MiOiJodHRwczovL3doY2FwaS1xYS53aGl0ZWNvYXQuZ2xvYmFsLyIsImF1ZCI6IjQxNGUxOTI3YTM4ODRmNjhhYmM3OWY3MjgzODM3ZmQxIiwiZXhwIjoxNzIwNjA1ODE3LCJuYmYiOjE2ODkwNjk4MTd9.T5hMybqAV7W_FuqX9WlPkZjgFBzkjw_XP5RGxlN2aUQ&device_id=raBw19aP3NkWnm8g93LOPmZ7iSffnu")
//        vc.modalPresentationStyle = .fullScreen
//        present(vc, animated: true)
//        push(vc: vc)
        let item = items[indexPath.row]
        switch item.type{
            case .course:
            let vc = CourseListVC()
            push(vc: vc)
        }
        if indexPath.row == 1{
            case .booking:
                let vc = YardListVC()
                push(vc: vc)
            case .activity:
            let vc = ActivityListVC()
            push(vc: vc)
        }
        if indexPath.row == 2{
            case .video:
            let vc = CourseOnlineListVC()
            vc.title = "看视频得奖励"
            push(vc: vc)
        }
        if indexPath.row == 3{
            case .coin:
            let vc = CourseOnlineListVC()
            vc.title = "线上课得积分"
            push(vc: vc)
        }
        if indexPath.row == 4{
            let vc = YardListVC()
            push(vc: vc)
        }
        if indexPath.row == 5{
            let vc = WelfareFreeVC()
            push(vc: vc)
        }
        if indexPath.row == 7{
            case .ticket:break
            case .wisdomCourt:
            let vc = WelfareWeeklyListVC()
            push(vc: vc)
            case .welfare:
                let vc = WelfareFreeVC()
                push(vc: vc)
            case .none:break
        }
    }
    
WanPai/Root/Other/TCell/StudentInfoTCell.swift
@@ -19,6 +19,7 @@
    @IBOutlet weak var label_name: UILabel!
    @IBOutlet weak var label_phone: UILabel!
    @IBOutlet weak var label_age: UILabel!
    @IBOutlet weak var btn_handle: UIButton!
    override func awakeFromNib() {
        super.awakeFromNib()
WanPai/Root/Other/TCell/StudentInfoTCell.xib
@@ -110,6 +110,7 @@
                </constraints>
            </tableViewCellContentView>
            <connections>
                <outlet property="btn_handle" destination="UXK-s8-fn9" id="icG-R5-OUD"/>
                <outlet property="label_age" destination="o0m-fp-glP" id="KJW-vV-H6Z"/>
                <outlet property="label_name" destination="0TW-3R-Kd5" id="Rxm-mg-OvM"/>
                <outlet property="label_phone" destination="A9b-WE-sPt" id="obG-aM-y0V"/>
WanPai/Root/Other/View/CommonDatePickerView.swift
@@ -10,13 +10,19 @@
class CommonDatePickerView: UIView,JQNibView{
    enum DatePickerType{
        case YMD,YM
    }
    @IBOutlet weak var view_container: UIView!
    @IBOutlet weak var cons_bottom: NSLayoutConstraint!
    @IBOutlet weak var pickerView: UIPickerView!
    private var type:DatePickerType!
    private var years = [Int]()
    private var months = [1,2,3,4,5,6,7,8,9,10,11,12]
    private var days = [Int]()
    private var clouse:((Int,Int,Int?)->Void)?
    override func awakeFromNib() {
        super.awakeFromNib()
@@ -25,16 +31,32 @@
        layoutIfNeeded()
        pickerView.delegate = self
        pickerView.dataSource = self
        years.append(Date().jq_nowYear())
        years.append(Date().jq_nowYear()-1)
        years.append(Date().jq_nowYear()-2)
        years.append(Date().jq_nowYear()-3)
    }
    static func show(){
        /// 初始化
        /// - Parameters:
        ///   - before: 向上N年
        ///   - after: 向下N年
        ///   - type: 显示状态
    static func show(before:Int = 0,after:Int = 0,type:DatePickerType = .YM,clouse:@escaping (Int,Int,Int?)->Void){
        let pickerView = CommonDatePickerView.jq_loadNibView()
        pickerView.type = type
        pickerView.clouse = clouse
        if before > 0{
            for i in 0...before{
                pickerView.years.append(Date().jq_nowYear() - i)
            }
        }
        if after > 0{
            for i in 0...after{
                pickerView.years.append(Date().jq_nowYear() + i)
            }
        }
        pickerView.years = pickerView.years.sorted()
        pickerView.frame = screnDelegate?.window?.frame ?? .zero
        screnDelegate?.window?.addSubview(pickerView)
@@ -43,6 +65,8 @@
            pickerView.alpha = 1
            pickerView.layoutIfNeeded()
        }
        pickerView.pickerView.reloadAllComponents()
    }
    @IBAction func hiddenAction(_ sender: UIButton) {
@@ -55,6 +79,36 @@
        }
    }
    @IBAction func completeAction(_ sender: UIButton) {
        var year:Int!
        var month:Int!
        var day:Int?
        switch type{
            case .YMD:
                year = years[pickerView.selectedRow(inComponent: 0)]
                month = months[pickerView.selectedRow(inComponent: 1)]
                day = pickerView.selectedRow(inComponent: 2) + 1
            case .YM:
                year = years[pickerView.selectedRow(inComponent: 0)]
                month = months[pickerView.selectedRow(inComponent: 1)]
            case .none:break
        }
        cons_bottom.constant = -(JQ_ScreenW * 0.6974)
        UIView.animate(withDuration: 0.4) {
            self.alpha = 0
            self.layoutIfNeeded()
        } completion: { _ in
            self.removeFromSuperview()
            self.clouse?(year,month,day)
        }
    }
    override func layoutSubviews() {
        super.layoutSubviews()
        view_container.jq_addCorners(corner: [.topLeft,.topRight], radius: 20)
@@ -65,6 +119,10 @@
    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if component == 0{
            pickerView.reloadComponent(1)
            if type == .YMD{pickerView.reloadComponent(2)}
        }
        if component == 1{
            pickerView.reloadComponent(2)
        }
    }
}
@@ -72,21 +130,28 @@
extension CommonDatePickerView:UIPickerViewDataSource{
    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        if component == 0{
            return years.count
        }
        if component == 0{return years.count
        }else if component == 1{
        if component == 1 && pickerView.selectedRow(inComponent: 0) == 0{
            return Date().jq_nowMonth()
        }
        return months.count
        }else if component == 2{
            let year = years[pickerView.selectedRow(inComponent: 0)]
            let month = months[pickerView.selectedRow(inComponent: 1)]
            return Date.jq_getDays(year, month)
        }
        return 0
    }
    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 2
        switch type{
            case .YM:return 2
            case .YMD:return 3
            case .none:return 0
    }
    }
    func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
        return 55
@@ -95,7 +160,10 @@
    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        if component == 0{
            return "\(years[row])年"
        }
        }else if component == 1{
        return "\(months[row])月"
        }else{
            return "\(row + 1)日"
        }
    }
}
WanPai/Root/Other/View/CommonDatePickerView.xib
@@ -34,6 +34,9 @@
                                    <real key="value" value="20"/>
                                </userDefinedRuntimeAttribute>
                            </userDefinedRuntimeAttributes>
                            <connections>
                                <action selector="completeAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="O51-A6-ZdT"/>
                            </connections>
                        </button>
                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="KFX-Q3-Kqk">
                            <rect key="frame" x="41" y="178" width="145.66666666666666" height="40"/>
WanPai/Root/Other/View/StudentChooseView.swift
@@ -8,6 +8,14 @@
import UIKit
import JQTools
import QMUIKit
import RxSwift
import RxCocoa
class StudentViewModel:RefreshModel<CourseDetailStudentModel>{
    override func api() -> (Observable<BaseResponse<[CourseDetailStudentModel]>>)? {
        return Services.queryStudentList()
    }
}
class StudentChooseView: UIView,JQNibView{
@@ -19,6 +27,8 @@
    private var clickClouse:(()->Void)!
    private var needAddClouse:(()->Void)!
    private var itemType:ItemType!
    private var selectStudents = [CourseDetailStudentModel]()
    private var viewModel = StudentViewModel()
    
    override func awakeFromNib() {
        super.awakeFromNib()
@@ -30,10 +40,17 @@
        tableView.separatorStyle = .none
        alpha = 0
        layoutIfNeeded()
        viewModel.configure(tableView,needMore: false)
        viewModel.beginRefresh()
    }
    
    static func show(itemType:ItemType,clickClouse:@escaping ()->Void,needAddClouse:@escaping ()->Void){
    static func show(itemType:ItemType,defaultStu:CourseDetailStudentModel? = nil,clickClouse:@escaping ()->Void,needAddClouse:@escaping ()->Void){
        let studentChooseView = StudentChooseView.jq_loadNibView()
        if defaultStu != nil{
            studentChooseView.selectStudents.append(defaultStu!)
        }
        if itemType == .course{
            studentChooseView.tableView.register(UINib(nibName: "StudentInfoTCell", bundle: nil), forCellReuseIdentifier: "_StudentInfoTCell")
        }else if itemType == .activity{
@@ -55,15 +72,13 @@
        }
    }
    
    @IBAction func closeAction(_ sender: UIButton) {
        closeAction()
    }
    
    @IBAction func addNewStudentAction(_ sender: QMUIButton) {
        self.cons_bottom.constant = -(JQ_ScreenW * 1.1)
        UIView.animate(withDuration: 0.4) {
            self.alpha = 0
        } completion: { _ in
            self.removeFromSuperview()
            self.needAddClouse!()
        }
        needAddClouse!()
        closeAction()
    }
    
    
@@ -74,32 +89,54 @@
        }
    }
    
    @IBAction func completeAction(_ sender: UIButton) {
    private func closeAction(){
        self.cons_bottom.constant = -(JQ_ScreenW * 1.1)
        UIView.animate(withDuration: 0.4) {
            self.alpha = 0
            self.layoutIfNeeded()
        } completion: { _ in
            self.removeFromSuperview()
            self.clickClouse!()
        }
    }
    @IBAction func completeAction(_ sender: UIButton) {
        clickClouse!()
        closeAction()
    }
}
extension StudentChooseView:UITableViewDelegate{
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    
         let item = viewModel.dataSource.value[indexPath.row]
        if self.selectStudents.contains(where: {$0.id == item.id}){
            if self.selectStudents.count == 1{
                alert(msg: "至少选择一位学员");return
            }
            self.selectStudents.remove(at: indexPath.row)
        }else{
            self.selectStudents.append(item)
        }
        tableView.reloadData()
    }
}
extension StudentChooseView:UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
        return viewModel.dataSource.value.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        if itemType == .course{
            let item = viewModel.dataSource.value[indexPath.row]
            let cell = tableView.dequeueReusableCell(withIdentifier: "_StudentInfoTCell") as! StudentInfoTCell
            if selectStudents.contains(where: {$0.id == item.id}){
                cell.btn_handle.setImage(UIImage(named: "btn_choose_s"), for: .normal)
            }else{
                cell.btn_handle.setImage(nil, for: .normal)
            }
            cell.studentModel = item
            return cell
        }else if itemType == .activity{
            let cell = tableView.dequeueReusableCell(withIdentifier: "_StudentInfo_2_TCell") as! StudentInfo_2_TCell
WanPai/Root/Other/View/StudentChooseView.xib
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_12" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21679"/>
        <capability name="Named colors" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@@ -74,12 +74,23 @@
                        <constraint firstItem="yxv-pI-vBX" firstAttribute="top" secondItem="7ap-MY-Ney" secondAttribute="top" constant="23" id="vTH-12-aze"/>
                    </constraints>
                </view>
                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="SpM-LP-wsu">
                    <rect key="frame" x="0.0" y="0.0" width="393" height="509"/>
                    <inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
                    <connections>
                        <action selector="closeAction:" destination="iN0-l3-epB" eventType="touchUpInside" id="yBy-d7-naf"/>
                    </connections>
                </button>
            </subviews>
            <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.5" colorSpace="custom" customColorSpace="sRGB"/>
            <constraints>
                <constraint firstItem="7ap-MY-Ney" firstAttribute="top" secondItem="SpM-LP-wsu" secondAttribute="bottom" id="9DJ-dZ-09M"/>
                <constraint firstItem="7ap-MY-Ney" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="9DX-KP-mJX"/>
                <constraint firstAttribute="trailing" secondItem="SpM-LP-wsu" secondAttribute="trailing" id="Iv2-Qs-iBg"/>
                <constraint firstAttribute="trailing" secondItem="7ap-MY-Ney" secondAttribute="trailing" id="Srr-Wv-dah"/>
                <constraint firstItem="SpM-LP-wsu" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="bKQ-hj-0tc"/>
                <constraint firstAttribute="bottom" secondItem="7ap-MY-Ney" secondAttribute="bottom" id="kSV-Gg-P7I"/>
                <constraint firstItem="SpM-LP-wsu" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="nXa-Iu-gYY"/>
            </constraints>
            <connections>
                <outlet property="btn_add" destination="yxv-pI-vBX" id="5Sm-2V-OfF"/>
@@ -93,7 +104,7 @@
    <resources>
        <image name="btn_add_1" width="16" height="16"/>
        <namedColor name="FE6E0D">
            <color red="0.99599999189376831" green="0.4309999942779541" blue="0.050999999046325684" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
            <color red="0.99199998378753662" green="0.53299999237060547" blue="0.0080000003799796104" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
        </namedColor>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
WanPai/Root/Welfare/VC/RechargeRecordVC.swift
@@ -45,7 +45,9 @@
    }
    @IBAction func datetimeAction(_ sender: UIButton) {
        CommonDatePickerView.show()
        CommonDatePickerView.show { year, month, day in
        }
    }
WanPai/Root/Welfare/VC/WelfareBillListVC.swift
@@ -129,7 +129,9 @@
    }
    @objc func datetimePickerAction(){
        CommonDatePickerView.show()
        CommonDatePickerView.show{ year, month, day in
        }
    }
    required init?(coder: NSCoder) {
WanPai/Root/Welfare/VC/WelfareFreeVC.swift
@@ -13,16 +13,4 @@
        super.viewDidLoad()
        title = "免费福利"
    }
    /*
    // MARK: - Navigation
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
    }
    */
}