- 苹果支付、分享
|
|
@ -225,6 +225,8 @@
|
||||||
30C4C01D2FDBF557009215C1 /* RemoveMemberViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */; };
|
30C4C01D2FDBF557009215C1 /* RemoveMemberViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */; };
|
||||||
30C4C0202FDC0EC5009215C1 /* GroupInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */; };
|
30C4C0202FDC0EC5009215C1 /* GroupInfoView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */; };
|
||||||
30C4C0222FDC0ED3009215C1 /* GroupInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */; };
|
30C4C0222FDC0ED3009215C1 /* GroupInfoVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */; };
|
||||||
|
30C6666C2FFB7C4000E62B25 /* IAPManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C6666B2FFB7C4000E62B25 /* IAPManager.swift */; };
|
||||||
|
30C6679E2FFB7FEF00E62B25 /* SharePopView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30C6679C2FFB7FEF00E62B25 /* SharePopView.swift */; };
|
||||||
30CCDE4E2FE26CEA00F5214A /* PayResultPopVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */; };
|
30CCDE4E2FE26CEA00F5214A /* PayResultPopVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */; };
|
||||||
30CCDE512FE2785D00F5214A /* SignInVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE502FE2785D00F5214A /* SignInVC.swift */; };
|
30CCDE512FE2785D00F5214A /* SignInVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE502FE2785D00F5214A /* SignInVC.swift */; };
|
||||||
30CCDE532FE2786600F5214A /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE522FE2786600F5214A /* SignInView.swift */; };
|
30CCDE532FE2786600F5214A /* SignInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 30CCDE522FE2786600F5214A /* SignInView.swift */; };
|
||||||
|
|
@ -524,6 +526,8 @@
|
||||||
30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveMemberViewModel.swift; sourceTree = "<group>"; };
|
30C4C01C2FDBF557009215C1 /* RemoveMemberViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoveMemberViewModel.swift; sourceTree = "<group>"; };
|
||||||
30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoView.swift; sourceTree = "<group>"; };
|
30C4C01F2FDC0EC5009215C1 /* GroupInfoView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoView.swift; sourceTree = "<group>"; };
|
||||||
30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoVC.swift; sourceTree = "<group>"; };
|
30C4C0212FDC0ED3009215C1 /* GroupInfoVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupInfoVC.swift; sourceTree = "<group>"; };
|
||||||
|
30C6666B2FFB7C4000E62B25 /* IAPManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IAPManager.swift; sourceTree = "<group>"; };
|
||||||
|
30C6679C2FFB7FEF00E62B25 /* SharePopView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharePopView.swift; sourceTree = "<group>"; };
|
||||||
30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayResultPopVC.swift; sourceTree = "<group>"; };
|
30CCDE4D2FE26CEA00F5214A /* PayResultPopVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PayResultPopVC.swift; sourceTree = "<group>"; };
|
||||||
30CCDE502FE2785D00F5214A /* SignInVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInVC.swift; sourceTree = "<group>"; };
|
30CCDE502FE2785D00F5214A /* SignInVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInVC.swift; sourceTree = "<group>"; };
|
||||||
30CCDE522FE2786600F5214A /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = "<group>"; };
|
30CCDE522FE2786600F5214A /* SignInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignInView.swift; sourceTree = "<group>"; };
|
||||||
|
|
@ -910,6 +914,7 @@
|
||||||
305A752A2FCA8C7000227D26 /* Theme */,
|
305A752A2FCA8C7000227D26 /* Theme */,
|
||||||
305A752C2FCA8C7000227D26 /* URL */,
|
305A752C2FCA8C7000227D26 /* URL */,
|
||||||
30D87CD52FDF9F1900E958FD /* MQTT */,
|
30D87CD52FDF9F1900E958FD /* MQTT */,
|
||||||
|
30C6666A2FFB7C3000E62B25 /* IAPManager */,
|
||||||
);
|
);
|
||||||
path = Manager;
|
path = Manager;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -1072,6 +1077,7 @@
|
||||||
30DC18592FD11E7A0041DCD1 /* Web */,
|
30DC18592FD11E7A0041DCD1 /* Web */,
|
||||||
30ACD54A2FF6332200174861 /* PopupWindow */,
|
30ACD54A2FF6332200174861 /* PopupWindow */,
|
||||||
30EFF3AD2FD7FF1400EB35D4 /* TextInput */,
|
30EFF3AD2FD7FF1400EB35D4 /* TextInput */,
|
||||||
|
30C6679D2FFB7FEF00E62B25 /* Share */,
|
||||||
);
|
);
|
||||||
path = Section;
|
path = Section;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -1436,6 +1442,22 @@
|
||||||
path = GroupInfo;
|
path = GroupInfo;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
30C6666A2FFB7C3000E62B25 /* IAPManager */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
30C6666B2FFB7C4000E62B25 /* IAPManager.swift */,
|
||||||
|
);
|
||||||
|
path = IAPManager;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
30C6679D2FFB7FEF00E62B25 /* Share */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
30C6679C2FFB7FEF00E62B25 /* SharePopView.swift */,
|
||||||
|
);
|
||||||
|
path = Share;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
30CCDE4F2FE2782700F5214A /* SignIn */ = {
|
30CCDE4F2FE2782700F5214A /* SignIn */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
|
@ -1840,6 +1862,7 @@
|
||||||
305A769C2FCA8C7000227D26 /* PopupViewController.swift in Sources */,
|
305A769C2FCA8C7000227D26 /* PopupViewController.swift in Sources */,
|
||||||
305A769D2FCA8C7000227D26 /* PopupViewController+Extension.swift in Sources */,
|
305A769D2FCA8C7000227D26 /* PopupViewController+Extension.swift in Sources */,
|
||||||
30EFF3C42FDA431D00EB35D4 /* ChangePhoneVC.swift in Sources */,
|
30EFF3C42FDA431D00EB35D4 /* ChangePhoneVC.swift in Sources */,
|
||||||
|
30C6666C2FFB7C4000E62B25 /* IAPManager.swift in Sources */,
|
||||||
305A769E2FCA8C7000227D26 /* TextArrowCell.swift in Sources */,
|
305A769E2FCA8C7000227D26 /* TextArrowCell.swift in Sources */,
|
||||||
305A769F2FCA8C7000227D26 /* TextContentArrowCell.swift in Sources */,
|
305A769F2FCA8C7000227D26 /* TextContentArrowCell.swift in Sources */,
|
||||||
30D87D042FE1336300E958FD /* NavigationVC.swift in Sources */,
|
30D87D042FE1336300E958FD /* NavigationVC.swift in Sources */,
|
||||||
|
|
@ -1925,6 +1948,7 @@
|
||||||
305A76CA2FCA8C7000227D26 /* AppSettings.swift in Sources */,
|
305A76CA2FCA8C7000227D26 /* AppSettings.swift in Sources */,
|
||||||
305A76CB2FCA8C7000227D26 /* Authorize.swift in Sources */,
|
305A76CB2FCA8C7000227D26 /* Authorize.swift in Sources */,
|
||||||
30CCDE552FE2903100F5214A /* SignInModel.swift in Sources */,
|
30CCDE552FE2903100F5214A /* SignInModel.swift in Sources */,
|
||||||
|
30C6679E2FFB7FEF00E62B25 /* SharePopView.swift in Sources */,
|
||||||
305A76CC2FCA8C7000227D26 /* FileTools.swift in Sources */,
|
305A76CC2FCA8C7000227D26 /* FileTools.swift in Sources */,
|
||||||
305A76CD2FCA8C7000227D26 /* Permission.swift in Sources */,
|
305A76CD2FCA8C7000227D26 /* Permission.swift in Sources */,
|
||||||
30D74AB02FEA13ED0050EB2C /* ScheduleVC.swift in Sources */,
|
30D74AB02FEA13ED0050EB2C /* ScheduleVC.swift in Sources */,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ enum OrderAPI {
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - type: 类型 member
|
/// - type: 类型 member
|
||||||
case rechargeInfo(type: String)
|
case rechargeInfo(type: String)
|
||||||
|
|
||||||
/// 支付参数
|
/// 支付参数
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - goodsId: 商品ID
|
/// - goodsId: 商品ID
|
||||||
|
|
@ -23,19 +23,24 @@ enum OrderAPI {
|
||||||
/// - source: center
|
/// - source: center
|
||||||
/// - extra: 额外参数
|
/// - extra: 额外参数
|
||||||
case orderPayParams(goodsId: String, payType: String, source: String, extra: [String:Any]=[:])
|
case orderPayParams(goodsId: String, payType: String, source: String, extra: [String:Any]=[:])
|
||||||
|
|
||||||
|
/// Apple 内购通知
|
||||||
|
case appleNotify(receipt: String, productId: String, transactionId: String)
|
||||||
}
|
}
|
||||||
|
|
||||||
extension OrderAPI: MultiTargetProtocol {
|
extension OrderAPI: MultiTargetProtocol {
|
||||||
|
|
||||||
var path: String {
|
var path: String {
|
||||||
switch self {
|
switch self {
|
||||||
case .rechargeInfo:
|
case .rechargeInfo:
|
||||||
return "api/order/goods"
|
return "api/order/goods"
|
||||||
case .orderPayParams:
|
case .orderPayParams:
|
||||||
return "api/order"
|
return "api/order"
|
||||||
|
case .appleNotify:
|
||||||
|
return "api/order/notify/apple"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var method: Moya.Method {
|
var method: Moya.Method {
|
||||||
switch self {
|
switch self {
|
||||||
case .rechargeInfo:
|
case .rechargeInfo:
|
||||||
|
|
@ -44,14 +49,14 @@ extension OrderAPI: MultiTargetProtocol {
|
||||||
return .post
|
return .post
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var task: Moya.Task {
|
var task: Moya.Task {
|
||||||
switch self {
|
switch self {
|
||||||
case let .rechargeInfo(type):
|
case let .rechargeInfo(type):
|
||||||
var params = Parameters()
|
var params = Parameters()
|
||||||
params["type"] = type
|
params["type"] = type
|
||||||
return .requestParameters(parameters: params, encoding: URLEncoding())
|
return .requestParameters(parameters: params, encoding: URLEncoding())
|
||||||
|
|
||||||
case let .orderPayParams(goodsId, payType, source, extra):
|
case let .orderPayParams(goodsId, payType, source, extra):
|
||||||
var params = Parameters()
|
var params = Parameters()
|
||||||
params["goods_id"] = goodsId
|
params["goods_id"] = goodsId
|
||||||
|
|
@ -60,6 +65,13 @@ extension OrderAPI: MultiTargetProtocol {
|
||||||
params["pay_source"] = "app"
|
params["pay_source"] = "app"
|
||||||
params["extra"] = extra
|
params["extra"] = extra
|
||||||
return .requestParameters(parameters: params, encoding: JSONEncoding())
|
return .requestParameters(parameters: params, encoding: JSONEncoding())
|
||||||
|
|
||||||
|
case let .appleNotify(receipt, productId, transactionId):
|
||||||
|
var params = Parameters()
|
||||||
|
params["receipt_data"] = receipt
|
||||||
|
params["product_id"] = productId
|
||||||
|
params["transaction_id"] = transactionId
|
||||||
|
return .requestParameters(parameters: params, encoding: JSONEncoding())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,25 +18,27 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
|
||||||
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
|
||||||
|
|
||||||
setupLocation()
|
setupLocation()
|
||||||
ApiManager.shared.setup()
|
ApiManager.shared.setup()
|
||||||
AppRouter.shared.setup()
|
AppRouter.shared.setup()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
||||||
// Override point for customization after application launch.
|
// Override point for customization after application launch.
|
||||||
|
|
||||||
|
IAPManager.shared.startObserving()
|
||||||
|
|
||||||
IQKeyboardManager.shared.isEnabled = true
|
IQKeyboardManager.shared.isEnabled = true
|
||||||
IQKeyboardManager.shared.enableAutoToolbar = false
|
IQKeyboardManager.shared.enableAutoToolbar = false
|
||||||
IQKeyboardManager.shared.resignOnTouchOutside = true
|
IQKeyboardManager.shared.resignOnTouchOutside = true
|
||||||
|
|
||||||
// 微信
|
// 微信
|
||||||
WXApi.registerApp(AppSettings.kAppsWXApiAppId, universalLink: AppSettings.kAppsUniversalLink)
|
WXApi.registerApp(AppSettings.kAppsWXApiAppId, universalLink: AppSettings.kAppsUniversalLink)
|
||||||
|
|
||||||
|
|
||||||
// 高德地图
|
// 高德地图
|
||||||
#if !targetEnvironment(simulator)
|
#if !targetEnvironment(simulator)
|
||||||
AMapServices.shared().apiKey = AppSettings.kAppsAMapAppId
|
AMapServices.shared().apiKey = AppSettings.kAppsAMapAppId
|
||||||
|
|
@ -53,19 +55,19 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
print("preGetToken: \(preDic)")
|
print("preGetToken: \(preDic)")
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// OpenIM
|
// OpenIM
|
||||||
GroupIMService.shared.initSDK()
|
GroupIMService.shared.initSDK()
|
||||||
|
|
||||||
window = UIWindow(frame: UIScreen.main.bounds)
|
window = UIWindow(frame: UIScreen.main.bounds)
|
||||||
window?.backgroundColor = .white
|
window?.backgroundColor = .white
|
||||||
window?.overrideUserInterfaceStyle = .light
|
window?.overrideUserInterfaceStyle = .light
|
||||||
window?.rootViewController = LaunchViewController()
|
window?.rootViewController = LaunchViewController()
|
||||||
window?.makeKeyAndVisible()
|
window?.makeKeyAndVisible()
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
|
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
|
||||||
print("📱 application open url: \(url.absoluteString) host: \(url.host ?? "")")
|
print("📱 application open url: \(url.absoluteString) host: \(url.host ?? "")")
|
||||||
// 处理支付宝支付结果(不限制 host,适应新版 SDK)
|
// 处理支付宝支付结果(不限制 host,适应新版 SDK)
|
||||||
|
|
@ -75,17 +77,17 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||||
guard let result = resultDic,
|
guard let result = resultDic,
|
||||||
let resultStatus = result["resultStatus"] as? String,
|
let resultStatus = result["resultStatus"] as? String,
|
||||||
resultStatus != "6001" else { return }
|
resultStatus != "6001" else { return }
|
||||||
|
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
else if url.host == "pay" {
|
else if url.host == "pay" {
|
||||||
return WXApi.handleOpen(url, delegate: self)
|
return WXApi.handleOpen(url, delegate: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupLocation() {
|
func setupLocation() {
|
||||||
let manager = AuthorizeManager.manager(type: .locationWhenInUse)
|
let manager = AuthorizeManager.manager(type: .locationWhenInUse)
|
||||||
if manager?.authorizeStatus() != .authorized {
|
if manager?.authorizeStatus() != .authorized {
|
||||||
|
|
@ -112,7 +114,7 @@ extension AppDelegate {
|
||||||
static var keyWindow: UIWindow? {
|
static var keyWindow: UIWindow? {
|
||||||
UIApplication.shared.windows.filter { $0.isKeyWindow }.first
|
UIApplication.shared.windows.filter { $0.isKeyWindow }.first
|
||||||
}
|
}
|
||||||
|
|
||||||
static var rootViewController: UIViewController? {
|
static var rootViewController: UIViewController? {
|
||||||
getRootViewController(keyWindow?.rootViewController)
|
getRootViewController(keyWindow?.rootViewController)
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +143,7 @@ extension AppDelegate: WXApiDelegate {
|
||||||
func onReq(_ req: BaseReq) {
|
func onReq(_ req: BaseReq) {
|
||||||
print(req)
|
print(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
func onResp(_ resp: BaseResp) {
|
func onResp(_ resp: BaseResp) {
|
||||||
if resp.isKind(of: PayResp.self),
|
if resp.isKind(of: PayResp.self),
|
||||||
let response: PayResp = resp as? PayResp {
|
let response: PayResp = resp as? PayResp {
|
||||||
|
|
@ -150,7 +152,7 @@ extension AppDelegate: WXApiDelegate {
|
||||||
if response.errCode == 0 { // 支付成功
|
if response.errCode == 0 { // 支付成功
|
||||||
DispatchQueue.global().async {
|
DispatchQueue.global().async {
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
QuickLocation/Assets.xcassets/PromotionalActivities/normal_bg.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2432@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2432@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/normal_bg.imageset/Group_2432@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/normal_bg.imageset/Group_2432@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 33 KiB |
22
QuickLocation/Assets.xcassets/PromotionalActivities/normal_on_bg.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "normal_on_bg@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "normal_on_bg@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/normal_on_bg.imageset/normal_on_bg@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/normal_on_bg.imageset/normal_on_bg@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 40 KiB |
22
QuickLocation/Assets.xcassets/PromotionalActivities/recommend_bg.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "recommend_bg@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "recommend_bg@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/recommend_bg.imageset/recommend_bg@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/recommend_bg.imageset/recommend_bg@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 62 KiB |
22
QuickLocation/Assets.xcassets/PromotionalActivities/recommend_icon.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2429@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2429@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/recommend_icon.imageset/Group_2429@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 882 B |
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/recommend_icon.imageset/Group_2429@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
22
QuickLocation/Assets.xcassets/PromotionalActivities/recommend_on_bg.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "recommend_on_bg@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "recommend_on_bg@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/recommend_on_bg.imageset/recommend_on_bg@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/recommend_on_bg.imageset/recommend_on_bg@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 77 KiB |
22
QuickLocation/Assets.xcassets/PromotionalActivities/tips_bg.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2428@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Group_2428@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/tips_bg.imageset/Group_2428@2x.png
vendored
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
QuickLocation/Assets.xcassets/PromotionalActivities/tips_bg.imageset/Group_2428@3x.png
vendored
Normal file
|
After Width: | Height: | Size: 28 KiB |
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"provides-namespace" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "friend@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "friend@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 6.2 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "moments@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "moments@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "url@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "url@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 5.5 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "apple@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "apple@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
|
@ -116,6 +116,8 @@ struct PopupWindowTimeModel: Mappable {
|
||||||
var pay_pop_time: Int = 0
|
var pay_pop_time: Int = 0
|
||||||
/// vip折扣
|
/// vip折扣
|
||||||
var min_discount: Double = 0
|
var min_discount: Double = 0
|
||||||
|
/// 默认支付方式 1 支付宝 2 微信
|
||||||
|
var pay_pop_type: Int = 0
|
||||||
|
|
||||||
init?(map: Map) {
|
init?(map: Map) {
|
||||||
|
|
||||||
|
|
@ -127,5 +129,6 @@ struct PopupWindowTimeModel: Mappable {
|
||||||
signup_tip <- map["signup_tip"]
|
signup_tip <- map["signup_tip"]
|
||||||
pay_pop_time <- map["pay_pop_time"]
|
pay_pop_time <- map["pay_pop_time"]
|
||||||
min_discount <- map["min_discount"]
|
min_discount <- map["min_discount"]
|
||||||
|
pay_pop_type <- map["pay_pop_type"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
//
|
||||||
|
// IAPManager.swift
|
||||||
|
// QuickLocation
|
||||||
|
//
|
||||||
|
// Created by 八条 on 2026/7/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
import StoreKit
|
||||||
|
import RxSwift
|
||||||
|
|
||||||
|
class IAPManager: NSObject {
|
||||||
|
static let shared = IAPManager()
|
||||||
|
private let disposeBag = DisposeBag()
|
||||||
|
|
||||||
|
private var currentGoodsId: String = ""
|
||||||
|
private var purchaseCompletion: ((Bool, String?) -> Void)?
|
||||||
|
|
||||||
|
func startObserving() {
|
||||||
|
SKPaymentQueue.default().add(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
func purchase(goodsId: String, completion: @escaping (Bool, String?) -> Void) {
|
||||||
|
currentGoodsId = goodsId
|
||||||
|
purchaseCompletion = completion
|
||||||
|
let request = SKProductsRequest(productIdentifiers: [goodsId])
|
||||||
|
request.delegate = self
|
||||||
|
request.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - SKProductsRequestDelegate
|
||||||
|
extension IAPManager: SKProductsRequestDelegate {
|
||||||
|
func productsRequest(_ request: SKProductsRequest, didReceive response: SKProductsResponse) {
|
||||||
|
guard let product = response.products.first else {
|
||||||
|
purchaseCompletion?(false, "商品不可用")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
SKPaymentQueue.default().add(SKPayment(product: product))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - SKPaymentTransactionObserver
|
||||||
|
extension IAPManager: SKPaymentTransactionObserver {
|
||||||
|
func paymentQueue(_ queue: SKPaymentQueue, updatedTransactions transactions: [SKPaymentTransaction]) {
|
||||||
|
for tx in transactions {
|
||||||
|
switch tx.transactionState {
|
||||||
|
case .purchased:
|
||||||
|
verifyReceipt(transaction: tx)
|
||||||
|
case .failed:
|
||||||
|
queue.finishTransaction(tx)
|
||||||
|
let msg = tx.error?.localizedDescription ?? "支付失败"
|
||||||
|
purchaseCompletion?(false, msg)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func verifyReceipt(transaction: SKPaymentTransaction) {
|
||||||
|
guard let receiptURL = Bundle.main.appStoreReceiptURL,
|
||||||
|
let receiptData = try? Data(contentsOf: receiptURL) else {
|
||||||
|
SKPaymentQueue.default().finishTransaction(transaction)
|
||||||
|
purchaseCompletion?(false, "获取凭证失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let receipt = receiptData.base64EncodedString()
|
||||||
|
let txId = transaction.transactionIdentifier ?? ""
|
||||||
|
|
||||||
|
OrderService.appleNotify(
|
||||||
|
receipt: receipt,
|
||||||
|
productId: currentGoodsId,
|
||||||
|
transactionId: txId
|
||||||
|
).subscribe(onNext: { [weak self] _ in
|
||||||
|
SKPaymentQueue.default().finishTransaction(transaction)
|
||||||
|
self?.purchaseCompletion?(true, nil)
|
||||||
|
}, onError: { [weak self] error in
|
||||||
|
SKPaymentQueue.default().finishTransaction(transaction)
|
||||||
|
self?.purchaseCompletion?(false, error.localizedDescription)
|
||||||
|
}).disposed(by: disposeBag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
import UIKit
|
import UIKit
|
||||||
import ObjectMapper
|
import ObjectMapper
|
||||||
import RxSwift
|
import RxSwift
|
||||||
|
import RxCocoa
|
||||||
|
|
||||||
class InviteJoinVC: BaseViewController {
|
class InviteJoinVC: BaseViewController {
|
||||||
|
|
||||||
|
|
@ -25,8 +26,13 @@ class InviteJoinVC: BaseViewController {
|
||||||
|
|
||||||
// Do any additional setup after loading the view.
|
// Do any additional setup after loading the view.
|
||||||
|
|
||||||
guard let model = groupInModel else { return }
|
// 分享
|
||||||
|
rootView.shareAppBtn.rx.tap.subscribe(onNext: { _ in
|
||||||
|
let url = "https://smartdrive.zuom8.cn/jisu/share/user/"
|
||||||
|
SharePopView.show(shareURL: url)
|
||||||
|
}).disposed(by: disposeBag)
|
||||||
|
|
||||||
|
guard let model = groupInModel else { return }
|
||||||
rootView.groupIcon.image = model.groupIcon
|
rootView.groupIcon.image = model.groupIcon
|
||||||
rootView.groupNameLab.text = model.name
|
rootView.groupNameLab.text = model.name
|
||||||
requestOperateGroup(key: model.group_key)
|
requestOperateGroup(key: model.group_key)
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ class HomeViewController: BaseViewController {
|
||||||
|
|
||||||
override func viewDidAppear(_ animated: Bool) {
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - MQTT 位置上报
|
// MARK: - MQTT 位置上报
|
||||||
|
|
@ -246,6 +246,13 @@ class HomeViewController: BaseViewController {
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.requestSendEmote(emoteIdx: emoteIdx)
|
self.requestSendEmote(emoteIdx: emoteIdx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 分享
|
||||||
|
rootView.interactionView.onShare = { [weak self] in
|
||||||
|
guard let self = self, let member = self.rootView.interactionView.currentMember else { return }
|
||||||
|
let url = "https://smartdrive.zuom8.cn/jisu/share/user/\(member.id)"
|
||||||
|
SharePopView.show(shareURL: url)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func bindViewModel() {
|
private func bindViewModel() {
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,17 @@ import Lottie
|
||||||
class InteractionView: UIView {
|
class InteractionView: UIView {
|
||||||
|
|
||||||
var disposeBag = DisposeBag()
|
var disposeBag = DisposeBag()
|
||||||
|
|
||||||
private static let emojiCols = 4
|
private static let emojiCols = 4
|
||||||
private static let emojiRows = 3
|
private static let emojiRows = 3
|
||||||
private static let emojiPerPage = emojiCols * emojiRows
|
private static let emojiPerPage = emojiCols * emojiRows
|
||||||
|
|
||||||
func configure(member: CircleMember) {
|
func configure(member: CircleMember) {
|
||||||
self.currentMember = member
|
self.currentMember = member
|
||||||
avaterImgView.image = UIImage(named: "UserIcon/\(member.avatar)")
|
avaterImgView.image = UIImage(named: "UserIcon/\(member.avatar)")
|
||||||
nameLab.text = member.name
|
nameLab.text = member.name
|
||||||
locationLab.text = member.address
|
locationLab.text = member.address
|
||||||
|
|
||||||
// 会员权益
|
// 会员权益
|
||||||
if AppContextManager.shared.vip > 1 {
|
if AppContextManager.shared.vip > 1 {
|
||||||
batteryInfoView.isHidden = member.battery.int == 0
|
batteryInfoView.isHidden = member.battery.int == 0
|
||||||
|
|
@ -33,7 +33,7 @@ class InteractionView: UIView {
|
||||||
let batteryPercent = min(CGFloat(batteryInt), 100)
|
let batteryPercent = min(CGFloat(batteryInt), 100)
|
||||||
batteryView.layoutChain.width(CGFloat(16 - 1) * batteryPercent / 100.0)
|
batteryView.layoutChain.width(CGFloat(16 - 1) * batteryPercent / 100.0)
|
||||||
batteryLab.text = "\(member.battery)%"
|
batteryLab.text = "\(member.battery)%"
|
||||||
|
|
||||||
// 趣味表情
|
// 趣味表情
|
||||||
lockView.isHidden = true
|
lockView.isHidden = true
|
||||||
}
|
}
|
||||||
|
|
@ -68,6 +68,12 @@ class InteractionView: UIView {
|
||||||
})
|
})
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
|
|
||||||
|
shareBtn.rx.tap
|
||||||
|
.subscribe(onNext: { [weak self] _ in
|
||||||
|
self?.onShare?()
|
||||||
|
})
|
||||||
|
.disposed(by: disposeBag)
|
||||||
|
|
||||||
// 绑定表情数据到 collectionView
|
// 绑定表情数据到 collectionView
|
||||||
emojiRelay
|
emojiRelay
|
||||||
.map { [SectionModel(model: "", items: $0)] }
|
.map { [SectionModel(model: "", items: $0)] }
|
||||||
|
|
@ -115,7 +121,7 @@ class InteractionView: UIView {
|
||||||
interestBg.isHidden = isFun
|
interestBg.isHidden = isFun
|
||||||
emojiRelay.accept(isFun ? UIView.funEmojiFileNames : UIView.emojiFileNames)
|
emojiRelay.accept(isFun ? UIView.funEmojiFileNames : UIView.emojiFileNames)
|
||||||
}
|
}
|
||||||
|
|
||||||
private lazy var dataSource: RxCollectionViewSectionedReloadDataSource<SectionModel<String, String>> = {
|
private lazy var dataSource: RxCollectionViewSectionedReloadDataSource<SectionModel<String, String>> = {
|
||||||
RxCollectionViewSectionedReloadDataSource<SectionModel<String, String>> { _, collectionView, indexPath, name in
|
RxCollectionViewSectionedReloadDataSource<SectionModel<String, String>> { _, collectionView, indexPath, name in
|
||||||
let cell: EmojiPanelCell = collectionView.dequeueReusableCell(for: indexPath)
|
let cell: EmojiPanelCell = collectionView.dequeueReusableCell(for: indexPath)
|
||||||
|
|
@ -130,7 +136,7 @@ class InteractionView: UIView {
|
||||||
(cell as? EmojiPanelCell)?.stopAnimation()
|
(cell as? EmojiPanelCell)?.stopAnimation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupUI() {
|
private func setupUI() {
|
||||||
addSubview(infoView)
|
addSubview(infoView)
|
||||||
infoView.addSubview(headerBgView)
|
infoView.addSubview(headerBgView)
|
||||||
|
|
@ -150,109 +156,109 @@ class InteractionView: UIView {
|
||||||
emojiView.addSubview(segmentView)
|
emojiView.addSubview(segmentView)
|
||||||
emojiView.addSubview(emojiCollectionView)
|
emojiView.addSubview(emojiCollectionView)
|
||||||
emojiView.addSubview(emojiPageControl)
|
emojiView.addSubview(emojiPageControl)
|
||||||
|
|
||||||
infoView.layoutChain.edges()
|
infoView.layoutChain.edges()
|
||||||
|
|
||||||
headerBgView.layoutChain
|
headerBgView.layoutChain
|
||||||
.edges(excludingEdge: .bottom)
|
.edges(excludingEdge: .bottom)
|
||||||
.height(134)
|
.height(134)
|
||||||
|
|
||||||
lineView.layoutChain
|
lineView.layoutChain
|
||||||
.top(13)
|
.top(13)
|
||||||
.width(36)
|
.width(36)
|
||||||
.height(4)
|
.height(4)
|
||||||
.centerX()
|
.centerX()
|
||||||
|
|
||||||
avaterImgView.layoutChain
|
avaterImgView.layoutChain
|
||||||
.top(25)
|
.top(25)
|
||||||
.left(25)
|
.left(25)
|
||||||
.width(50)
|
.width(50)
|
||||||
.height(50)
|
.height(50)
|
||||||
|
|
||||||
batteryInfoView.layoutChain
|
batteryInfoView.layoutChain
|
||||||
.leftToView(avaterImgView)
|
.leftToView(avaterImgView)
|
||||||
.rightToView(avaterImgView)
|
.rightToView(avaterImgView)
|
||||||
.bottomToView(avaterImgView)
|
.bottomToView(avaterImgView)
|
||||||
.height(12)
|
.height(12)
|
||||||
|
|
||||||
cornerView.layoutChain.edges()
|
cornerView.layoutChain.edges()
|
||||||
|
|
||||||
batteryIcon.layoutChain
|
batteryIcon.layoutChain
|
||||||
.left(7)
|
.left(7)
|
||||||
.centerY()
|
.centerY()
|
||||||
.width(16)
|
.width(16)
|
||||||
.height(8)
|
.height(8)
|
||||||
|
|
||||||
batteryView.layoutChain
|
batteryView.layoutChain
|
||||||
.topToView(batteryIcon)
|
.topToView(batteryIcon)
|
||||||
.leftToView(batteryIcon, offset: -1)
|
.leftToView(batteryIcon, offset: -1)
|
||||||
.bottomToView(batteryIcon)
|
.bottomToView(batteryIcon)
|
||||||
|
|
||||||
batteryLab.layoutChain
|
batteryLab.layoutChain
|
||||||
.leftToRightOfView(batteryIcon, offset: 4)
|
.leftToRightOfView(batteryIcon, offset: 4)
|
||||||
.right(5)
|
.right(5)
|
||||||
.centerY()
|
.centerY()
|
||||||
|
|
||||||
nameLab.layoutChain
|
nameLab.layoutChain
|
||||||
.topToView(avaterImgView, offset: 8)
|
.topToView(avaterImgView, offset: 8)
|
||||||
.leftToRightOfView(avaterImgView, offset: 15)
|
.leftToRightOfView(avaterImgView, offset: 15)
|
||||||
|
|
||||||
locationLab.layoutChain
|
locationLab.layoutChain
|
||||||
.topToBottomOfView(nameLab)
|
.topToBottomOfView(nameLab)
|
||||||
.leftToView(nameLab)
|
.leftToView(nameLab)
|
||||||
|
|
||||||
shareBtn.layoutChain
|
shareBtn.layoutChain
|
||||||
.right(15)
|
.right(15)
|
||||||
.centerY(avaterImgView)
|
.centerY(avaterImgView)
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
|
|
||||||
navigateBtn.layoutChain
|
navigateBtn.layoutChain
|
||||||
.rightToLeftOfView(shareBtn, offset: -10)
|
.rightToLeftOfView(shareBtn, offset: -10)
|
||||||
.centerY(avaterImgView)
|
.centerY(avaterImgView)
|
||||||
.width(30)
|
.width(30)
|
||||||
.height(30)
|
.height(30)
|
||||||
|
|
||||||
emojiView.layoutChain
|
emojiView.layoutChain
|
||||||
.topToBottomOfView(batteryInfoView, offset: 21)
|
.topToBottomOfView(batteryInfoView, offset: 21)
|
||||||
.edgesHorzontal(15)
|
.edgesHorzontal(15)
|
||||||
.height(276)
|
.height(276)
|
||||||
|
|
||||||
emojiBgView.layoutChain.edges()
|
emojiBgView.layoutChain.edges()
|
||||||
|
|
||||||
segmentView.layoutChain
|
segmentView.layoutChain
|
||||||
.edges(excludingEdge: .bottom)
|
.edges(excludingEdge: .bottom)
|
||||||
.height(56)
|
.height(56)
|
||||||
|
|
||||||
emojiPageControl.layoutChain
|
emojiPageControl.layoutChain
|
||||||
.centerX()
|
.centerX()
|
||||||
.height(28)
|
.height(28)
|
||||||
.bottom(13)
|
.bottom(13)
|
||||||
|
|
||||||
emojiCollectionView.layoutChain
|
emojiCollectionView.layoutChain
|
||||||
.top(51)
|
.top(51)
|
||||||
.edgesHorzontal()
|
.edgesHorzontal()
|
||||||
.height(180)
|
.height(180)
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy var infoView: UIView = {
|
lazy var infoView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .white
|
view.backgroundColor = .white
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var headerBgView: UIImageView = {
|
lazy var headerBgView: UIImageView = {
|
||||||
let view = UIImageView(image: UIImage(named: "Home/interaction_header"))
|
let view = UIImageView(image: UIImage(named: "Home/interaction_header"))
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var lineView: UIView = {
|
lazy var lineView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .white
|
view.backgroundColor = .white
|
||||||
view.cornerRadius = 2
|
view.cornerRadius = 2
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var avaterImgView: UIImageView = {
|
lazy var avaterImgView: UIImageView = {
|
||||||
let view = UIImageView()
|
let view = UIImageView()
|
||||||
view.backgroundColor = .lightGray
|
view.backgroundColor = .lightGray
|
||||||
|
|
@ -260,7 +266,7 @@ class InteractionView: UIView {
|
||||||
view.cornerRadius = 25
|
view.cornerRadius = 25
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var batteryInfoView: UIView = {
|
lazy var batteryInfoView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .clear
|
view.backgroundColor = .clear
|
||||||
|
|
@ -271,48 +277,48 @@ class InteractionView: UIView {
|
||||||
view.isHidden = true
|
view.isHidden = true
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var cornerView: UIView = {
|
lazy var cornerView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .white
|
view.backgroundColor = .white
|
||||||
view.cornerRadius = 6
|
view.cornerRadius = 6
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var batteryView: UIView = {
|
lazy var batteryView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = UIColor(hexStr: "#75E582")
|
view.backgroundColor = UIColor(hexStr: "#75E582")
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var batteryIcon: UIImageView = {
|
lazy var batteryIcon: UIImageView = {
|
||||||
let view = UIImageView()
|
let view = UIImageView()
|
||||||
view.backgroundColor = .clear
|
view.backgroundColor = .clear
|
||||||
view.image = UIImage(named: "Home/battery")
|
view.image = UIImage(named: "Home/battery")
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var batteryLab: UILabel = {
|
lazy var batteryLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.textColor = UIColor(hexStr: "#D4D4D4")
|
label.textColor = UIColor(hexStr: "#D4D4D4")
|
||||||
label.font = .systemFont(ofSize: 6, weight: .medium)
|
label.font = .systemFont(ofSize: 6, weight: .medium)
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var nameLab: UILabel = {
|
lazy var nameLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.textColor = UIColor(hexStr: "#0F2846")
|
label.textColor = UIColor(hexStr: "#0F2846")
|
||||||
label.font = .systemFont(ofSize: 14, weight: .semibold)
|
label.font = .systemFont(ofSize: 14, weight: .semibold)
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var locationLab: UILabel = {
|
lazy var locationLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.textColor = UIColor(hexStr: "#8D8D8D")
|
label.textColor = UIColor(hexStr: "#8D8D8D")
|
||||||
label.font = .systemFont(ofSize: 10, weight: .regular)
|
label.font = .systemFont(ofSize: 10, weight: .regular)
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var navigateBtn: UIButton = {
|
lazy var navigateBtn: UIButton = {
|
||||||
let btn = UIButton(type: .custom)
|
let btn = UIButton(type: .custom)
|
||||||
btn.backgroundColor = .white
|
btn.backgroundColor = .white
|
||||||
|
|
@ -321,7 +327,7 @@ class InteractionView: UIView {
|
||||||
btn.extendEdgeInsets = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 0)
|
btn.extendEdgeInsets = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 0)
|
||||||
return btn
|
return btn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var shareBtn: UIButton = {
|
lazy var shareBtn: UIButton = {
|
||||||
let btn = UIButton(type: .custom)
|
let btn = UIButton(type: .custom)
|
||||||
btn.backgroundColor = .white
|
btn.backgroundColor = .white
|
||||||
|
|
@ -330,36 +336,36 @@ class InteractionView: UIView {
|
||||||
btn.extendEdgeInsets = UIEdgeInsets(top: 30, left: 0, bottom: 30, right: 15)
|
btn.extendEdgeInsets = UIEdgeInsets(top: 30, left: 0, bottom: 30, right: 15)
|
||||||
return btn
|
return btn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var emojiView: UIView = {
|
lazy var emojiView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = UIColor(hexStr: "#E3F7FE")//.clear
|
view.backgroundColor = UIColor(hexStr: "#E3F7FE")//.clear
|
||||||
view.cornerRadius = 15
|
view.cornerRadius = 15
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var emojiBgView: UIView = {
|
lazy var emojiBgView: UIView = {
|
||||||
let view = UIImageView()//UIImageView(image: UIImage(named: "Home/emoji_bg"))
|
let view = UIImageView()//UIImageView(image: UIImage(named: "Home/emoji_bg"))
|
||||||
view.contentMode = .scaleAspectFill
|
view.contentMode = .scaleAspectFill
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var segmentView: UIView = {
|
lazy var segmentView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = UIColor(hexStr: "#E3F7FE")
|
view.backgroundColor = UIColor(hexStr: "#E3F7FE")
|
||||||
|
|
||||||
view.addSubview(normalBg)
|
view.addSubview(normalBg)
|
||||||
view.addSubview(interestBg)
|
view.addSubview(interestBg)
|
||||||
normalBg.layoutChain
|
normalBg.layoutChain
|
||||||
.top().left()
|
.top().left()
|
||||||
.height(56)
|
.height(56)
|
||||||
.widthToHeight(220/56)
|
.widthToHeight(220/56)
|
||||||
|
|
||||||
interestBg.layoutChain
|
interestBg.layoutChain
|
||||||
.top().right()
|
.top().right()
|
||||||
.height(56)
|
.height(56)
|
||||||
.widthToHeight(220/56)
|
.widthToHeight(220/56)
|
||||||
|
|
||||||
let normalLab = UILabel()
|
let normalLab = UILabel()
|
||||||
normalLab.text = "常规表情"
|
normalLab.text = "常规表情"
|
||||||
normalLab.font = .systemFont(ofSize: 12, weight: .semibold)
|
normalLab.font = .systemFont(ofSize: 12, weight: .semibold)
|
||||||
|
|
@ -369,7 +375,7 @@ class InteractionView: UIView {
|
||||||
normalLab.layoutChain
|
normalLab.layoutChain
|
||||||
.top(11)
|
.top(11)
|
||||||
.left().rightToCenterXOfView(view)
|
.left().rightToCenterXOfView(view)
|
||||||
|
|
||||||
let interesView = UIView()
|
let interesView = UIView()
|
||||||
interesView.backgroundColor = .clear
|
interesView.backgroundColor = .clear
|
||||||
view.addSubview(interesView)
|
view.addSubview(interesView)
|
||||||
|
|
@ -377,81 +383,81 @@ class InteractionView: UIView {
|
||||||
.top(11)
|
.top(11)
|
||||||
.right().leftToCenterXOfView(view)
|
.right().leftToCenterXOfView(view)
|
||||||
.height(18)
|
.height(18)
|
||||||
|
|
||||||
let interestLab = UILabel()
|
let interestLab = UILabel()
|
||||||
interestLab.text = "趣味表情"
|
interestLab.text = "趣味表情"
|
||||||
interestLab.font = .systemFont(ofSize: 12, weight: .semibold)
|
interestLab.font = .systemFont(ofSize: 12, weight: .semibold)
|
||||||
interestLab.textColor = .black
|
interestLab.textColor = .black
|
||||||
interestLab.textAlignment = .center
|
interestLab.textAlignment = .center
|
||||||
|
|
||||||
interesView.addSubview(interestLab)
|
interesView.addSubview(interestLab)
|
||||||
interestLab.layoutChain
|
interestLab.layoutChain
|
||||||
.top()
|
.top()
|
||||||
.centerX()
|
.centerX()
|
||||||
|
|
||||||
interesView.addSubview(lockView)
|
interesView.addSubview(lockView)
|
||||||
lockView.layoutChain
|
lockView.layoutChain
|
||||||
.leftToRightOfView(interestLab, offset: 4)
|
.leftToRightOfView(interestLab, offset: 4)
|
||||||
.centerY(interestLab)
|
.centerY(interestLab)
|
||||||
.width(18)
|
.width(18)
|
||||||
.height(18)
|
.height(18)
|
||||||
|
|
||||||
view.addSubview(emojiNormalBtn)
|
view.addSubview(emojiNormalBtn)
|
||||||
emojiNormalBtn.layoutChain
|
emojiNormalBtn.layoutChain
|
||||||
.top()
|
.top()
|
||||||
.left()
|
.left()
|
||||||
.rightToCenterXOfView(view)
|
.rightToCenterXOfView(view)
|
||||||
.height(40)
|
.height(40)
|
||||||
|
|
||||||
view.addSubview(emojiFunBtn)
|
view.addSubview(emojiFunBtn)
|
||||||
emojiFunBtn.layoutChain
|
emojiFunBtn.layoutChain
|
||||||
.top()
|
.top()
|
||||||
.right()
|
.right()
|
||||||
.leftToCenterXOfView(view)
|
.leftToCenterXOfView(view)
|
||||||
.height(40)
|
.height(40)
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var normalBg: UIImageView = {
|
lazy var normalBg: UIImageView = {
|
||||||
let view = UIImageView(image: UIImage(named: "Home/emoji_normal"))
|
let view = UIImageView(image: UIImage(named: "Home/emoji_normal"))
|
||||||
view.contentMode = .scaleAspectFill
|
view.contentMode = .scaleAspectFill
|
||||||
view.isHidden = true
|
view.isHidden = true
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var interestBg: UIImageView = {
|
lazy var interestBg: UIImageView = {
|
||||||
let view = UIImageView(image: UIImage(named: "Home/emoji_interest"))
|
let view = UIImageView(image: UIImage(named: "Home/emoji_interest"))
|
||||||
view.contentMode = .scaleAspectFill
|
view.contentMode = .scaleAspectFill
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var emojiNormalBtn: UIButton = {
|
lazy var emojiNormalBtn: UIButton = {
|
||||||
let btn = UIButton()
|
let btn = UIButton()
|
||||||
btn.backgroundColor = .clear
|
btn.backgroundColor = .clear
|
||||||
return btn
|
return btn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var emojiFunBtn: UIButton = {
|
lazy var emojiFunBtn: UIButton = {
|
||||||
let btn = UIButton()
|
let btn = UIButton()
|
||||||
btn.backgroundColor = .clear
|
btn.backgroundColor = .clear
|
||||||
return btn
|
return btn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var lockView: UIView = {
|
lazy var lockView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .white
|
view.backgroundColor = .white
|
||||||
view.cornerRadius = 9
|
view.cornerRadius = 9
|
||||||
|
|
||||||
let icon = UIImageView(image: UIImage(named: "Home/lock"))
|
let icon = UIImageView(image: UIImage(named: "Home/lock"))
|
||||||
view.addSubview(icon)
|
view.addSubview(icon)
|
||||||
icon.layoutChain
|
icon.layoutChain
|
||||||
.centerX()
|
.centerX()
|
||||||
.centerY()
|
.centerY()
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var emojiCollectionView: UICollectionView = {
|
lazy var emojiCollectionView: UICollectionView = {
|
||||||
let layout = CollectionHFlowLayout()
|
let layout = CollectionHFlowLayout()
|
||||||
let hSpacing: CGFloat = (kScreenWidth - 30 - CGFloat(InteractionView.emojiCols) * 50) / CGFloat(InteractionView.emojiCols + 1)
|
let hSpacing: CGFloat = (kScreenWidth - 30 - CGFloat(InteractionView.emojiCols) * 50) / CGFloat(InteractionView.emojiCols + 1)
|
||||||
|
|
@ -471,9 +477,10 @@ class InteractionView: UIView {
|
||||||
cv.delegate = self
|
cv.delegate = self
|
||||||
return cv
|
return cv
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var onNavigate: (() -> Void)?
|
var onNavigate: (() -> Void)?
|
||||||
var onSendEmote: ((Int) -> Void)?
|
var onSendEmote: ((Int) -> Void)?
|
||||||
|
var onShare: (() -> Void)?
|
||||||
var currentMember: CircleMember?
|
var currentMember: CircleMember?
|
||||||
|
|
||||||
lazy var emojiPageControl: UIPageControl = {
|
lazy var emojiPageControl: UIPageControl = {
|
||||||
|
|
@ -483,7 +490,7 @@ class InteractionView: UIView {
|
||||||
pc.pageIndicatorTintColor = UIColor(hexStr: "#7AD6FF", alpha: 0.4)
|
pc.pageIndicatorTintColor = UIColor(hexStr: "#7AD6FF", alpha: 0.4)
|
||||||
return pc
|
return pc
|
||||||
}()
|
}()
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
backgroundColor = .clear
|
backgroundColor = .clear
|
||||||
|
|
@ -559,17 +566,17 @@ final class EmojiPanelCell: UICollectionViewCell {
|
||||||
v.loopMode = .loop
|
v.loopMode = .loop
|
||||||
return v
|
return v
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var lockView: UIView = {
|
lazy var lockView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .clear
|
view.backgroundColor = .clear
|
||||||
view.isHidden = true
|
view.isHidden = true
|
||||||
|
|
||||||
let icon = UIImageView(image: UIImage(named: "Home/emoji_lock"))
|
let icon = UIImageView(image: UIImage(named: "Home/emoji_lock"))
|
||||||
view.addSubview(icon)
|
view.addSubview(icon)
|
||||||
icon.layoutChain
|
icon.layoutChain
|
||||||
.edges()
|
.edges()
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -603,7 +610,7 @@ final class EmojiPanelCell: UICollectionViewCell {
|
||||||
self.lottieView.play()
|
self.lottieView.play()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lockView.isHidden = AppContextManager.shared.vip > 1
|
lockView.isHidden = AppContextManager.shared.vip > 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -636,7 +643,7 @@ extension UIView {
|
||||||
.map { $0.replacingOccurrences(of: ".json", with: "") }
|
.map { $0.replacingOccurrences(of: ".json", with: "") }
|
||||||
.sorted()
|
.sorted()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
static var funEmojiFileNames: [String] = {
|
static var funEmojiFileNames: [String] = {
|
||||||
let paths = Bundle.main.paths(forResourcesOfType: "json", inDirectory: nil)
|
let paths = Bundle.main.paths(forResourcesOfType: "json", inDirectory: nil)
|
||||||
return paths
|
return paths
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,37 @@ import RxSwift
|
||||||
import RxCocoa
|
import RxCocoa
|
||||||
import RxDataSources
|
import RxDataSources
|
||||||
|
|
||||||
|
extension PromotionalActivitiesItem: Equatable {
|
||||||
|
static func == (lhs: Self, rhs: Self) -> Bool {
|
||||||
|
switch (lhs, rhs) {
|
||||||
|
case (.recommend(let a), .recommend(let b)): return a == b
|
||||||
|
case (.normal(let a), .normal(let b)): return a == b
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PromotionalActivitiesItem: IdentifiableType {
|
||||||
|
typealias Identity = String
|
||||||
|
var identity: String {
|
||||||
|
switch self {
|
||||||
|
case .recommend(let model): return model.goods_id
|
||||||
|
case .normal(let model): return model.goods_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PromotionalActivitiesVC: BaseViewController {
|
class PromotionalActivitiesVC: BaseViewController {
|
||||||
|
|
||||||
fileprivate var rootView: PromotionalActivitiesView!
|
fileprivate var rootView: PromotionalActivitiesView!
|
||||||
var onDismiss: (() -> Void)?
|
var onDismiss: (() -> Void)?
|
||||||
|
private var selectedGoodsId: String = ""
|
||||||
|
private let itemsRelay = BehaviorRelay<[PromotionalActivitiesItem]>(value: [])
|
||||||
|
|
||||||
|
var items: [PromotionalActivitiesItem] {
|
||||||
|
get { itemsRelay.value }
|
||||||
|
set { itemsRelay.accept(newValue) }
|
||||||
|
}
|
||||||
|
|
||||||
override func loadView() {
|
override func loadView() {
|
||||||
rootView = PromotionalActivitiesView(frame: UIScreen.main.bounds)
|
rootView = PromotionalActivitiesView(frame: UIScreen.main.bounds)
|
||||||
|
|
@ -23,8 +50,50 @@ class PromotionalActivitiesVC: BaseViewController {
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
// Do any additional setup after loading the view.
|
setupTableView()
|
||||||
requestRechargeInfo()
|
requestRechargeInfo()
|
||||||
|
|
||||||
|
rootView.confirmBtn.rx.tap.subscribe(onNext: { _ in
|
||||||
|
self.requestOrderPayParams()
|
||||||
|
}).disposed(by: disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupTableView() {
|
||||||
|
typealias Section = SectionModel<String, PromotionalActivitiesItem>
|
||||||
|
let dataSource = RxTableViewSectionedReloadDataSource<Section> { _, tableView, indexPath, item in
|
||||||
|
let isSelected = item.identity == self.selectedGoodsId
|
||||||
|
switch item {
|
||||||
|
case .recommend(let model):
|
||||||
|
let cell: PromotionalRecommendCell = tableView.dequeueReusableCell(for: indexPath)
|
||||||
|
cell.configure(model: model, isSelected: isSelected)
|
||||||
|
return cell
|
||||||
|
case .normal(let model):
|
||||||
|
let cell: PromotionalNormalCell = tableView.dequeueReusableCell(for: indexPath)
|
||||||
|
cell.configure(model: model, isSelected: isSelected)
|
||||||
|
return cell
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsRelay
|
||||||
|
.map { [SectionModel(model: "", items: $0)] }
|
||||||
|
.bind(to: rootView.tableView.rx.items(dataSource: dataSource))
|
||||||
|
.disposed(by: disposeBag)
|
||||||
|
|
||||||
|
itemsRelay
|
||||||
|
.subscribe(onNext: { [weak self] items in
|
||||||
|
self?.rootView.tableView.layoutChain.height(CGFloat(items.count) * 106 + 5)
|
||||||
|
self?.rootView.scrollContentView.layoutIfNeeded()
|
||||||
|
})
|
||||||
|
.disposed(by: disposeBag)
|
||||||
|
|
||||||
|
rootView.tableView.rx.itemSelected
|
||||||
|
.subscribe(onNext: { [weak self] indexPath in
|
||||||
|
guard let self = self else { return }
|
||||||
|
let item = self.itemsRelay.value[indexPath.row]
|
||||||
|
self.selectedGoodsId = item.identity
|
||||||
|
self.rootView.tableView.reloadData()
|
||||||
|
})
|
||||||
|
.disposed(by: disposeBag)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewDidDisappear(_ animated: Bool) {
|
override func viewDidDisappear(_ animated: Bool) {
|
||||||
|
|
@ -39,7 +108,103 @@ class PromotionalActivitiesVC: BaseViewController {
|
||||||
DLToast.showLoading()
|
DLToast.showLoading()
|
||||||
OrderService.rechargeInfo(type: "member").subscribe(onNext: { [weak self] response in
|
OrderService.rechargeInfo(type: "member").subscribe(onNext: { [weak self] response in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.rootView.startCountdown(endTime: 1769875199)
|
if let checkedId = response.list.first(where: { $0.checked })?.goods_id {
|
||||||
|
self.selectedGoodsId = checkedId
|
||||||
|
}
|
||||||
|
let items = response.list.map { model in
|
||||||
|
model.goods_id == "20042"
|
||||||
|
? PromotionalActivitiesItem.recommend(model: model)
|
||||||
|
: PromotionalActivitiesItem.normal(model: model)
|
||||||
|
}
|
||||||
|
self.items = items
|
||||||
|
self.rootView.startCountdown()
|
||||||
}).disposed(by: disposeBag)
|
}).disposed(by: disposeBag)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func requestOrderPayParams() {
|
||||||
|
guard let systemConfig = AppContextManager.shared.systemConfig, let timeConfig = systemConfig.timeConfig else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if timeConfig.pay_pop_type == 3 {
|
||||||
|
IAPManager.shared.purchase(goodsId: selectedGoodsId) { [weak self] success, msg in
|
||||||
|
guard let self = self else { return }
|
||||||
|
if success {
|
||||||
|
self.showPayResultPop(showCloseBtn: false,
|
||||||
|
status: true,
|
||||||
|
title: "支付成功",
|
||||||
|
message: "恭喜您!成功开通!",
|
||||||
|
confirmText: "确定", confirmBlock: {
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
|
}, cancelBlock: { })
|
||||||
|
} else {
|
||||||
|
self.showPayResultPop(status: false,
|
||||||
|
title: "支付失败",
|
||||||
|
message: msg ?? "很抱歉,请您重新支付!",
|
||||||
|
confirmText: "重新支付", confirmBlock: { },
|
||||||
|
cancelText: "取消", cancelBlock: {
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let payType = timeConfig.pay_pop_type == 1 ? "alipay" : "weixin"
|
||||||
|
dl.showLoading()
|
||||||
|
OrderService.orderPayParams(goodsId: selectedGoodsId,
|
||||||
|
payType: payType).subscribe(onNext: { response in
|
||||||
|
self.dl.dismiss()
|
||||||
|
guard let data = response.data else { return }
|
||||||
|
|
||||||
|
if payType == "weixin" { // 微信
|
||||||
|
// WXApi.registerApp(model.appId, universalLink: AppSettings.kAppsUniversalLink)
|
||||||
|
//
|
||||||
|
// let request: PayReq = PayReq()
|
||||||
|
// request.partnerId = model.partnerId
|
||||||
|
// request.prepayId = model.prepayId
|
||||||
|
// request.package = model.packageValue
|
||||||
|
// request.nonceStr = model.nonceStr
|
||||||
|
// request.timeStamp = UInt32(model.timeStamp) ?? 0
|
||||||
|
// request.sign = model.sign
|
||||||
|
// WXApi.send(request)
|
||||||
|
}
|
||||||
|
else if payType == "alipay" { // 支付宝
|
||||||
|
if let payParam = data["payParam"] as? String, let appId = data["payParam"] as? String {
|
||||||
|
AlipaySDK.defaultService().payOrder(payParam, fromScheme: "Alipay\(appId)") { resultDic in
|
||||||
|
print("支付宝callback -> \(resultDic)")
|
||||||
|
guard let result = resultDic,
|
||||||
|
let resultStatus = result["resultStatus"] as? String else { return }
|
||||||
|
/**
|
||||||
|
9000 订单支付成功。
|
||||||
|
8000 正在处理中,支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态。
|
||||||
|
4000 订单支付失败。
|
||||||
|
5000 重复请求。
|
||||||
|
6001 用户中途取消。
|
||||||
|
6002 网络连接出错。
|
||||||
|
6004 支付结果未知(有可能已经支付成功),请查询商家订单列表中订单的支付状态。
|
||||||
|
其它 其它支付错误。
|
||||||
|
*/
|
||||||
|
if resultStatus == "9000" {
|
||||||
|
self.showPayResultPop(showCloseBtn: false,
|
||||||
|
status: true,
|
||||||
|
title: "支付成功",
|
||||||
|
message: "恭喜您!成功开通\("")",
|
||||||
|
confirmText: "确定", confirmBlock: {
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
|
}, cancelBlock: { })
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.showPayResultPop(status: false,
|
||||||
|
title: "支付失败",
|
||||||
|
message: "很抱歉,请您重新支付!",
|
||||||
|
confirmText: "重新支付", confirmBlock: { }, cancelText: "取消", cancelBlock: {
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, onError: { _ in }).disposed(by: disposeBag)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,11 @@ import UIKit
|
||||||
import RxSwift
|
import RxSwift
|
||||||
import RxCocoa
|
import RxCocoa
|
||||||
|
|
||||||
|
enum PromotionalActivitiesItem {
|
||||||
|
case recommend(model: VipExpenseModel)
|
||||||
|
case normal(model: VipExpenseModel)
|
||||||
|
}
|
||||||
|
|
||||||
class PromotionalActivitiesView: UIView {
|
class PromotionalActivitiesView: UIView {
|
||||||
|
|
||||||
var disposeBag = DisposeBag()
|
var disposeBag = DisposeBag()
|
||||||
|
|
@ -17,7 +22,6 @@ class PromotionalActivitiesView: UIView {
|
||||||
backBtn.rx.tap.subscribe(onNext: { _ in
|
backBtn.rx.tap.subscribe(onNext: { _ in
|
||||||
VipWaivePopView.show()
|
VipWaivePopView.show()
|
||||||
}).disposed(by: disposeBag)
|
}).disposed(by: disposeBag)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupUI() {
|
private func setupUI() {
|
||||||
|
|
@ -121,13 +125,18 @@ class PromotionalActivitiesView: UIView {
|
||||||
.leftToRightOfView(iconView, offset: 4)
|
.leftToRightOfView(iconView, offset: 4)
|
||||||
.centerY(iconView)
|
.centerY(iconView)
|
||||||
|
|
||||||
|
scrollContentView.addSubview(tableView)
|
||||||
|
tableView.layoutChain
|
||||||
|
.topToBottomOfView(titleLab, offset: 0)
|
||||||
|
.edgesHorzontal()
|
||||||
|
|
||||||
let agreementView = UIView()
|
let agreementView = UIView()
|
||||||
infoView.addSubview(agreementView)
|
infoView.addSubview(agreementView)
|
||||||
agreementView.layoutChain
|
agreementView.layoutChain
|
||||||
.topToBottomOfView(titleLab, offset: 18)
|
.topToBottomOfView(tableView, offset: 15)
|
||||||
.left(15)
|
.left(15)
|
||||||
.right(15)
|
.right(15)
|
||||||
.height(30)
|
.height(16)
|
||||||
|
|
||||||
agreementView.addSubview(agreementCheckBtn)
|
agreementView.addSubview(agreementCheckBtn)
|
||||||
agreementCheckBtn.layoutChain
|
agreementCheckBtn.layoutChain
|
||||||
|
|
@ -138,7 +147,7 @@ class PromotionalActivitiesView: UIView {
|
||||||
|
|
||||||
agreementView.addSubview(agreementTextView)
|
agreementView.addSubview(agreementTextView)
|
||||||
agreementTextView.layoutChain
|
agreementTextView.layoutChain
|
||||||
.leftToRightOfView(agreementCheckBtn, offset: 6)
|
.leftToRightOfView(agreementCheckBtn, offset: 3)
|
||||||
.right(0)
|
.right(0)
|
||||||
.centerY()
|
.centerY()
|
||||||
.bottom(0)
|
.bottom(0)
|
||||||
|
|
@ -161,12 +170,24 @@ class PromotionalActivitiesView: UIView {
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
lazy var tableView: UITableView = {
|
||||||
|
let tableView = UITableView(frame: .zero, style: .plain)
|
||||||
|
tableView.backgroundColor = .clear
|
||||||
|
tableView.separatorStyle = .none
|
||||||
|
tableView.estimatedRowHeight = 106
|
||||||
|
tableView.isScrollEnabled = false
|
||||||
|
tableView.showsVerticalScrollIndicator = false
|
||||||
|
tableView.register(PromotionalNormalCell.self)
|
||||||
|
tableView.register(PromotionalRecommendCell.self)
|
||||||
|
return tableView
|
||||||
|
}()
|
||||||
|
|
||||||
lazy var bottomView: UIView = {
|
lazy var bottomView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .white
|
view.backgroundColor = .white
|
||||||
|
|
||||||
view.addSubview(countdownLabel)
|
view.addSubview(countdownContainer)
|
||||||
countdownLabel.layoutChain
|
countdownContainer.layoutChain
|
||||||
.top(11)
|
.top(11)
|
||||||
.centerX()
|
.centerX()
|
||||||
|
|
||||||
|
|
@ -186,6 +207,7 @@ class PromotionalActivitiesView: UIView {
|
||||||
btn.rx.tap.subscribe(onNext: { [weak btn] in
|
btn.rx.tap.subscribe(onNext: { [weak btn] in
|
||||||
btn?.isSelected.toggle()
|
btn?.isSelected.toggle()
|
||||||
}).disposed(by: disposeBag)
|
}).disposed(by: disposeBag)
|
||||||
|
btn.isSelected = true
|
||||||
return btn
|
return btn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -212,9 +234,59 @@ class PromotionalActivitiesView: UIView {
|
||||||
return tv
|
return tv
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var countdownLabel: UILabel = {
|
lazy var countdownContainer: UIStackView = {
|
||||||
|
let stack = UIStackView(arrangedSubviews: [countdownPrefixLabel, countdownMinLabel, countdownColonLabel, countdownSecLabel, countdownSuffixLabel])
|
||||||
|
stack.axis = .horizontal
|
||||||
|
stack.alignment = .center
|
||||||
|
stack.spacing = 0
|
||||||
|
return stack
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var countdownPrefixLabel: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
|
label.font = .systemFont(ofSize: 12)
|
||||||
|
label.textColor = UIColor(hexStr: "#FD501B")
|
||||||
|
label.text = "优惠活动倒计时 "
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var countdownMinLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .systemFont(ofSize: 12)
|
||||||
|
label.textColor = .white
|
||||||
|
label.backgroundColor = UIColor(hexStr: "#FD501B")
|
||||||
|
label.layer.cornerRadius = 2
|
||||||
|
label.clipsToBounds = true
|
||||||
label.textAlignment = .center
|
label.textAlignment = .center
|
||||||
|
label.text = "15"
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var countdownColonLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .systemFont(ofSize: 12)
|
||||||
|
label.textColor = UIColor(hexStr: "#FD501B")
|
||||||
|
label.text = ":"
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var countdownSecLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .systemFont(ofSize: 12)
|
||||||
|
label.textColor = .white
|
||||||
|
label.backgroundColor = UIColor(hexStr: "#FD501B")
|
||||||
|
label.layer.cornerRadius = 2
|
||||||
|
label.clipsToBounds = true
|
||||||
|
label.textAlignment = .center
|
||||||
|
label.text = "00"
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var countdownSuffixLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.font = .systemFont(ofSize: 12)
|
||||||
|
label.textColor = UIColor(hexStr: "#FD501B")
|
||||||
|
label.text = " 限时特惠"
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|
@ -228,11 +300,11 @@ class PromotionalActivitiesView: UIView {
|
||||||
return btn
|
return btn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private var countdownEndTime: TimeInterval = 0
|
private var countdownRemaining: Int = 15 * 60
|
||||||
private var countdownTimer: Timer?
|
private var countdownTimer: Timer?
|
||||||
|
|
||||||
func startCountdown(endTime: TimeInterval) {
|
func startCountdown() {
|
||||||
countdownEndTime = endTime
|
countdownRemaining = 15 * 60
|
||||||
updateCountdown()
|
updateCountdown()
|
||||||
countdownTimer?.invalidate()
|
countdownTimer?.invalidate()
|
||||||
countdownTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
|
countdownTimer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] _ in
|
||||||
|
|
@ -246,38 +318,17 @@ class PromotionalActivitiesView: UIView {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateCountdown() {
|
private func updateCountdown() {
|
||||||
let remaining = max(0, countdownEndTime - Date().timeIntervalSince1970)
|
if countdownRemaining > 0 {
|
||||||
let totalSeconds = Int(remaining)
|
countdownRemaining -= 1
|
||||||
let days = totalSeconds / 86400
|
|
||||||
let hours = (totalSeconds % 86400) / 3600
|
|
||||||
let minutes = (totalSeconds % 3600) / 60
|
|
||||||
let seconds = totalSeconds % 60
|
|
||||||
|
|
||||||
let attr = NSMutableAttributedString()
|
|
||||||
|
|
||||||
let normalStyle: [NSAttributedString.Key: Any] = [
|
|
||||||
.foregroundColor: UIColor(hexStr: "#FD501B"),
|
|
||||||
.font: UIFont.systemFont(ofSize: 12)
|
|
||||||
]
|
|
||||||
let timeStyle: [NSAttributedString.Key: Any] = [
|
|
||||||
.foregroundColor: UIColor.white,
|
|
||||||
.font: UIFont.systemFont(ofSize: 12),
|
|
||||||
.backgroundColor: UIColor(hexStr: "#FD501B")
|
|
||||||
]
|
|
||||||
|
|
||||||
attr.append(NSAttributedString(string: "优惠活动倒计时 ", attributes: normalStyle))
|
|
||||||
|
|
||||||
let timeStr: String
|
|
||||||
if days > 0 {
|
|
||||||
timeStr = String(format: "%d天%02d:%02d:%02d", days, hours, minutes, seconds)
|
|
||||||
} else {
|
|
||||||
timeStr = String(format: "%02d:%02d:%02d", hours, minutes, seconds)
|
|
||||||
}
|
}
|
||||||
attr.append(NSAttributedString(string: timeStr, attributes: timeStyle))
|
else {
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
attr.append(NSAttributedString(string: " 限时特惠", attributes: normalStyle))
|
return
|
||||||
|
}
|
||||||
countdownLabel.attributedText = attr
|
let min = countdownRemaining / 60
|
||||||
|
let sec = countdownRemaining % 60
|
||||||
|
countdownMinLabel.text = String(format: "%02d", min)
|
||||||
|
countdownSecLabel.text = String(format: "%02d", sec)
|
||||||
}
|
}
|
||||||
|
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
|
|
@ -319,3 +370,287 @@ extension PromotionalActivitiesView: UITextViewDelegate {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - PromotionalNormalCell
|
||||||
|
class PromotionalNormalCell: UITableViewCell {
|
||||||
|
|
||||||
|
func configure(model: VipExpenseModel, isSelected: Bool) {
|
||||||
|
priceLab.text = model.price
|
||||||
|
originPriceLab.text = "原价" + model.origin_price
|
||||||
|
originPriceLab.setupStrikethroughStyle()
|
||||||
|
goodsNameLab.text = model.goods_name
|
||||||
|
tipsLab.text = model.tips2
|
||||||
|
bgView.image = UIImage(named: isSelected ? "PromotionalActivities/normal_on_bg" : "PromotionalActivities/normal_bg")
|
||||||
|
priceLab.textColor = isSelected ? UIColor(hexStr: "#FF383C") : ThemeManager.shared.color.titleAuxColor
|
||||||
|
unitLab.textColor = isSelected ? UIColor(hexStr: "#FF383C") : ThemeManager.shared.color.titleAuxColor
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(style: CellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||||
|
selectionStyle = .none
|
||||||
|
backgroundColor = .clear
|
||||||
|
setupSubviews()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupSubviews() {
|
||||||
|
contentView.addSubview(bgView)
|
||||||
|
bgView.addSubview(unitLab)
|
||||||
|
bgView.addSubview(priceLab)
|
||||||
|
bgView.addSubview(originPriceLab)
|
||||||
|
bgView.addSubview(goodsNameLab)
|
||||||
|
bgView.addSubview(tipsLab)
|
||||||
|
|
||||||
|
bgView.layoutChain
|
||||||
|
.top(22)
|
||||||
|
.edgesHorzontal(15)
|
||||||
|
.bottom()
|
||||||
|
|
||||||
|
priceLab.layoutChain
|
||||||
|
.leftToRightOfView(unitLab, offset: 0)
|
||||||
|
.centerY()
|
||||||
|
|
||||||
|
unitLab.layoutChain
|
||||||
|
.left(32)
|
||||||
|
.centerY(bgView, offset: 9)
|
||||||
|
|
||||||
|
originPriceLab.layoutChain
|
||||||
|
.topToBottomOfView(priceLab, offset: -5)
|
||||||
|
.centerX(priceLab)
|
||||||
|
|
||||||
|
goodsNameLab.layoutChain
|
||||||
|
.leftToRightOfView(priceLab, offset: 27)
|
||||||
|
.bottomToCenterYOfView(bgView)
|
||||||
|
|
||||||
|
tipsLab.layoutChain
|
||||||
|
.leftToView(goodsNameLab)
|
||||||
|
.topToCenterYOfView(bgView, offset: 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func awakeFromNib() {
|
||||||
|
super.awakeFromNib()
|
||||||
|
// Initialization code
|
||||||
|
}
|
||||||
|
|
||||||
|
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||||
|
super.setSelected(selected, animated: animated)
|
||||||
|
|
||||||
|
// Configure the view for the selected state
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy var bgView: UIImageView = {
|
||||||
|
let view = UIImageView()
|
||||||
|
view.backgroundColor = .clear
|
||||||
|
view.contentMode = .scaleAspectFill
|
||||||
|
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var priceLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = UIColor(hexStr: "#FF383C")
|
||||||
|
label.font = .systemFont(ofSize: 40, weight: .bold)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var unitLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.text = "¥"
|
||||||
|
label.textColor = UIColor(hexStr: "#FF383C")
|
||||||
|
label.font = .systemFont(ofSize: 12, weight: .regular)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var originPriceLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = UIColor(hexStr: "#999999")
|
||||||
|
label.font = .systemFont(ofSize: 10, weight: .regular)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var goodsNameLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = ThemeManager.shared.color.titleAuxColor
|
||||||
|
label.font = .systemFont(ofSize: 18, weight: .semibold)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var tipsLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = ThemeManager.shared.color.contentColor
|
||||||
|
label.font = .systemFont(ofSize: 14, weight: .regular)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - PromotionalRecommendCell
|
||||||
|
class PromotionalRecommendCell: UITableViewCell {
|
||||||
|
|
||||||
|
func configure(model: VipExpenseModel, isSelected: Bool) {
|
||||||
|
tipsTitleLab.text = model.tips
|
||||||
|
priceLab.text = model.price
|
||||||
|
originPriceLab.text = "原价" + model.origin_price
|
||||||
|
originPriceLab.setupStrikethroughStyle()
|
||||||
|
goodsNameLab.text = model.goods_name
|
||||||
|
tipsLab.text = model.tips2
|
||||||
|
bgView.image = UIImage(named: isSelected ? "PromotionalActivities/recommend_on_bg" : "PromotionalActivities/recommend_bg")
|
||||||
|
priceLab.textColor = isSelected ? UIColor(hexStr: "#FF383C") : ThemeManager.shared.color.titleAuxColor
|
||||||
|
unitLab.textColor = isSelected ? UIColor(hexStr: "#FF383C") : ThemeManager.shared.color.titleAuxColor
|
||||||
|
}
|
||||||
|
|
||||||
|
override init(style: CellStyle, reuseIdentifier: String?) {
|
||||||
|
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
||||||
|
selectionStyle = .none
|
||||||
|
backgroundColor = .clear
|
||||||
|
setupSubviews()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func setupSubviews() {
|
||||||
|
contentView.addSubview(bgView)
|
||||||
|
bgView.addSubview(unitLab)
|
||||||
|
bgView.addSubview(priceLab)
|
||||||
|
bgView.addSubview(originPriceLab)
|
||||||
|
bgView.addSubview(goodsNameLab)
|
||||||
|
bgView.addSubview(tipsLab)
|
||||||
|
bgView.addSubview(recommendLab)
|
||||||
|
bgView.addSubview(recommendIcon)
|
||||||
|
bgView.addSubview(tipsTitleView)
|
||||||
|
tipsTitleView.addSubview(tipsTitleLab)
|
||||||
|
|
||||||
|
bgView.layoutChain
|
||||||
|
.top(22)
|
||||||
|
.edgesHorzontal(15)
|
||||||
|
.bottom()
|
||||||
|
|
||||||
|
tipsTitleView.layoutChain
|
||||||
|
.topToView(bgView, offset: -8)
|
||||||
|
.leftToView(bgView, offset: -6)
|
||||||
|
.width(94)
|
||||||
|
.height(35)
|
||||||
|
|
||||||
|
tipsTitleLab.layoutChain
|
||||||
|
.centerX()
|
||||||
|
.top(5)
|
||||||
|
|
||||||
|
priceLab.layoutChain
|
||||||
|
.leftToRightOfView(unitLab, offset: 0)
|
||||||
|
.centerY()
|
||||||
|
|
||||||
|
unitLab.layoutChain
|
||||||
|
.left(32)
|
||||||
|
.centerY(bgView, offset: 9)
|
||||||
|
|
||||||
|
originPriceLab.layoutChain
|
||||||
|
.topToBottomOfView(priceLab, offset: -5)
|
||||||
|
.centerX(priceLab)
|
||||||
|
|
||||||
|
goodsNameLab.layoutChain
|
||||||
|
.leftToRightOfView(priceLab, offset: 27)
|
||||||
|
.bottomToCenterYOfView(bgView, offset: -5)
|
||||||
|
|
||||||
|
tipsLab.layoutChain
|
||||||
|
.leftToView(goodsNameLab)
|
||||||
|
.topToCenterYOfView(bgView, offset: 8)
|
||||||
|
|
||||||
|
recommendLab.layoutChain
|
||||||
|
.top(8)
|
||||||
|
.right(24)
|
||||||
|
|
||||||
|
recommendIcon.layoutChain
|
||||||
|
.rightToLeftOfView(recommendLab, offset: -3)
|
||||||
|
.centerY(recommendLab)
|
||||||
|
.width(13)
|
||||||
|
.height(11)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
override func awakeFromNib() {
|
||||||
|
super.awakeFromNib()
|
||||||
|
// Initialization code
|
||||||
|
}
|
||||||
|
|
||||||
|
override func setSelected(_ selected: Bool, animated: Bool) {
|
||||||
|
super.setSelected(selected, animated: animated)
|
||||||
|
|
||||||
|
// Configure the view for the selected state
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy var bgView: UIImageView = {
|
||||||
|
let view = UIImageView()
|
||||||
|
view.backgroundColor = .clear
|
||||||
|
view.contentMode = .scaleAspectFill
|
||||||
|
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var priceLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = UIColor(hexStr: "#FF383C")
|
||||||
|
label.font = .systemFont(ofSize: 40, weight: .bold)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var unitLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.text = "¥"
|
||||||
|
label.textColor = UIColor(hexStr: "#FF383C")
|
||||||
|
label.font = .systemFont(ofSize: 12, weight: .regular)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var originPriceLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = UIColor(hexStr: "#999999")
|
||||||
|
label.font = .systemFont(ofSize: 10, weight: .regular)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var goodsNameLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = ThemeManager.shared.color.titleAuxColor
|
||||||
|
label.font = .systemFont(ofSize: 18, weight: .semibold)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var tipsTitleView: UIImageView = {
|
||||||
|
let view = UIImageView()
|
||||||
|
view.backgroundColor = .clear
|
||||||
|
view.image = UIImage(named: "PromotionalActivities/tips_bg")
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var tipsTitleLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = .white
|
||||||
|
label.font = .systemFont(ofSize: 12, weight: .semibold)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var tipsLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.textColor = ThemeManager.shared.color.contentColor
|
||||||
|
label.font = .systemFont(ofSize: 14, weight: .regular)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var recommendIcon: UIImageView = {
|
||||||
|
let view = UIImageView()
|
||||||
|
view.contentMode = .scaleAspectFill
|
||||||
|
view.image = UIImage(named: "PromotionalActivities/recommend_icon")
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
lazy var recommendLab: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.text = "80%的用户选择"
|
||||||
|
label.textColor = .white
|
||||||
|
label.font = .systemFont(ofSize: 12, weight: .medium)
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
//
|
||||||
|
// SharePopView.swift
|
||||||
|
// QuickLocation
|
||||||
|
//
|
||||||
|
// Created by 八条 on 2026/7/3.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
class SharePopView: UIView {
|
||||||
|
|
||||||
|
private static let shared = SharePopView(frame: CGRect(origin: .zero, size: kScreenSize))
|
||||||
|
private var shareURL: String = ""
|
||||||
|
|
||||||
|
private let contentHeight: CGFloat = 191 + kSafeBottomMargin
|
||||||
|
|
||||||
|
static func show(shareURL: String) {
|
||||||
|
guard let superView = kKeyWindow else { return }
|
||||||
|
|
||||||
|
if SharePopView.shared.superview != nil {
|
||||||
|
SharePopView.shared.dismiss(animated: false)
|
||||||
|
}
|
||||||
|
|
||||||
|
SharePopView.shared.shareURL = shareURL
|
||||||
|
SharePopView.shared.bgView.alpha = 0
|
||||||
|
superView.addSubview(SharePopView.shared)
|
||||||
|
superView.bringSubviewToFront(SharePopView.shared)
|
||||||
|
|
||||||
|
SharePopView.shared.contentView.transform = CGAffineTransform(translationX: 0, y: SharePopView.shared.contentHeight)
|
||||||
|
UIView.animate(withDuration: 0.3, delay: 0, options: .curveEaseOut) {
|
||||||
|
SharePopView.shared.bgView.alpha = 1
|
||||||
|
SharePopView.shared.contentView.transform = .identity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func dismiss(animated: Bool = true) {
|
||||||
|
if animated {
|
||||||
|
UIView.animate(withDuration: 0.25, delay: 0, options: .curveEaseIn) {
|
||||||
|
self.bgView.alpha = 0
|
||||||
|
self.contentView.transform = CGAffineTransform(translationX: 0, y: self.contentHeight)
|
||||||
|
} completion: { _ in
|
||||||
|
self.removeFromSuperview()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
removeFromSuperview()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleBgTap() {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleWeChatTap() {
|
||||||
|
shareToWeChat(scene: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleMomentsTap() {
|
||||||
|
shareToWeChat(scene: 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func handleLinkTap() {
|
||||||
|
UIPasteboard.general.string = shareURL
|
||||||
|
DLToast.showSuccess(text: "链接已复制")
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func shareToWeChat(scene: Int32) {
|
||||||
|
let message = WXMediaMessage()
|
||||||
|
message.title = kAppName
|
||||||
|
let webpage = WXWebpageObject()
|
||||||
|
webpage.webpageUrl = shareURL
|
||||||
|
message.mediaObject = webpage
|
||||||
|
|
||||||
|
let req = SendMessageToWXReq()
|
||||||
|
req.bText = false
|
||||||
|
req.message = message
|
||||||
|
req.scene = scene
|
||||||
|
WXApi.send(req)
|
||||||
|
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - UI
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
backgroundColor = .clear
|
||||||
|
|
||||||
|
addSubview(bgView)
|
||||||
|
bgView.addSubview(contentView)
|
||||||
|
contentView.addSubview(titleLabel)
|
||||||
|
contentView.addSubview(shareStack)
|
||||||
|
contentView.addSubview(closeBtn)
|
||||||
|
|
||||||
|
bgView.layoutChain.edges()
|
||||||
|
contentView.layoutChain
|
||||||
|
.edges(excludingEdge: .top)
|
||||||
|
.height(contentHeight)
|
||||||
|
|
||||||
|
titleLabel.layoutChain
|
||||||
|
.top(20)
|
||||||
|
.centerX()
|
||||||
|
|
||||||
|
closeBtn.layoutChain
|
||||||
|
.centerY(titleLabel)
|
||||||
|
.right(20)
|
||||||
|
.width(20)
|
||||||
|
.height(20)
|
||||||
|
|
||||||
|
shareStack.layoutChain
|
||||||
|
.topToBottomOfView(titleLabel, offset: 30)
|
||||||
|
.centerX()
|
||||||
|
|
||||||
|
let tap = UITapGestureRecognizer(target: self, action: #selector(handleBgTap))
|
||||||
|
bgView.addGestureRecognizer(tap)
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
fatalError("init(coder:) has not been implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Lazy Views
|
||||||
|
|
||||||
|
private lazy var bgView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .black.withAlphaComponent(0.5)
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var contentView: UIView = {
|
||||||
|
let view = UIView()
|
||||||
|
view.backgroundColor = .white
|
||||||
|
view.layer.cornerRadius = 26
|
||||||
|
view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
||||||
|
view.clipsToBounds = true
|
||||||
|
return view
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var titleLabel: UILabel = {
|
||||||
|
let label = UILabel()
|
||||||
|
label.text = "分享"
|
||||||
|
label.font = .systemFont(ofSize: 16, weight: .medium)
|
||||||
|
label.textColor = UIColor(hexStr: "#333333")
|
||||||
|
return label
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var shareStack: UIStackView = {
|
||||||
|
let stack = UIStackView(arrangedSubviews: [
|
||||||
|
makeShareItem(icon: "Share/friend", title: "微信", action: #selector(handleWeChatTap)),
|
||||||
|
makeShareItem(icon: "Share/moments", title: "朋友圈", action: #selector(handleMomentsTap)),
|
||||||
|
makeShareItem(icon: "Share/url", title: "链接", action: #selector(handleLinkTap))
|
||||||
|
])
|
||||||
|
stack.axis = .horizontal
|
||||||
|
stack.spacing = 50
|
||||||
|
stack.alignment = .center
|
||||||
|
return stack
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var closeBtn: UIButton = {
|
||||||
|
let btn = UIButton(type: .custom)
|
||||||
|
btn.setImage(UIImage(named: "Group/close"), for: .normal)
|
||||||
|
btn.addTarget(self, action: #selector(handleBgTap), for: .touchUpInside)
|
||||||
|
btn.extendEdgeInsets = UIEdgeInsets(top: 15, left: 20, bottom: 20, right: 20)
|
||||||
|
return btn
|
||||||
|
}()
|
||||||
|
|
||||||
|
private func makeShareItem(icon: String, title: String, action: Selector) -> UIView {
|
||||||
|
let container = UIView()
|
||||||
|
|
||||||
|
let imgView = UIImageView(image: UIImage(named: icon))
|
||||||
|
imgView.contentMode = .scaleAspectFit
|
||||||
|
container.addSubview(imgView)
|
||||||
|
imgView.layoutChain
|
||||||
|
.top(0)
|
||||||
|
.centerX()
|
||||||
|
.width(50)
|
||||||
|
.height(50)
|
||||||
|
|
||||||
|
let label = UILabel()
|
||||||
|
label.text = title
|
||||||
|
label.font = .systemFont(ofSize: 12)
|
||||||
|
label.textColor = UIColor(hexStr: "#666666")
|
||||||
|
label.textAlignment = .center
|
||||||
|
container.addSubview(label)
|
||||||
|
label.layoutChain
|
||||||
|
.topToBottomOfView(imgView, offset: 8)
|
||||||
|
.centerX()
|
||||||
|
.bottom(0)
|
||||||
|
|
||||||
|
container.layoutChain.width(60).height(78)
|
||||||
|
|
||||||
|
let btn = UIButton(type: .custom)
|
||||||
|
container.addSubview(btn)
|
||||||
|
btn.layoutChain.edges()
|
||||||
|
btn.addTarget(self, action: action, for: .touchUpInside)
|
||||||
|
|
||||||
|
return container
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -18,7 +18,7 @@ class VipRechargeVC: BaseViewController {
|
||||||
rootView = VipRechargeView(frame: UIScreen.main.bounds)
|
rootView = VipRechargeView(frame: UIScreen.main.bounds)
|
||||||
view = rootView
|
view = rootView
|
||||||
}
|
}
|
||||||
|
|
||||||
private var viewModel = VipRechargeVM()
|
private var viewModel = VipRechargeVM()
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
|
|
@ -33,19 +33,19 @@ class VipRechargeVC: BaseViewController {
|
||||||
viewModel.output.sectionedItems
|
viewModel.output.sectionedItems
|
||||||
.bind(to: rootView.expenseCollectionView.rx.items(dataSource: dataSource))
|
.bind(to: rootView.expenseCollectionView.rx.items(dataSource: dataSource))
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
|
|
||||||
viewModel.output.vipRightItems
|
viewModel.output.vipRightItems
|
||||||
.bind(to: rootView.vipRightsCollectionView.rx.items(dataSource: vipRightsDataSource))
|
.bind(to: rootView.vipRightsCollectionView.rx.items(dataSource: vipRightsDataSource))
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
|
|
||||||
viewModel.createCount.asObservable()
|
viewModel.createCount.asObservable()
|
||||||
.bind(to: rootView.createCountLab.rx.text)
|
.bind(to: rootView.createCountLab.rx.text)
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
|
|
||||||
viewModel.groupCount.asObservable()
|
viewModel.groupCount.asObservable()
|
||||||
.bind(to: rootView.groupCountLab.rx.text)
|
.bind(to: rootView.groupCountLab.rx.text)
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
|
|
||||||
viewModel.joinCount.asObservable()
|
viewModel.joinCount.asObservable()
|
||||||
.bind(to: rootView.joinCountLab.rx.text)
|
.bind(to: rootView.joinCountLab.rx.text)
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
|
|
@ -55,7 +55,7 @@ class VipRechargeVC: BaseViewController {
|
||||||
rootView.payBtnView.rx.tapGesture.subscribe(onNext: { _ in
|
rootView.payBtnView.rx.tapGesture.subscribe(onNext: { _ in
|
||||||
self.requestOrderPayParams()
|
self.requestOrderPayParams()
|
||||||
}).disposed(by: disposeBag)
|
}).disposed(by: disposeBag)
|
||||||
|
|
||||||
Observable.zip(
|
Observable.zip(
|
||||||
rootView.expenseCollectionView.rx.itemSelected,
|
rootView.expenseCollectionView.rx.itemSelected,
|
||||||
rootView.expenseCollectionView.rx.modelSelected(VipExpenseModel.self)
|
rootView.expenseCollectionView.rx.modelSelected(VipExpenseModel.self)
|
||||||
|
|
@ -67,7 +67,7 @@ class VipRechargeVC: BaseViewController {
|
||||||
})
|
})
|
||||||
.disposed(by: disposeBag)
|
.disposed(by: disposeBag)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - dataSource
|
// MARK: - dataSource
|
||||||
private lazy var dataSource: RxCollectionViewSectionedReloadDataSource<ExpenseListSectionModel> = {
|
private lazy var dataSource: RxCollectionViewSectionedReloadDataSource<ExpenseListSectionModel> = {
|
||||||
RxCollectionViewSectionedReloadDataSource<ExpenseListSectionModel> { datasource, collectionView, indexPath, model in
|
RxCollectionViewSectionedReloadDataSource<ExpenseListSectionModel> { datasource, collectionView, indexPath, model in
|
||||||
|
|
@ -76,7 +76,7 @@ class VipRechargeVC: BaseViewController {
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
private lazy var vipRightsDataSource: RxCollectionViewSectionedReloadDataSource<VipRightsListSectionModel> = {
|
private lazy var vipRightsDataSource: RxCollectionViewSectionedReloadDataSource<VipRightsListSectionModel> = {
|
||||||
RxCollectionViewSectionedReloadDataSource<VipRightsListSectionModel> { datasource, collectionView, indexPath, model in
|
RxCollectionViewSectionedReloadDataSource<VipRightsListSectionModel> { datasource, collectionView, indexPath, model in
|
||||||
let cell: VipRightsCell = collectionView.dequeueReusableCell(for: indexPath)
|
let cell: VipRightsCell = collectionView.dequeueReusableCell(for: indexPath)
|
||||||
|
|
@ -96,19 +96,45 @@ class VipRechargeVC: BaseViewController {
|
||||||
self.rootView.discountLab.text = self.viewModel.discountPriceString
|
self.rootView.discountLab.text = self.viewModel.discountPriceString
|
||||||
}).disposed(by: disposeBag)
|
}).disposed(by: disposeBag)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - API支付参数
|
// MARK: - API支付参数
|
||||||
private func requestOrderPayParams() {
|
private func requestOrderPayParams() {
|
||||||
DLToast.showLoading()
|
|
||||||
let types = viewModel.payType.components(separatedBy: ",").map { $0.trimmingCharacters(in: .whitespaces) }
|
let types = viewModel.payType.components(separatedBy: ",").map { $0.trimmingCharacters(in: .whitespaces) }
|
||||||
|
let payType = types[rootView.selectedPayTypeTag]
|
||||||
|
|
||||||
|
if payType == "apple" {
|
||||||
|
IAPManager.shared.purchase(goodsId: viewModel.goodsId) { [weak self] success, msg in
|
||||||
|
guard let self = self else { return }
|
||||||
|
if success {
|
||||||
|
self.showPayResultPop(showCloseBtn: false,
|
||||||
|
status: true,
|
||||||
|
title: "支付成功",
|
||||||
|
message: "恭喜您!成功开通\(self.viewModel.goodsName)",
|
||||||
|
confirmText: "确定", confirmBlock: {
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
|
}, cancelBlock: { })
|
||||||
|
} else {
|
||||||
|
self.showPayResultPop(status: false,
|
||||||
|
title: "支付失败",
|
||||||
|
message: msg ?? "很抱歉,请您重新支付!",
|
||||||
|
confirmText: "重新支付", confirmBlock: { },
|
||||||
|
cancelText: "取消", cancelBlock: {
|
||||||
|
AppRouter.shared.popOrDismiss()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
DLToast.showLoading()
|
||||||
OrderService.orderPayParams(goodsId: viewModel.goodsId,
|
OrderService.orderPayParams(goodsId: viewModel.goodsId,
|
||||||
payType: types[rootView.selectedPayTypeTag]).subscribe(onNext: { response in
|
payType: types[rootView.selectedPayTypeTag]).subscribe(onNext: { response in
|
||||||
guard let data = response.data else { return }
|
guard let data = response.data else { return }
|
||||||
|
|
||||||
let payType = types[self.rootView.selectedPayTypeTag]
|
let payType = types[self.rootView.selectedPayTypeTag]
|
||||||
if payType == "weixin" { // 微信
|
if payType == "weixin" { // 微信
|
||||||
// WXApi.registerApp(model.appId, universalLink: AppSettings.kAppsUniversalLink)
|
// WXApi.registerApp(model.appId, universalLink: AppSettings.kAppsUniversalLink)
|
||||||
//
|
//
|
||||||
// let request: PayReq = PayReq()
|
// let request: PayReq = PayReq()
|
||||||
// request.partnerId = model.partnerId
|
// request.partnerId = model.partnerId
|
||||||
// request.prepayId = model.prepayId
|
// request.prepayId = model.prepayId
|
||||||
|
|
|
||||||
|
|
@ -10,23 +10,23 @@ import RxSwift
|
||||||
import RxCocoa
|
import RxCocoa
|
||||||
|
|
||||||
class VipRechargeView: UIView {
|
class VipRechargeView: UIView {
|
||||||
|
|
||||||
var disposeBag = DisposeBag()
|
var disposeBag = DisposeBag()
|
||||||
|
|
||||||
private func setupRx() {
|
private func setupRx() {
|
||||||
backBtn.rx.tap.subscribe(onNext: { _ in
|
backBtn.rx.tap.subscribe(onNext: { _ in
|
||||||
VipWaivePopView.show()
|
VipWaivePopView.show()
|
||||||
}).disposed(by: disposeBag)
|
}).disposed(by: disposeBag)
|
||||||
|
|
||||||
agreementLab.rx.tapGesture.subscribe { _ in
|
agreementLab.rx.tapGesture.subscribe { _ in
|
||||||
AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.userAgreementUrl])
|
AppRouter.push(Route.web, userInfo: ["url": URLManager.shared.userAgreementUrl])
|
||||||
}.disposed(by: disposeBag)
|
}.disposed(by: disposeBag)
|
||||||
|
|
||||||
vipRightsDetailView.rx.tapGesture.subscribe { _ in
|
vipRightsDetailView.rx.tapGesture.subscribe { _ in
|
||||||
AppRouter.push(Route.vipRights)
|
AppRouter.push(Route.vipRights)
|
||||||
}.disposed(by: disposeBag)
|
}.disposed(by: disposeBag)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func setupUI() {
|
private func setupUI() {
|
||||||
addSubview(scrollView)
|
addSubview(scrollView)
|
||||||
scrollView.addSubview(scrollContentView)
|
scrollView.addSubview(scrollContentView)
|
||||||
|
|
@ -37,119 +37,119 @@ class VipRechargeView: UIView {
|
||||||
scrollContentView.addSubview(vipRightsView)
|
scrollContentView.addSubview(vipRightsView)
|
||||||
scrollContentView.addSubview(agreementLab)
|
scrollContentView.addSubview(agreementLab)
|
||||||
scrollContentView.addSubview(tipsLab)
|
scrollContentView.addSubview(tipsLab)
|
||||||
|
|
||||||
vipRightsView.addSubview(vipRightsTitleView)
|
vipRightsView.addSubview(vipRightsTitleView)
|
||||||
vipRightsView.addSubview(groupCountView)
|
vipRightsView.addSubview(groupCountView)
|
||||||
vipRightsView.addSubview(vipRightsCollectionView)
|
vipRightsView.addSubview(vipRightsCollectionView)
|
||||||
|
|
||||||
addSubview(bottomView)
|
addSubview(bottomView)
|
||||||
bottomView.addSubview(payTypeStackView)
|
bottomView.addSubview(payTypeStackView)
|
||||||
bottomView.addSubview(payBtnView)
|
bottomView.addSubview(payBtnView)
|
||||||
bottomView.addSubview(payPriceView)
|
bottomView.addSubview(payPriceView)
|
||||||
|
|
||||||
addSubview(navBarView)
|
addSubview(navBarView)
|
||||||
navBarView.addSubview(navTitleLabel)
|
navBarView.addSubview(navTitleLabel)
|
||||||
addSubview(backBtn)
|
addSubview(backBtn)
|
||||||
|
|
||||||
navBarView.layoutChain
|
navBarView.layoutChain
|
||||||
.edges(excludingEdge: .bottom)
|
.edges(excludingEdge: .bottom)
|
||||||
.height(kNaviHeight)
|
.height(kNaviHeight)
|
||||||
|
|
||||||
navTitleLabel.layoutChain
|
navTitleLabel.layoutChain
|
||||||
.top(kStatusBarHeight + 12)
|
.top(kStatusBarHeight + 12)
|
||||||
.centerY(backBtn)
|
.centerY(backBtn)
|
||||||
.centerX()
|
.centerX()
|
||||||
|
|
||||||
backBtn.layoutChain
|
backBtn.layoutChain
|
||||||
.top(kStatusBarHeight + 12)
|
.top(kStatusBarHeight + 12)
|
||||||
.left(15)
|
.left(15)
|
||||||
.width(24)
|
.width(24)
|
||||||
.height(24)
|
.height(24)
|
||||||
|
|
||||||
bottomView.layoutChain
|
bottomView.layoutChain
|
||||||
.edgesHorzontal()
|
.edgesHorzontal()
|
||||||
.heightToWidth(144/375)
|
.heightToWidth(144/375)
|
||||||
.bottom()
|
.bottom()
|
||||||
|
|
||||||
payBtnView.layoutChain
|
payBtnView.layoutChain
|
||||||
.edgesHorzontal(16)
|
.edgesHorzontal(16)
|
||||||
.heightToWidth(50/343)
|
.heightToWidth(50/343)
|
||||||
.centerY()
|
.centerY()
|
||||||
|
|
||||||
payTypeStackView.layoutChain
|
payTypeStackView.layoutChain
|
||||||
.top(13)
|
.top(13)
|
||||||
.edgesHorzontal(16)
|
.edgesHorzontal(16)
|
||||||
.bottomToTopOfView(payBtnView)
|
.bottomToTopOfView(payBtnView)
|
||||||
|
|
||||||
payPriceView.layoutChain
|
payPriceView.layoutChain
|
||||||
.left(32)
|
.left(32)
|
||||||
.centerY(payBtnView, offset: -7)
|
.centerY(payBtnView, offset: -7)
|
||||||
.height(30)
|
.height(30)
|
||||||
|
|
||||||
scrollView.layoutChain
|
scrollView.layoutChain
|
||||||
.edges(excludingEdge: .bottom)
|
.edges(excludingEdge: .bottom)
|
||||||
.bottomToTopOfView(bottomView)
|
.bottomToTopOfView(bottomView)
|
||||||
|
|
||||||
scrollContentView.layoutChain
|
scrollContentView.layoutChain
|
||||||
.edges()
|
.edges()
|
||||||
.widthToView(scrollView)
|
.widthToView(scrollView)
|
||||||
|
|
||||||
headerBgImgView.layoutChain
|
headerBgImgView.layoutChain
|
||||||
.edges(excludingEdge: .bottom)
|
.edges(excludingEdge: .bottom)
|
||||||
.heightToWidth(267/375)
|
.heightToWidth(267/375)
|
||||||
|
|
||||||
vipRightsDetailView.layoutChain
|
vipRightsDetailView.layoutChain
|
||||||
.top(36)
|
.top(36)
|
||||||
.right()
|
.right()
|
||||||
.height(24)
|
.height(24)
|
||||||
|
|
||||||
cornerView.layoutChain
|
cornerView.layoutChain
|
||||||
.topToBottomOfView(headerBgImgView, offset: -20)
|
.topToBottomOfView(headerBgImgView, offset: -20)
|
||||||
.edges(excludingEdge: .top)
|
.edges(excludingEdge: .top)
|
||||||
|
|
||||||
let expenseCollectionViewHeight = (kScreenWidth - 32 - 32) / 3 * (144/110) + 10
|
let expenseCollectionViewHeight = (kScreenWidth - 32 - 32) / 3 * (144/110) + 10
|
||||||
expenseCollectionView.layoutChain
|
expenseCollectionView.layoutChain
|
||||||
.topToView(cornerView, offset: -43)
|
.topToView(cornerView, offset: -43)
|
||||||
.edgesHorzontal()
|
.edgesHorzontal()
|
||||||
.height(expenseCollectionViewHeight * 1.1)
|
.height(expenseCollectionViewHeight * 1.1)
|
||||||
|
|
||||||
vipRightsView.layoutChain
|
vipRightsView.layoutChain
|
||||||
.topToBottomOfView(expenseCollectionView, offset: 18)
|
.topToBottomOfView(expenseCollectionView, offset: 18)
|
||||||
.edgesHorzontal(16)
|
.edgesHorzontal(16)
|
||||||
|
|
||||||
vipRightsTitleView.layoutChain
|
vipRightsTitleView.layoutChain
|
||||||
.top(14)
|
.top(14)
|
||||||
.centerX()
|
.centerX()
|
||||||
|
|
||||||
groupCountView.layoutChain
|
groupCountView.layoutChain
|
||||||
.topToBottomOfView(vipRightsTitleView, offset: 9)
|
.topToBottomOfView(vipRightsTitleView, offset: 9)
|
||||||
.edgesHorzontal()
|
.edgesHorzontal()
|
||||||
|
|
||||||
vipRightsCollectionView.layoutChain
|
vipRightsCollectionView.layoutChain
|
||||||
.topToBottomOfView(groupCountView, offset: 14)
|
.topToBottomOfView(groupCountView, offset: 14)
|
||||||
.edgesHorzontal()
|
.edgesHorzontal()
|
||||||
.bottom(14)
|
.bottom(14)
|
||||||
.height(150)
|
.height(150)
|
||||||
|
|
||||||
agreementLab.layoutChain
|
agreementLab.layoutChain
|
||||||
.topToBottomOfView(vipRightsView, offset: 6)
|
.topToBottomOfView(vipRightsView, offset: 6)
|
||||||
.leftToView(vipRightsView)
|
.leftToView(vipRightsView)
|
||||||
.rightToView(vipRightsView)
|
.rightToView(vipRightsView)
|
||||||
|
|
||||||
tipsLab.layoutChain
|
tipsLab.layoutChain
|
||||||
.topToBottomOfView(agreementLab, offset: 4)
|
.topToBottomOfView(agreementLab, offset: 4)
|
||||||
.leftToView(vipRightsView)
|
.leftToView(vipRightsView)
|
||||||
.rightToView(vipRightsView)
|
.rightToView(vipRightsView)
|
||||||
.bottom(10)
|
.bottom(10)
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy var navBarView: UIView = {
|
lazy var navBarView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .white
|
view.backgroundColor = .white
|
||||||
view.alpha = 0
|
view.alpha = 0
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var navTitleLabel: UILabel = {
|
lazy var navTitleLabel: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.text = "升级会员"
|
label.text = "升级会员"
|
||||||
|
|
@ -158,14 +158,14 @@ class VipRechargeView: UIView {
|
||||||
label.textAlignment = .center
|
label.textAlignment = .center
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var backBtn: UIButton = {
|
lazy var backBtn: UIButton = {
|
||||||
let btn = UIButton(type: .custom)
|
let btn = UIButton(type: .custom)
|
||||||
btn.setImage(UIImage(named: "Common/back"), for: .normal)
|
btn.setImage(UIImage(named: "Common/back"), for: .normal)
|
||||||
btn.extendEdgeInsets = UIEdgeInsets(top: 54, left: 15, bottom: 15, right: 100)
|
btn.extendEdgeInsets = UIEdgeInsets(top: 54, left: 15, bottom: 15, right: 100)
|
||||||
return btn
|
return btn
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var scrollView: UIScrollView = {
|
lazy var scrollView: UIScrollView = {
|
||||||
let view = UIScrollView()
|
let view = UIScrollView()
|
||||||
view.backgroundColor = UIColor(hexStr: "#F5FBFB")
|
view.backgroundColor = UIColor(hexStr: "#F5FBFB")
|
||||||
|
|
@ -175,43 +175,43 @@ class VipRechargeView: UIView {
|
||||||
view.contentInsetAdjustmentBehavior = .never
|
view.contentInsetAdjustmentBehavior = .never
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var scrollContentView: UIView = {
|
lazy var scrollContentView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .clear
|
view.backgroundColor = .clear
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var headerBgImgView: UIImageView = {
|
lazy var headerBgImgView: UIImageView = {
|
||||||
let view = UIImageView()
|
let view = UIImageView()
|
||||||
view.image = UIImage(named: "VipRecharge/header_bg")
|
view.image = UIImage(named: "VipRecharge/header_bg")
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var vipRightsDetailView: UIView = {
|
lazy var vipRightsDetailView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = UIColor(hexStr: "#FFFFFF", alpha: 0.7)
|
view.backgroundColor = UIColor(hexStr: "#FFFFFF", alpha: 0.7)
|
||||||
|
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.text = "权益对比"
|
label.text = "权益对比"
|
||||||
label.font = .systemFont(ofSize: 11, weight: .bold)
|
label.font = .systemFont(ofSize: 11, weight: .bold)
|
||||||
label.textColor = UIColor(hexStr: "#224E92")
|
label.textColor = UIColor(hexStr: "#224E92")
|
||||||
|
|
||||||
view.addSubview(label)
|
view.addSubview(label)
|
||||||
label.layoutChain
|
label.layoutChain
|
||||||
.edgesVertical(4)
|
.edgesVertical(4)
|
||||||
.edgesHorzontal(8)
|
.edgesHorzontal(8)
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var cornerView: UIView = {
|
lazy var cornerView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = UIColor(hexStr: "#F5FBFB")
|
view.backgroundColor = UIColor(hexStr: "#F5FBFB")
|
||||||
view.clipsToBounds = false
|
view.clipsToBounds = false
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 资费
|
/// 资费
|
||||||
lazy var expenseCollectionView: UICollectionView = {
|
lazy var expenseCollectionView: UICollectionView = {
|
||||||
let layout = UICollectionViewFlowLayout()
|
let layout = UICollectionViewFlowLayout()
|
||||||
|
|
@ -222,14 +222,14 @@ class VipRechargeView: UIView {
|
||||||
layout.sectionInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
|
layout.sectionInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
|
||||||
layout.minimumLineSpacing = spacing
|
layout.minimumLineSpacing = spacing
|
||||||
layout.scrollDirection = .horizontal
|
layout.scrollDirection = .horizontal
|
||||||
|
|
||||||
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
||||||
cv.backgroundColor = .clear
|
cv.backgroundColor = .clear
|
||||||
cv.showsHorizontalScrollIndicator = false
|
cv.showsHorizontalScrollIndicator = false
|
||||||
cv.register(ExpenseCell.self)
|
cv.register(ExpenseCell.self)
|
||||||
return cv
|
return cv
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 会员权益
|
/// 会员权益
|
||||||
lazy var vipRightsView: UIView = {
|
lazy var vipRightsView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
|
|
@ -237,11 +237,11 @@ class VipRechargeView: UIView {
|
||||||
view.cornerRadius = 10
|
view.cornerRadius = 10
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var vipRightsTitleView: UIView = {
|
lazy var vipRightsTitleView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .clear
|
view.backgroundColor = .clear
|
||||||
|
|
||||||
let titleLab = UILabel()
|
let titleLab = UILabel()
|
||||||
titleLab.text = "会员权益"
|
titleLab.text = "会员权益"
|
||||||
titleLab.font = .systemFont(ofSize: 14, weight: .bold)
|
titleLab.font = .systemFont(ofSize: 14, weight: .bold)
|
||||||
|
|
@ -251,7 +251,7 @@ class VipRechargeView: UIView {
|
||||||
titleLab.layoutChain
|
titleLab.layoutChain
|
||||||
.edgesVertical()
|
.edgesVertical()
|
||||||
.centerX()
|
.centerX()
|
||||||
|
|
||||||
let leftLine1 = UIView()
|
let leftLine1 = UIView()
|
||||||
leftLine1.backgroundColor = UIColor(hexStr: "#B7F34E")
|
leftLine1.backgroundColor = UIColor(hexStr: "#B7F34E")
|
||||||
leftLine1.cornerRadius = 1
|
leftLine1.cornerRadius = 1
|
||||||
|
|
@ -261,7 +261,7 @@ class VipRechargeView: UIView {
|
||||||
.width(2)
|
.width(2)
|
||||||
.height(10)
|
.height(10)
|
||||||
.centerY()
|
.centerY()
|
||||||
|
|
||||||
let leftLine2 = UIView()
|
let leftLine2 = UIView()
|
||||||
leftLine2.backgroundColor = UIColor(hexStr: "#B7F34E")
|
leftLine2.backgroundColor = UIColor(hexStr: "#B7F34E")
|
||||||
leftLine2.cornerRadius = 1
|
leftLine2.cornerRadius = 1
|
||||||
|
|
@ -271,7 +271,7 @@ class VipRechargeView: UIView {
|
||||||
.width(2)
|
.width(2)
|
||||||
.edgesVertical()
|
.edgesVertical()
|
||||||
.rightToLeftOfView(titleLab, offset: -10)
|
.rightToLeftOfView(titleLab, offset: -10)
|
||||||
|
|
||||||
let leftLine3 = UIView()
|
let leftLine3 = UIView()
|
||||||
leftLine3.backgroundColor = UIColor(hexStr: "#B7F34E")
|
leftLine3.backgroundColor = UIColor(hexStr: "#B7F34E")
|
||||||
leftLine3.cornerRadius = 1
|
leftLine3.cornerRadius = 1
|
||||||
|
|
@ -280,7 +280,7 @@ class VipRechargeView: UIView {
|
||||||
.leftToRightOfView(titleLab, offset: 10)
|
.leftToRightOfView(titleLab, offset: 10)
|
||||||
.width(2)
|
.width(2)
|
||||||
.edgesVertical()
|
.edgesVertical()
|
||||||
|
|
||||||
let leftLine4 = UIView()
|
let leftLine4 = UIView()
|
||||||
leftLine4.backgroundColor = UIColor(hexStr: "#B7F34E")
|
leftLine4.backgroundColor = UIColor(hexStr: "#B7F34E")
|
||||||
leftLine4.cornerRadius = 1
|
leftLine4.cornerRadius = 1
|
||||||
|
|
@ -290,195 +290,195 @@ class VipRechargeView: UIView {
|
||||||
.width(2)
|
.width(2)
|
||||||
.height(10)
|
.height(10)
|
||||||
.centerY()
|
.centerY()
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var groupCountView: UIView = {
|
lazy var groupCountView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .clear
|
view.backgroundColor = .clear
|
||||||
|
|
||||||
// 创建圈子
|
// 创建圈子
|
||||||
let createCountView = UIView()
|
let createCountView = UIView()
|
||||||
createCountView.backgroundColor = .clear
|
createCountView.backgroundColor = .clear
|
||||||
|
|
||||||
let createIcon = UIImageView(image: UIImage(named: "VipRecharge/create_count"))
|
let createIcon = UIImageView(image: UIImage(named: "VipRecharge/create_count"))
|
||||||
|
|
||||||
let createBgImg = UIImageView(image: UIImage(named: "VipRecharge/count_bg"))
|
let createBgImg = UIImageView(image: UIImage(named: "VipRecharge/count_bg"))
|
||||||
|
|
||||||
let createUnitLab = UILabel()
|
let createUnitLab = UILabel()
|
||||||
createUnitLab.text = "个"
|
createUnitLab.text = "个"
|
||||||
createUnitLab.font = .systemFont(ofSize: 10, weight: .medium)
|
createUnitLab.font = .systemFont(ofSize: 10, weight: .medium)
|
||||||
createUnitLab.textColor = UIColor(hexStr: "#1A1A1A")
|
createUnitLab.textColor = UIColor(hexStr: "#1A1A1A")
|
||||||
|
|
||||||
let createTitleLab = UILabel()
|
let createTitleLab = UILabel()
|
||||||
createTitleLab.text = "创建圈子"
|
createTitleLab.text = "创建圈子"
|
||||||
createTitleLab.font = .systemFont(ofSize: 12, weight: .medium)
|
createTitleLab.font = .systemFont(ofSize: 12, weight: .medium)
|
||||||
createTitleLab.textColor = UIColor(hexStr: "#1A1A1A")
|
createTitleLab.textColor = UIColor(hexStr: "#1A1A1A")
|
||||||
|
|
||||||
createCountView.addSubview(createIcon)
|
createCountView.addSubview(createIcon)
|
||||||
createCountView.addSubview(createBgImg)
|
createCountView.addSubview(createBgImg)
|
||||||
createCountView.addSubview(createUnitLab)
|
createCountView.addSubview(createUnitLab)
|
||||||
createCountView.addSubview(createTitleLab)
|
createCountView.addSubview(createTitleLab)
|
||||||
createCountView.addSubview(createCountLab)
|
createCountView.addSubview(createCountLab)
|
||||||
|
|
||||||
createIcon.layoutChain
|
createIcon.layoutChain
|
||||||
.top()
|
.top()
|
||||||
.centerX()
|
.centerX()
|
||||||
.width(34).height(34)
|
.width(34).height(34)
|
||||||
|
|
||||||
createBgImg.layoutChain
|
createBgImg.layoutChain
|
||||||
.top(8)
|
.top(8)
|
||||||
.edges(excludingEdge: .top)
|
.edges(excludingEdge: .top)
|
||||||
|
|
||||||
createCountLab.layoutChain
|
createCountLab.layoutChain
|
||||||
.topToBottomOfView(createIcon, offset: 2)
|
.topToBottomOfView(createIcon, offset: 2)
|
||||||
.centerX()
|
.centerX()
|
||||||
|
|
||||||
createUnitLab.layoutChain
|
createUnitLab.layoutChain
|
||||||
.leftToRightOfView(createCountLab)
|
.leftToRightOfView(createCountLab)
|
||||||
.bottomToView(createCountLab, offset: 0)
|
.bottomToView(createCountLab, offset: 0)
|
||||||
|
|
||||||
createTitleLab.layoutChain
|
createTitleLab.layoutChain
|
||||||
.centerX()
|
.centerX()
|
||||||
.bottom(4)
|
.bottom(4)
|
||||||
|
|
||||||
// 分隔线
|
// 分隔线
|
||||||
let separator1 = UIImageView(image: UIImage(named: "VipRecharge/separator"))
|
let separator1 = UIImageView(image: UIImage(named: "VipRecharge/separator"))
|
||||||
|
|
||||||
// 圈子人数
|
// 圈子人数
|
||||||
let groupCountView = UIView()
|
let groupCountView = UIView()
|
||||||
groupCountView.backgroundColor = .clear
|
groupCountView.backgroundColor = .clear
|
||||||
|
|
||||||
let groupCountIcon = UIImageView(image: UIImage(named: "VipRecharge/member_count"))
|
let groupCountIcon = UIImageView(image: UIImage(named: "VipRecharge/member_count"))
|
||||||
|
|
||||||
let groupCountBgImg = UIImageView(image: UIImage(named: "VipRecharge/count_bg"))
|
let groupCountBgImg = UIImageView(image: UIImage(named: "VipRecharge/count_bg"))
|
||||||
|
|
||||||
let groupCountUnitLab = UILabel()
|
let groupCountUnitLab = UILabel()
|
||||||
groupCountUnitLab.text = "个"
|
groupCountUnitLab.text = "个"
|
||||||
groupCountUnitLab.font = .systemFont(ofSize: 10, weight: .medium)
|
groupCountUnitLab.font = .systemFont(ofSize: 10, weight: .medium)
|
||||||
groupCountUnitLab.textColor = UIColor(hexStr: "#1A1A1A")
|
groupCountUnitLab.textColor = UIColor(hexStr: "#1A1A1A")
|
||||||
|
|
||||||
let groupCountTitleLab = UILabel()
|
let groupCountTitleLab = UILabel()
|
||||||
groupCountTitleLab.text = "圈子人数"
|
groupCountTitleLab.text = "圈子人数"
|
||||||
groupCountTitleLab.font = .systemFont(ofSize: 12, weight: .medium)
|
groupCountTitleLab.font = .systemFont(ofSize: 12, weight: .medium)
|
||||||
groupCountTitleLab.textColor = UIColor(hexStr: "#1A1A1A")
|
groupCountTitleLab.textColor = UIColor(hexStr: "#1A1A1A")
|
||||||
|
|
||||||
groupCountView.addSubview(groupCountIcon)
|
groupCountView.addSubview(groupCountIcon)
|
||||||
groupCountView.addSubview(groupCountBgImg)
|
groupCountView.addSubview(groupCountBgImg)
|
||||||
groupCountView.addSubview(groupCountUnitLab)
|
groupCountView.addSubview(groupCountUnitLab)
|
||||||
groupCountView.addSubview(groupCountTitleLab)
|
groupCountView.addSubview(groupCountTitleLab)
|
||||||
groupCountView.addSubview(groupCountLab)
|
groupCountView.addSubview(groupCountLab)
|
||||||
|
|
||||||
groupCountIcon.layoutChain
|
groupCountIcon.layoutChain
|
||||||
.top()
|
.top()
|
||||||
.centerX()
|
.centerX()
|
||||||
.width(34).height(34)
|
.width(34).height(34)
|
||||||
|
|
||||||
groupCountBgImg.layoutChain
|
groupCountBgImg.layoutChain
|
||||||
.top(8)
|
.top(8)
|
||||||
.edges(excludingEdge: .top)
|
.edges(excludingEdge: .top)
|
||||||
|
|
||||||
groupCountLab.layoutChain
|
groupCountLab.layoutChain
|
||||||
.topToBottomOfView(groupCountIcon, offset: 2)
|
.topToBottomOfView(groupCountIcon, offset: 2)
|
||||||
.centerX()
|
.centerX()
|
||||||
|
|
||||||
groupCountUnitLab.layoutChain
|
groupCountUnitLab.layoutChain
|
||||||
.leftToRightOfView(groupCountLab)
|
.leftToRightOfView(groupCountLab)
|
||||||
.bottomToView(groupCountLab, offset: 0)
|
.bottomToView(groupCountLab, offset: 0)
|
||||||
|
|
||||||
groupCountTitleLab.layoutChain
|
groupCountTitleLab.layoutChain
|
||||||
.centerX()
|
.centerX()
|
||||||
.bottom(4)
|
.bottom(4)
|
||||||
|
|
||||||
// 分隔线
|
// 分隔线
|
||||||
let separator2 = UIImageView(image: UIImage(named: "VipRecharge/separator"))
|
let separator2 = UIImageView(image: UIImage(named: "VipRecharge/separator"))
|
||||||
|
|
||||||
// 加入圈子
|
// 加入圈子
|
||||||
let joinCountView = UIView()
|
let joinCountView = UIView()
|
||||||
joinCountView.backgroundColor = .clear
|
joinCountView.backgroundColor = .clear
|
||||||
|
|
||||||
let joinCountIcon = UIImageView(image: UIImage(named: "VipRecharge/join_count"))
|
let joinCountIcon = UIImageView(image: UIImage(named: "VipRecharge/join_count"))
|
||||||
|
|
||||||
let joinCountBgImg = UIImageView(image: UIImage(named: "VipRecharge/count_bg"))
|
let joinCountBgImg = UIImageView(image: UIImage(named: "VipRecharge/count_bg"))
|
||||||
|
|
||||||
let joinCountUnitLab = UILabel()
|
let joinCountUnitLab = UILabel()
|
||||||
joinCountUnitLab.text = "个"
|
joinCountUnitLab.text = "个"
|
||||||
joinCountUnitLab.font = .systemFont(ofSize: 10, weight: .medium)
|
joinCountUnitLab.font = .systemFont(ofSize: 10, weight: .medium)
|
||||||
joinCountUnitLab.textColor = UIColor(hexStr: "#1A1A1A")
|
joinCountUnitLab.textColor = UIColor(hexStr: "#1A1A1A")
|
||||||
|
|
||||||
let joinCountTitleLab = UILabel()
|
let joinCountTitleLab = UILabel()
|
||||||
joinCountTitleLab.text = "加入圈子"
|
joinCountTitleLab.text = "加入圈子"
|
||||||
joinCountTitleLab.font = .systemFont(ofSize: 12, weight: .medium)
|
joinCountTitleLab.font = .systemFont(ofSize: 12, weight: .medium)
|
||||||
joinCountTitleLab.textColor = UIColor(hexStr: "#1A1A1A")
|
joinCountTitleLab.textColor = UIColor(hexStr: "#1A1A1A")
|
||||||
|
|
||||||
joinCountView.addSubview(joinCountIcon)
|
joinCountView.addSubview(joinCountIcon)
|
||||||
joinCountView.addSubview(joinCountBgImg)
|
joinCountView.addSubview(joinCountBgImg)
|
||||||
joinCountView.addSubview(joinCountUnitLab)
|
joinCountView.addSubview(joinCountUnitLab)
|
||||||
joinCountView.addSubview(joinCountTitleLab)
|
joinCountView.addSubview(joinCountTitleLab)
|
||||||
joinCountView.addSubview(joinCountLab)
|
joinCountView.addSubview(joinCountLab)
|
||||||
|
|
||||||
joinCountIcon.layoutChain
|
joinCountIcon.layoutChain
|
||||||
.top()
|
.top()
|
||||||
.centerX()
|
.centerX()
|
||||||
.width(34).height(34)
|
.width(34).height(34)
|
||||||
|
|
||||||
joinCountBgImg.layoutChain
|
joinCountBgImg.layoutChain
|
||||||
.top(8)
|
.top(8)
|
||||||
.edges(excludingEdge: .top)
|
.edges(excludingEdge: .top)
|
||||||
|
|
||||||
joinCountLab.layoutChain
|
joinCountLab.layoutChain
|
||||||
.topToBottomOfView(joinCountIcon, offset: 2)
|
.topToBottomOfView(joinCountIcon, offset: 2)
|
||||||
.centerX()
|
.centerX()
|
||||||
|
|
||||||
joinCountUnitLab.layoutChain
|
joinCountUnitLab.layoutChain
|
||||||
.leftToRightOfView(joinCountLab)
|
.leftToRightOfView(joinCountLab)
|
||||||
.bottomToView(joinCountLab, offset: 0)
|
.bottomToView(joinCountLab, offset: 0)
|
||||||
|
|
||||||
joinCountTitleLab.layoutChain
|
joinCountTitleLab.layoutChain
|
||||||
.centerX()
|
.centerX()
|
||||||
.bottom(4)
|
.bottom(4)
|
||||||
|
|
||||||
view.addSubview(createCountView)
|
view.addSubview(createCountView)
|
||||||
view.addSubview(separator1)
|
view.addSubview(separator1)
|
||||||
view.addSubview(groupCountView)
|
view.addSubview(groupCountView)
|
||||||
view.addSubview(separator2)
|
view.addSubview(separator2)
|
||||||
view.addSubview(joinCountView)
|
view.addSubview(joinCountView)
|
||||||
|
|
||||||
groupCountView.layoutChain
|
groupCountView.layoutChain
|
||||||
.top()
|
.top()
|
||||||
.centerX()
|
.centerX()
|
||||||
.width(69)
|
.width(69)
|
||||||
.height(90)
|
.height(90)
|
||||||
.bottom()
|
.bottom()
|
||||||
|
|
||||||
separator1.layoutChain
|
separator1.layoutChain
|
||||||
.rightToLeftOfView(groupCountView, offset: -26)
|
.rightToLeftOfView(groupCountView, offset: -26)
|
||||||
.centerY()
|
.centerY()
|
||||||
.height(85)
|
.height(85)
|
||||||
.width(1)
|
.width(1)
|
||||||
|
|
||||||
createCountView.layoutChain
|
createCountView.layoutChain
|
||||||
.topToView(groupCountView)
|
.topToView(groupCountView)
|
||||||
.rightToLeftOfView(separator1, offset: -26)
|
.rightToLeftOfView(separator1, offset: -26)
|
||||||
.width(69)
|
.width(69)
|
||||||
.height(90)
|
.height(90)
|
||||||
|
|
||||||
separator2.layoutChain
|
separator2.layoutChain
|
||||||
.leftToRightOfView(groupCountView, offset: 26)
|
.leftToRightOfView(groupCountView, offset: 26)
|
||||||
.centerY()
|
.centerY()
|
||||||
.height(85)
|
.height(85)
|
||||||
.width(1)
|
.width(1)
|
||||||
|
|
||||||
joinCountView.layoutChain
|
joinCountView.layoutChain
|
||||||
.topToView(groupCountView)
|
.topToView(groupCountView)
|
||||||
.leftToRightOfView(separator2, offset: 26)
|
.leftToRightOfView(separator2, offset: 26)
|
||||||
.width(69)
|
.width(69)
|
||||||
.height(90)
|
.height(90)
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var createCountLab: UILabel = {
|
lazy var createCountLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.text = "0"
|
label.text = "0"
|
||||||
|
|
@ -486,7 +486,7 @@ class VipRechargeView: UIView {
|
||||||
label.textColor = UIColor(hexStr: "#FF4F44")
|
label.textColor = UIColor(hexStr: "#FF4F44")
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var groupCountLab: UILabel = {
|
lazy var groupCountLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.text = "0"
|
label.text = "0"
|
||||||
|
|
@ -494,7 +494,7 @@ class VipRechargeView: UIView {
|
||||||
label.textColor = UIColor(hexStr: "#FF4F44")
|
label.textColor = UIColor(hexStr: "#FF4F44")
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var joinCountLab: UILabel = {
|
lazy var joinCountLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.text = "0"
|
label.text = "0"
|
||||||
|
|
@ -502,7 +502,7 @@ class VipRechargeView: UIView {
|
||||||
label.textColor = UIColor(hexStr: "#FF4F44")
|
label.textColor = UIColor(hexStr: "#FF4F44")
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var vipRightsCollectionView: UICollectionView = {
|
lazy var vipRightsCollectionView: UICollectionView = {
|
||||||
let layout = UICollectionViewFlowLayout()
|
let layout = UICollectionViewFlowLayout()
|
||||||
let spacing: CGFloat = 35
|
let spacing: CGFloat = 35
|
||||||
|
|
@ -513,20 +513,20 @@ class VipRechargeView: UIView {
|
||||||
layout.minimumLineSpacing = 20
|
layout.minimumLineSpacing = 20
|
||||||
layout.minimumInteritemSpacing = spacing
|
layout.minimumInteritemSpacing = spacing
|
||||||
layout.scrollDirection = .vertical
|
layout.scrollDirection = .vertical
|
||||||
|
|
||||||
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
||||||
cv.backgroundColor = .clear
|
cv.backgroundColor = .clear
|
||||||
cv.showsHorizontalScrollIndicator = false
|
cv.showsHorizontalScrollIndicator = false
|
||||||
cv.register(VipRightsCell.self)
|
cv.register(VipRightsCell.self)
|
||||||
return cv
|
return cv
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var agreementLab: UILabel = {
|
lazy var agreementLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .systemFont(ofSize: 10, weight: .medium)
|
label.font = .systemFont(ofSize: 10, weight: .medium)
|
||||||
label.textColor = UIColor(hexStr: "#767676")
|
label.textColor = UIColor(hexStr: "#767676")
|
||||||
label.isUserInteractionEnabled = true
|
label.isUserInteractionEnabled = true
|
||||||
|
|
||||||
let text = "*开通前请阅读《会员服务协议》"
|
let text = "*开通前请阅读《会员服务协议》"
|
||||||
let attr = NSMutableAttributedString(string: text)
|
let attr = NSMutableAttributedString(string: text)
|
||||||
let range = (text as NSString).range(of: "《会员服务协议》")
|
let range = (text as NSString).range(of: "《会员服务协议》")
|
||||||
|
|
@ -534,7 +534,7 @@ class VipRechargeView: UIView {
|
||||||
label.attributedText = attr
|
label.attributedText = attr
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var tipsLab: UILabel = {
|
lazy var tipsLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.text = "*根据相关隐私保护的规定,本产品功能需双方下载并授权同意后再使用,请在自己的设备上使用,不得在未经过对方同意和授权的情况下使用,仅限家庭/亲人/朋友/情侣等熟人间使用。"
|
label.text = "*根据相关隐私保护的规定,本产品功能需双方下载并授权同意后再使用,请在自己的设备上使用,不得在未经过对方同意和授权的情况下使用,仅限家庭/亲人/朋友/情侣等熟人间使用。"
|
||||||
|
|
@ -543,7 +543,7 @@ class VipRechargeView: UIView {
|
||||||
label.numberOfLines = 0
|
label.numberOfLines = 0
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var payTypeStackView: UIStackView = {
|
lazy var payTypeStackView: UIStackView = {
|
||||||
let stack = UIStackView()
|
let stack = UIStackView()
|
||||||
stack.axis = .horizontal
|
stack.axis = .horizontal
|
||||||
|
|
@ -562,6 +562,7 @@ class VipRechargeView: UIView {
|
||||||
let payTypeMap: [(String, String)] = types.compactMap {
|
let payTypeMap: [(String, String)] = types.compactMap {
|
||||||
if $0 == "weixin" { return ("wechat", "微信支付") }
|
if $0 == "weixin" { return ("wechat", "微信支付") }
|
||||||
if $0 == "alipay" { return ("alipay", "支付宝支付") }
|
if $0 == "alipay" { return ("alipay", "支付宝支付") }
|
||||||
|
if $0 == "apple" { return ("apple", "苹果支付") }
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
guard !payTypeMap.isEmpty else { return }
|
guard !payTypeMap.isEmpty else { return }
|
||||||
|
|
@ -622,30 +623,30 @@ class VipRechargeView: UIView {
|
||||||
view.layer.shadowOpacity = 0.06
|
view.layer.shadowOpacity = 0.06
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var payBtnView: UIView = {
|
lazy var payBtnView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .clear
|
view.backgroundColor = .clear
|
||||||
|
|
||||||
let bgImg = UIImageView()
|
let bgImg = UIImageView()
|
||||||
bgImg.image = UIImage(named: "VipRecharge/pay_bg")
|
bgImg.image = UIImage(named: "VipRecharge/pay_bg")
|
||||||
view.addSubview(bgImg)
|
view.addSubview(bgImg)
|
||||||
bgImg.layoutChain.edges()
|
bgImg.layoutChain.edges()
|
||||||
|
|
||||||
let unlockLab = UILabel()
|
let unlockLab = UILabel()
|
||||||
unlockLab.text = "解锁会员"
|
unlockLab.text = "解锁会员"
|
||||||
unlockLab.font = .systemFont(ofSize: 16, weight: .heavy)
|
unlockLab.font = .systemFont(ofSize: 16, weight: .heavy)
|
||||||
unlockLab.textColor = .white
|
unlockLab.textColor = .white
|
||||||
view.addSubview(unlockLab)
|
view.addSubview(unlockLab)
|
||||||
unlockLab.layoutChain.right(21).centerY()
|
unlockLab.layoutChain.right(21).centerY()
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var payPriceView: UIView = {
|
lazy var payPriceView: UIView = {
|
||||||
let view = UIView()
|
let view = UIView()
|
||||||
view.backgroundColor = .clear
|
view.backgroundColor = .clear
|
||||||
|
|
||||||
let titleLab = UILabel()
|
let titleLab = UILabel()
|
||||||
titleLab.text = "合计"
|
titleLab.text = "合计"
|
||||||
titleLab.font = .systemFont(ofSize: 14, weight: .bold)
|
titleLab.font = .systemFont(ofSize: 14, weight: .bold)
|
||||||
|
|
@ -654,7 +655,7 @@ class VipRechargeView: UIView {
|
||||||
titleLab.layoutChain
|
titleLab.layoutChain
|
||||||
.left()
|
.left()
|
||||||
.bottom()
|
.bottom()
|
||||||
|
|
||||||
let symbolLab = UILabel()
|
let symbolLab = UILabel()
|
||||||
symbolLab.text = "¥"
|
symbolLab.text = "¥"
|
||||||
symbolLab.font = .systemFont(ofSize: 12, weight: .heavy)
|
symbolLab.font = .systemFont(ofSize: 12, weight: .heavy)
|
||||||
|
|
@ -663,21 +664,21 @@ class VipRechargeView: UIView {
|
||||||
symbolLab.layoutChain
|
symbolLab.layoutChain
|
||||||
.leftToRightOfView(titleLab)
|
.leftToRightOfView(titleLab)
|
||||||
.bottomToView(titleLab)
|
.bottomToView(titleLab)
|
||||||
|
|
||||||
view.addSubview(priceLab)
|
view.addSubview(priceLab)
|
||||||
priceLab.layoutChain
|
priceLab.layoutChain
|
||||||
.leftToRightOfView(symbolLab)
|
.leftToRightOfView(symbolLab)
|
||||||
.bottomToView(titleLab, offset: 3)
|
.bottomToView(titleLab, offset: 3)
|
||||||
|
|
||||||
view.addSubview(discountLab)
|
view.addSubview(discountLab)
|
||||||
discountLab.layoutChain
|
discountLab.layoutChain
|
||||||
.leftToRightOfView(priceLab, offset: 5)
|
.leftToRightOfView(priceLab, offset: 5)
|
||||||
.bottomToView(titleLab)
|
.bottomToView(titleLab)
|
||||||
.right()
|
.right()
|
||||||
|
|
||||||
return view
|
return view
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var priceLab: UILabel = {
|
lazy var priceLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.text = "0"
|
label.text = "0"
|
||||||
|
|
@ -685,7 +686,7 @@ class VipRechargeView: UIView {
|
||||||
label.textColor = UIColor(hexStr: "#FF3B05")
|
label.textColor = UIColor(hexStr: "#FF3B05")
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
/// 数字翻滚动画 — 每位数字独立向上或向下滚动
|
/// 数字翻滚动画 — 每位数字独立向上或向下滚动
|
||||||
func animatePrice(to newValue: String) {
|
func animatePrice(to newValue: String) {
|
||||||
guard let target = Double(newValue) else {
|
guard let target = Double(newValue) else {
|
||||||
|
|
@ -722,18 +723,18 @@ class VipRechargeView: UIView {
|
||||||
label.textColor = UIColor(hexStr: "#1A1A1A")
|
label.textColor = UIColor(hexStr: "#1A1A1A")
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
cornerView.setNeedsLayout()
|
cornerView.setNeedsLayout()
|
||||||
cornerView.layoutIfNeeded()
|
cornerView.layoutIfNeeded()
|
||||||
cornerView.setCornerRadius(corners: [.topLeft, .topRight], withCornerRadii: CGSize(width: 10, height: 10))
|
cornerView.setCornerRadius(corners: [.topLeft, .topRight], withCornerRadii: CGSize(width: 10, height: 10))
|
||||||
|
|
||||||
vipRightsDetailView.setNeedsLayout()
|
vipRightsDetailView.setNeedsLayout()
|
||||||
vipRightsDetailView.layoutIfNeeded()
|
vipRightsDetailView.layoutIfNeeded()
|
||||||
vipRightsDetailView.setCornerRadius(corners: [.topLeft, .bottomLeft], withCornerRadii: CGSize(width: 6, height: 6))
|
vipRightsDetailView.setCornerRadius(corners: [.topLeft, .bottomLeft], withCornerRadii: CGSize(width: 6, height: 6))
|
||||||
}
|
}
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: .zero)
|
super.init(frame: .zero)
|
||||||
backgroundColor = .white
|
backgroundColor = .white
|
||||||
|
|
@ -789,7 +790,7 @@ final class ExpenseCell: UICollectionViewCell {
|
||||||
label.textAlignment = .center
|
label.textAlignment = .center
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var priceLab: UILabel = {
|
lazy var priceLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .systemFont(ofSize: 12, weight: .bold)
|
label.font = .systemFont(ofSize: 12, weight: .bold)
|
||||||
|
|
@ -797,7 +798,7 @@ final class ExpenseCell: UICollectionViewCell {
|
||||||
label.textAlignment = .center
|
label.textAlignment = .center
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var originPriceLab: UILabel = {
|
lazy var originPriceLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .systemFont(ofSize: 12, weight: .bold)
|
label.font = .systemFont(ofSize: 12, weight: .bold)
|
||||||
|
|
@ -805,7 +806,7 @@ final class ExpenseCell: UICollectionViewCell {
|
||||||
label.textAlignment = .center
|
label.textAlignment = .center
|
||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
lazy var tipsLab: UILabel = {
|
lazy var tipsLab: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .systemFont(ofSize: 10, weight: .bold)
|
label.font = .systemFont(ofSize: 10, weight: .bold)
|
||||||
|
|
@ -839,15 +840,15 @@ final class ExpenseCell: UICollectionViewCell {
|
||||||
.centerX()
|
.centerX()
|
||||||
.top(30)
|
.top(30)
|
||||||
.edgesHorzontal(2)
|
.edgesHorzontal(2)
|
||||||
|
|
||||||
priceLab.layoutChain
|
priceLab.layoutChain
|
||||||
.centerY()
|
.centerY()
|
||||||
.edgesHorzontal(2)
|
.edgesHorzontal(2)
|
||||||
|
|
||||||
originPriceLab.layoutChain
|
originPriceLab.layoutChain
|
||||||
.topToBottomOfView(priceLab, offset: 5)
|
.topToBottomOfView(priceLab, offset: 5)
|
||||||
.edgesHorzontal(2)
|
.edgesHorzontal(2)
|
||||||
|
|
||||||
tipsLab.layoutChain
|
tipsLab.layoutChain
|
||||||
.edgesHorzontal(2)
|
.edgesHorzontal(2)
|
||||||
.bottom(7)
|
.bottom(7)
|
||||||
|
|
@ -887,7 +888,7 @@ final class ExpenseCell: UICollectionViewCell {
|
||||||
animations()
|
animations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
tagBadgeView.setNeedsLayout()
|
tagBadgeView.setNeedsLayout()
|
||||||
|
|
@ -898,12 +899,12 @@ final class ExpenseCell: UICollectionViewCell {
|
||||||
|
|
||||||
// MARK: - ExpenseCell
|
// MARK: - ExpenseCell
|
||||||
final class VipRightsCell: UICollectionViewCell {
|
final class VipRightsCell: UICollectionViewCell {
|
||||||
|
|
||||||
func configure(_ model: VipRightsModel) {
|
func configure(_ model: VipRightsModel) {
|
||||||
iconView.image = UIImage(named: model.icon)
|
iconView.image = UIImage(named: model.icon)
|
||||||
titleLabel.text = model.title
|
titleLabel.text = model.title
|
||||||
}
|
}
|
||||||
|
|
||||||
private let titleLabel: UILabel = {
|
private let titleLabel: UILabel = {
|
||||||
let label = UILabel()
|
let label = UILabel()
|
||||||
label.font = .systemFont(ofSize: 12, weight: .medium)
|
label.font = .systemFont(ofSize: 12, weight: .medium)
|
||||||
|
|
@ -917,7 +918,7 @@ final class VipRightsCell: UICollectionViewCell {
|
||||||
iv.contentMode = .scaleAspectFill
|
iv.contentMode = .scaleAspectFill
|
||||||
return iv
|
return iv
|
||||||
}()
|
}()
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
contentView.addSubview(titleLabel)
|
contentView.addSubview(titleLabel)
|
||||||
|
|
@ -927,7 +928,7 @@ final class VipRightsCell: UICollectionViewCell {
|
||||||
.top().centerX()
|
.top().centerX()
|
||||||
.width(40)
|
.width(40)
|
||||||
.height(40)
|
.height(40)
|
||||||
|
|
||||||
titleLabel.layoutChain
|
titleLabel.layoutChain
|
||||||
.edgesHorzontal()
|
.edgesHorzontal()
|
||||||
.bottom()
|
.bottom()
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import Moya
|
||||||
|
|
||||||
struct OrderService {
|
struct OrderService {
|
||||||
static let disposeBag = DisposeBag()
|
static let disposeBag = DisposeBag()
|
||||||
|
|
||||||
/// 充值内容
|
/// 充值内容
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - type: 类型 member
|
/// - type: 类型 member
|
||||||
|
|
@ -20,7 +20,7 @@ struct OrderService {
|
||||||
.map(VipExpenseResponse.self)
|
.map(VipExpenseResponse.self)
|
||||||
.asObservable()
|
.asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 支付参数
|
/// 支付参数
|
||||||
/// - Parameters:
|
/// - Parameters:
|
||||||
/// - goodsId: 商品ID
|
/// - goodsId: 商品ID
|
||||||
|
|
@ -33,4 +33,12 @@ struct OrderService {
|
||||||
.map(ResponseModel.self)
|
.map(ResponseModel.self)
|
||||||
.asObservable()
|
.asObservable()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apple 内购通知
|
||||||
|
static func appleNotify(receipt: String, productId: String, transactionId: String) -> Observable<Void> {
|
||||||
|
let api = OrderAPI.appleNotify(receipt: receipt, productId: productId, transactionId: transactionId).multiTarget
|
||||||
|
return APIProvider.request(token: api)
|
||||||
|
.map { _ in () }
|
||||||
|
.asObservable()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||