57
     
48 58
     public var userAvatar: Observable<String> {
49
-        return item.map({ v in
59
+        return itemViewModel.item.map({ v in
50 60
             return v.avatar
51 61
         })
52 62
     }
53 63
     
54 64
     public var photoTime: Observable<String> {
55
-        return item.map({ v in
65
+        return itemViewModel.item.map({ v in
56 66
             return v.create_at_time_interval
57 67
         })
58 68
     }
59 69
     
60 70
     public var thumbupCount: Observable<String> {
61
-        return _thumbupItems.map({ v in
71
+        return itemViewModel.thumbupItems.map({ v in
62 72
             return "(\(v.count))"
63 73
         })
64 74
     }
65 75
     
66 76
     public var commentCount: Observable<String> {
67
-        return _commentItems.map({ v in
68
-             return "(\(v.count))"
77
+        return itemViewModel.commentItems.map({ v in
78
+            return "(\(v.count))"
69 79
         })
70 80
     }
71 81
     
72 82
     public var canBuy: Observable<Bool> {
73
-        return item.map({ v in
83
+        return itemViewModel.item.map({ v in
74 84
             return v.display_payment_btn > 0
75 85
         })
76 86
     }
77 87
     
88
+    public var watermarkImage: Observable<Bool> {
89
+        return _hasGetPrice.asObservable()
90
+    }
91
+    
92
+    public var watermarkText: Observable<String> {
93
+        return _hasGetPrice.map ({ hasGetPrice in
94
+            return hasGetPrice ? "¥\(CGFloat(self.itemViewModel.item.value.nomark) / 100)" : "去除水印"
95
+        })
96
+    }
97
+    
98
+    public var watermarkTextWithBought: Observable<String> {
99
+        return itemViewModel.item.map({ v in
100
+            return v.murl.isEmpty ? "去除水印" : "查看无水印照片"
101
+        })
102
+    }
103
+    
104
+    public var watermarkImageWithBought: Observable<Bool> {
105
+        return itemViewModel.item.map({ v in
106
+            return !v.murl.isEmpty
107
+        })
108
+    }
109
+    
78 110
     public var isHiddenEnterGroupBtn = BehaviorRelay<Bool>(value: false)
79 111
     
80 112
     public var viewWillAppear = BehaviorRelay<Void>(value: ())
81 113
     public weak var delegate: PhotoDetailViewModelDelegate?
82 114
     
83
-    private var item: BehaviorRelay<PhotoItem>
84
-    private var _thumbupItems = BehaviorRelay<[PhotoThumbupUserItem]>(value: [])
85
-    private var _commentItems = BehaviorRelay<[PhotoCommentItem]>(value: [])
86
-
87
-    var repository: PhotoDetailRepository
115
+    public var content: Observable<[AnimatableSectionModel<Int, PhotoItem>]> {
116
+        return items.map({ model in
117
+            return [AnimatableSectionModel(model: 0, items: model)]
118
+        })
119
+    }
120
+ 
121
+    public init(items: [PhotoItem], currIndex: Int) {
122
+        self.items = BehaviorRelay<[PhotoItem]>(value: items)
123
+        self.currIndex = currIndex
124
+        self.itemViewModel = PhotoDetailItemViewModel(item: items[currIndex])
125
+        self.purchaseViewModel = PhotoPurchaseViewModel(item: items[currIndex])
126
+    }
88 127
     
89
-    var disposeBag = DisposeBag()
90
-
91
-    public init(item: PhotoItem) {
92
-        self.item = BehaviorRelay<PhotoItem>(value: item)
93
-        repository = PhotoDetailRepository(photoId: item.photo_id, groupId: item.group_id)
128
+    public func willShow(index: Int) {
129
+        currIndex = index
130
+        _hasGetPrice.accept(false)
131
+        itemViewModel.item.accept(items.value[index])
132
+        purchaseViewModel.switchItem(item: items.value[index])
94 133
         
95
-        self.item.subscribe(onNext: {[unowned self] (photoItem) in
96
-            self.repository = PhotoDetailRepository(photoId: photoItem.photo_id, groupId: photoItem.group_id)
97
-            self.loadCommentItems()
98
-            self.loadThumbupUserItems()
99
-        }).disposed(by: disposeBag)
134
+        purchaseViewModel.notifyPhotoChanged.subscribe(onNext: payDidFinish(item:)).disposed(by: disposeBag)
100 135
     }
101 136
     
102
-    private func loadThumbupUserItems() {
103
-        repository.loadThumbups().subscribe(onSuccess: { (items) in
104
-            self._thumbupItems.accept(items)
105
-        }).disposed(by: disposeBag)
137
+    public func submitThumbup() {
138
+        itemViewModel.submitThumbup()
106 139
     }
107 140
     
108
-    private func loadCommentItems() {
109
-        repository.loadComments().subscribe(onSuccess: { (items) in
110
-            self._commentItems.accept(items)
111
-        }).disposed(by: disposeBag)
141
+    public func submitComment(text: String) {
142
+        itemViewModel.submitComment(text: text)
112 143
     }
113
-
114
-    public final func submitThumbup() {
115
-        repository.submitThumbup().subscribe(onSuccess: { items in
116
-            self._thumbupItems.accept(items)
117
-        }).disposed(by: disposeBag)
144
+    
145
+    public func purchase() {
146
+        if !itemViewModel.item.value.murl.isEmpty {
147
+            delegate?.didSelected()
148
+            return
149
+        }
150
+        if !_hasGetPrice.value {
151
+            _hasGetPrice.accept(true)
152
+        } else {
153
+            Toast.showActivity(message: "正在支付")
154
+            purchaseViewModel.purchase()
155
+        }
118 156
     }
119
-
120
-    public final func submitComment(text: String) {
121
-        repository.submitComment(text: text).subscribe(onSuccess: { (items) in
122
-            self._commentItems.accept(items)
123
-        }).disposed(by: disposeBag)
157
+    
158
+    public func payDidFinish(item: PhotoItem) {
159
+        var originItems = items.value
160
+        originItems[currIndex] = item
161
+        items.accept(originItems)
162
+        itemViewModel.item.accept(item)
124 163
     }
125 164
     
126 165
     public func navigateToGroup() {
127
-        delegate?.navigateToGroup(GroupItem(json: item.value.toJSON() as [String : AnyObject]))
166
+        delegate?.navigateToGroup(GroupItem(json: items.value[currIndex].toJSON() as [String : AnyObject]))
128 167
     }
129
-}
130
-
131
-extension PhotoDetailViewModel: PhotoDetailListViewModelSynchronization {
132
-    public func willShow(_ item: PhotoItem) {
133
-        self.item.accept(item)
168
+    
169
+    public func didSelected() {
170
+        delegate?.didSelected()
134 171
     }
135 172
 }

+ 43 - 101
PaiAi/PaiaiDataKit/PresentLayer/PhotoDetail/PhotoPurchaseViewModel.swift

@@ -7,116 +7,58 @@
7 7
 //
8 8
 
9 9
 import Foundation
10
+import RxSwift
11
+import RxCocoa
10 12
 
11 13
 //wechat pay
12
-extension PhotoDetailViewModel {
13
-    public final func handleResult(errorCode: Int, success: @escaping ((_ item: PhotoItem) -> Void)) {
14
-        //        func fetchOrderDetail() {
15
-        //            detailPageApi.post(param: ["order_id": orderId, "user_id": SharedUserInfo.userId] as [String: AnyObject], url: .orderDetail) { (result) in
16
-        //                guard let status = result["status"] as? Int, let data = result["data"] as? [String: AnyObject], let photoInfo = data["group_photo_info"] as? [String: AnyObject], status == 200 else {
17
-        ////                    FFToastView.hideLoadingToast()
18
-        ////                    FFToastView.showToast(inView: UIApplication.shared.keyWindow!, withText: "")
19
-        //                    return
20
-        //                }
21
-        //                let PhotoItem = PhotoItem(map: Map(mappingType: .fromJSON, JSON: photoInfo))
22
-        //                self.currentPhoto.murl = PhotoItem.murl
23
-        //                self.currentPhoto.rurl = PhotoItem.rurl
24
-        //                success(PhotoItem)
25
-        ////                FFToastView.hideLoadingToast()
26
-        ////                FFToastView.showToast(inView: UIApplication.shared.keyWindow!, withText: "")
27
-        ////                PhotoLocalStorage.instance.updateLocalData(PhotoItem: PhotoItem)
28
-        //            }
29
-        //        }
30
-        ////        Delay(3) {
31
-        //            let orderQequest = StatusNetworkRequest(param: ["order_id": self.orderId as AnyObject], path: .orderQuery)
32
-        //            self.detailPageApi.post(request: orderQequest, handler: { (res) in
33
-        //                if res.status == 200 {
34
-        //                    fetchOrderDetail()
35
-        //                } else {
36
-        ////                    FFToastView.hideLoadingToast()
37
-        ////                    FFToastView.showToast(inView: UIApplication.shared.keyWindow!, withText: "支付失败")
38
-        //                }
39
-        //            })
40
-        ////        }
14
+public class PhotoPurchaseViewModel {
15
+    private var purchaseAPI: PhotoPurchaseRemoteAPI
16
+    private var disposeBag = DisposeBag()
17
+    private var orderId: String = ""
18
+    
19
+    public var notifyPhotoChanged = PublishSubject<PhotoItem>()
20
+    
21
+    public init(item: PhotoItem) {
22
+        self.purchaseAPI = PhotoPurchaseRemoteAPI(item: item)
23
+        
24
+        payDidFinish()
41 25
     }
42 26
     
43
-    public final func getHD(getPriceSuccess: ((_ isExist: Bool) -> Void)?) {
44
-        //        if !currentPhoto.rurl.isEmpty {
45
-        //            getPriceSuccess!(true)
46
-        //            return
47
-        //        } else {
48
-        //            if hdPrice != -0.01 {
49
-        //                payPrice(photoType: "origin")
50
-        //            } else {
51
-        //                getPrice(photoType: "origin", success: getPriceSuccess)
52
-        //            }
53
-        //        }
27
+    public func switchItem(item: PhotoItem) {
28
+        self.purchaseAPI = PhotoPurchaseRemoteAPI(item: item)
54 29
     }
55 30
     
56
-    public final func getWatermark(getPriceSuccess: ((_ isExist: Bool) -> Void)?) {
57
-        //        if !currentPhoto.murl.isEmpty {
58
-        //            getPriceSuccess!(true)
59
-        //            return
60
-        //        } else {
61
-        //            if watermarkPrice != -0.01 {
62
-        //                payPrice(photoType: "nomark")
63
-        //            } else {
64
-        //                getPrice(photoType: "nomark", success: getPriceSuccess)
65
-        //            }
66
-        //        }
31
+    public func purchase() {
32
+        purchaseAPI.purchase().subscribe(onSuccess: {[weak self] orderId in
33
+            guard let `self` = self else { return }
34
+            self.orderId = orderId
35
+        }).disposed(by: disposeBag)
67 36
     }
68 37
     
69
-    public final func payPrice(photoType: String) {
70
-        //下单
71
-        //        let body = photoType == "origin" ? "获取高清照片" : "获取去水印照片"
72
-        //        let price = photoType == "origin" ? hdPrice : watermarkPrice
73
-        //        let params = ["user_id": SharedUserInfo.userId, "body": body, "total_fee": price, "trade_type": "APP", "group_id": currentPhoto.group_id, "photo_id": currentPhoto.photo_id, "photo_type": photoType] as [String: AnyObject]
74
-        //        detailPageApi.post(param: params, url: .wxorderCreat) { (result) in
75
-        ////            FFToastView.hideLoadingToast()
76
-        //            guard let status = result["status"] as? Int, let items = result["data"] as? [String: AnyObject], status == 200 else {
77
-        //                return
78
-        //            }
79
-        //            if let orderid = items["order_id"] as? String, let prepay_id = items["prepay_id"] as? String, let wxpay_params = items["wxpay_params"] as? [String: AnyObject], let appid = wxpay_params["appid"] as? String, let noncestr = wxpay_params["noncestr"] as? String, let package = wxpay_params["package"] as? String, let sign = wxpay_params["sign"] as? String, let partnerid = wxpay_params["partnerid"] as? String, let timestamp = wxpay_params["timestamp"] as? String {
80
-        //                //支付
81
-        //                self.orderId = orderid
82
-        //                #if !((arch(i386) || arch(x86_64)))
83
-        //                    guard WXApi.isWXAppInstalled() else {
84
-        //                        FFToastView.showToast(inView: UIApplication.shared.keyWindow!, withText: "尚未安装微信")
85
-        //                        return
86
-        //                    }
87
-        //
88
-        //                    WXApi.registerApp(appid)
89
-        //                    let payRequest = PayReq()
90
-        //                    payRequest.openID = appid
91
-        //                    payRequest.partnerId = partnerid
92
-        //                    payRequest.prepayId = prepay_id
93
-        //                    payRequest.package = package
94
-        //                    payRequest.nonceStr = noncestr
95
-        //                    payRequest.timeStamp = UInt32(timestamp) ?? 0
96
-        //                    payRequest.sign = sign
97
-        //                    WXApi.send(payRequest)
98
-        //                #endif
99
-        //            }
100
-        //        }
38
+    private func payDidFinish() {
39
+        NotificationCenter.default.rx.notification(Notification.wxNotification.payDidFinish).subscribe(onNext: { (notification) in
40
+            guard let userInfo = notification.userInfo as? [String: Int],
41
+                let code = userInfo["code"] else {
42
+                Toast.show(message: "支付失败")
43
+                return
44
+            }
45
+            
46
+            switch code {
47
+            case 0:
48
+                self.getOrderDetail()
49
+                break
50
+            case -2:
51
+                Toast.show(message: "取消支付")
52
+                break
53
+            default:
54
+                Toast.show(message: "发生未知错误")
55
+            }
56
+        }).disposed(by: disposeBag)
101 57
     }
102 58
     
103
-    public final func getPrice(photoType: String, success: ((_ isExist: Bool) -> Void)?) {
104
-        //        let params = ["user_id": SharedUserInfo.userId, "photo_id": currentPhoto.photo_id, "photo_type": photoType] as [String: AnyObject]
105
-        //        detailPageApi.post(param: params, url: .picPrice) {[weak self] (result) in
106
-        //            guard let status = result["status"] as? Int,
107
-        //                let items = result["data"] as? [String: AnyObject],
108
-        //                status == 200,
109
-        //                let weakself = self else {
110
-        //                return
111
-        //            }
112
-        //            if let price = items["price"] as? Double {
113
-        //                if photoType == "origin"{
114
-        //                    weakself.hdPrice = price
115
-        //                } else {
116
-        //                    weakself.watermarkPrice = price
117
-        //                }
118
-        //                success!(false)
119
-        //            }
120
-        //        }
59
+    private func getOrderDetail() {
60
+        purchaseAPI.getOrderDetail(orderId: orderId).subscribe(onSuccess: { item in
61
+            self.notifyPhotoChanged.onNext(item)
62
+        }).disposed(by: disposeBag)
121 63
     }
122 64
 }

+ 1 - 1
PaiAi/PaiaiDataKit/PresentLayer/UserInfoViewModel.swift

@@ -77,7 +77,7 @@ public class UserInfoViewModel {
77 77
     }
78 78
     
79 79
     public func wxLogin() {
80
-        repository.guestLogin().subscribe(onSuccess: { (userInfo) in
80
+        repository.wxLogin().subscribe(onSuccess: { (userInfo) in
81 81
             self.shareUserInfo.accept(userInfo)
82 82
             self._loginCompleted.onNext(())
83 83
         }) { (error) in

+ 15 - 0
PaiAi/PaiaiDataKit/Resuable/Extension/Notification+wxPay.swift

@@ -0,0 +1,15 @@
1
+//
2
+//  Notification+wxPay.swift
3
+//  PaiaiDataKit
4
+//
5
+//  Created by ffib on 2019/4/1.
6
+//  Copyright © 2019 yb. All rights reserved.
7
+//
8
+
9
+import Foundation
10
+
11
+public extension Notification {
12
+    struct wxNotification {
13
+        public static let payDidFinish = Notification.Name("WXPayDidFinishNotification")
14
+    }
15
+}

+ 1 - 1
PaiAi/Paiai_iOS/App/AppCoordinator.swift

@@ -72,7 +72,7 @@ fileprivate extension AppCoordinator {
72 72
     func makeMineCoordinator() -> MineCoordinator {
73 73
         let mineVC = makeMineViewController()
74 74
         mineVC.userInfoViewModel = shareUserInfoViewModel
75
-        let mineCoordinator = MineCoordinator(mineVC, navigationController: navigationController)
75
+        let mineCoordinator = MineCoordinator(mineVC, navigationController: navigationController, mainViewController: containerViewController)
76 76
         
77 77
         return mineCoordinator
78 78
     }

+ 2 - 3
PaiAi/Paiai_iOS/App/Group/GroupCoordinator.swift

@@ -35,11 +35,10 @@ extension GroupCoordinator: GroupViewModelDelegate {
35 35
     
36 36
     func didSelect(_ items: [PhotoItem], currIndex: Int) {
37 37
         let ctl = UIStoryboard.photoDetail.instantiateController(PhotoDetailViewController.self)
38
-        let viewModel = PhotoDetailViewModel(item: items[currIndex])
38
+        let viewModel = PhotoDetailViewModel(items: items, currIndex: currIndex)
39 39
         viewModel.isHiddenEnterGroupBtn.accept(true)
40 40
         let coordinator = PhotoDetailCoordinator(ctl, nav: navigationController,
41
-                                                 viewModel: viewModel,
42
-                                                 listViewModel: PhotoDetailListViewModel(items: items, currIndex: currIndex))
41
+                                                 viewModel: viewModel)
43 42
         coordinators[.photoDetail] = coordinator
44 43
         coordinator.start()
45 44
         navigationController.pushViewController(coordinator.photoDetailViewController)

+ 1 - 2
PaiAi/Paiai_iOS/App/Home/HomeCoordinator.swift

@@ -35,8 +35,7 @@ extension HomeCoordinator: HomeViewModelDelegate {
35 35
     func didSelect(_ items: [PhotoItem], currIndex: Int) {
36 36
         let ctl = UIStoryboard.photoDetail.instantiateController(PhotoDetailViewController.self)
37 37
         let coordinator = PhotoDetailCoordinator(ctl, nav: navigationController,
38
-                                                 viewModel: PhotoDetailViewModel(item: items[currIndex]),
39
-                                                 listViewModel: PhotoDetailListViewModel(items: items, currIndex: currIndex))
38
+                                                 viewModel: PhotoDetailViewModel(items: items, currIndex: currIndex))
40 39
         coordinators[.photoDetail] = coordinator
41 40
         coordinator.start()
42 41
         navigationController.pushViewController(coordinator.photoDetailViewController)

+ 13 - 11
PaiAi/Paiai_iOS/App/Mine/Mine.storyboard

@@ -1,11 +1,11 @@
1 1
 <?xml version="1.0" encoding="UTF-8"?>
2
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">
2
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useSafeAreas="YES" colorMatched="YES">
3 3
     <device id="retina4_7" orientation="portrait">
4 4
         <adaptation id="fullscreen"/>
5 5
     </device>
6 6
     <dependencies>
7 7
         <deployment identifier="iOS"/>
8
-        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
8
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
9 9
         <capability name="Safe area layout guides" minToolsVersion="9.0"/>
10 10
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
11 11
     </dependencies>
@@ -43,7 +43,7 @@
43 43
                                                     </userDefinedRuntimeAttributes>
44 44
                                                 </imageView>
45 45
                                                 <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="GAH-5d-ArA">
46
-                                                    <rect key="frame" x="339" y="12" width="24" height="36"/>
46
+                                                    <rect key="frame" x="355" y="24" width="8" height="12"/>
47 47
                                                 </imageView>
48 48
                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="群名称" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Bx9-cB-B0U">
49 49
                                                     <rect key="frame" x="70" y="6" width="49" height="19.5"/>
@@ -60,7 +60,7 @@
60 60
                                                     <nil key="highlightedColor"/>
61 61
                                                 </label>
62 62
                                                 <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="有0张照片" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aOD-P8-U4F">
63
-                                                    <rect key="frame" x="271" y="22" width="62" height="16"/>
63
+                                                    <rect key="frame" x="287" y="22" width="62" height="16"/>
64 64
                                                     <fontDescription key="fontDescription" type="system" pointSize="13"/>
65 65
                                                     <color key="textColor" red="0.29411764709999999" green="0.29411764709999999" blue="0.29411764709999999" alpha="1" colorSpace="calibratedRGB"/>
66 66
                                                     <nil key="highlightedColor"/>
@@ -213,7 +213,7 @@
213 213
                                                 <nil key="highlightedColor"/>
214 214
                                             </label>
215 215
                                             <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="MgR-ta-3jg">
216
-                                                <rect key="frame" x="341" y="6" width="24" height="36"/>
216
+                                                <rect key="frame" x="357" y="18" width="8" height="12"/>
217 217
                                             </imageView>
218 218
                                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="L1g-sb-a5F">
219 219
                                                 <rect key="frame" x="0.0" y="0.0" width="375" height="48"/>
@@ -248,7 +248,7 @@
248 248
                                                 <nil key="highlightedColor"/>
249 249
                                             </label>
250 250
                                             <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="vLw-Zd-Mis">
251
-                                                <rect key="frame" x="341" y="6" width="24" height="36"/>
251
+                                                <rect key="frame" x="357" y="18" width="8" height="12"/>
252 252
                                             </imageView>
253 253
                                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FIE-jb-ZGu">
254 254
                                                 <rect key="frame" x="0.0" y="0.0" width="375" height="48"/>
@@ -283,7 +283,7 @@
283 283
                                                 <nil key="highlightedColor"/>
284 284
                                             </label>
285 285
                                             <imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="list-arrow" translatesAutoresizingMaskIntoConstraints="NO" id="mhJ-Uj-tdj">
286
-                                                <rect key="frame" x="341" y="6" width="24" height="36"/>
286
+                                                <rect key="frame" x="357" y="18" width="8" height="12"/>
287 287
                                             </imageView>
288 288
                                             <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="VGv-oO-leT">
289 289
                                                 <rect key="frame" x="0.0" y="0.0" width="375" height="48"/>
@@ -539,6 +539,9 @@
539 539
                                                 <state key="normal" title="登出" image="BTN-logout">
540 540
                                                     <color key="titleColor" red="0.59999999999999998" green="0.59999999999999998" blue="0.59999999999999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
541 541
                                                 </state>
542
+                                                <connections>
543
+                                                    <action selector="loginOutAction:" destination="Kfp-Vc-gX5" eventType="touchUpInside" id="P1V-ug-XRT"/>
544
+                                                </connections>
542 545
                                             </button>
543 546
                                         </subviews>
544 547
                                         <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
@@ -577,7 +580,6 @@
577 580
                     </view>
578 581
                     <connections>
579 582
                         <outlet property="headerImageView" destination="diQ-B5-xB7" id="BrO-2N-Srv"/>
580
-                        <outlet property="logoutBtn" destination="uFJ-qP-CrW" id="VHg-fH-Znk"/>
581 583
                         <outlet property="mineView" destination="Jhj-pW-9Bq" id="DAA-ov-Pzt"/>
582 584
                         <outlet property="nickNameLabel" destination="59p-Cg-joQ" id="a4i-ff-np8"/>
583 585
                         <outlet property="tableView" destination="79F-2W-LpP" id="tPr-Iw-4MA"/>
@@ -589,14 +591,14 @@
589 591
         </scene>
590 592
     </scenes>
591 593
     <resources>
592
-        <image name="BTN-logout" width="32" height="32"/>
594
+        <image name="BTN-logout" width="48" height="48"/>
593 595
         <image name="BTN-send" width="608" height="304"/>
594 596
         <image name="about-contactUs" width="32" height="32"/>
595 597
         <image name="about-score" width="32" height="32"/>
596 598
         <image name="about-userAgreement" width="32" height="32"/>
597
-        <image name="list-arrow" width="24" height="36"/>
599
+        <image name="list-arrow" width="8" height="12"/>
598 600
         <image name="logo" width="140" height="140"/>
599
-        <image name="navigation-background" width="12" height="132"/>
601
+        <image name="navigation-background" width="6" height="66"/>
600 602
         <image name="默认头像" width="240" height="240"/>
601 603
     </resources>
602 604
 </document>

+ 7 - 2
PaiAi/Paiai_iOS/App/Mine/MineCoordinator.swift

@@ -15,11 +15,13 @@ class MineCoordinator: Coordinator {
15 15
     let mineViewController: MineViewController
16 16
     let navigationController: UINavigationController
17 17
     var childCoordinator = [CoordinatorKey: Coordinator]()
18
+    let mainViewController: ContainerViewController
18 19
 //    let shareUserInfoViewModel
19 20
     
20
-    init(_ mineViewController: MineViewController, navigationController: UINavigationController) {
21
+    init(_ mineViewController: MineViewController, navigationController: UINavigationController, mainViewController: ContainerViewController) {
21 22
         self.mineViewController = mineViewController
22 23
         self.navigationController = navigationController
24
+        self.mainViewController = mainViewController
23 25
         self.mineViewController.delegate = self
24 26
     }
25 27
     
@@ -30,8 +32,11 @@ class MineCoordinator: Coordinator {
30 32
 
31 33
 extension MineCoordinator: MineViewControllerDelegate {
32 34
     func logout() {
35
+        mineViewController.dismissController()
36
+        
33 37
         let vc = makeLoginViewController()
34
-        navigationController.presentController(vc)
38
+        vc.userInfoViewModel = mineViewController.userInfoViewModel
39
+        navigationController.addFullScreen(childViewController: vc)
35 40
     }
36 41
     
37 42
     func didSelect(_ item: MineItem) {

+ 0 - 1
PaiAi/Paiai_iOS/App/Mine/MineViewController.swift

@@ -33,7 +33,6 @@ class MineViewController: SideViewController {
33 33
 
34 34
     @IBOutlet weak var headerImageView: UIImageView!
35 35
     @IBOutlet weak var nickNameLabel: UILabel!
36
-    @IBOutlet weak var logoutBtn: UIButton!
37 36
     @IBOutlet weak var tableView: UITableView!
38 37
     @IBOutlet weak var mineView: UIView!
39 38
     

+ 5 - 11
PaiAi/Paiai_iOS/App/PhotoDetail/PhotoDetailCoordinator.swift

@@ -12,23 +12,19 @@ import PaiaiDataKit
12 12
 final class PhotoDetailCoordinator: Coordinator {
13 13
     let navigationController: UINavigationController
14 14
     let photoDetailViewController: PhotoDetailViewController
15
-    let shareListViewModel: PhotoDetailListViewModel
15
+    let shareViewModel: PhotoDetailViewModel
16 16
     
17 17
     fileprivate var coordinators = [CoordinatorKey: Coordinator]()
18 18
     
19 19
     init(_ photoDetailVC: PhotoDetailViewController,
20 20
          nav: UINavigationController,
21
-         viewModel: PhotoDetailViewModel,
22
-         listViewModel: PhotoDetailListViewModel) {
21
+         viewModel: PhotoDetailViewModel) {
23 22
         photoDetailViewController = photoDetailVC
24
-        shareListViewModel = listViewModel
23
+        shareViewModel = viewModel
25 24
         navigationController = nav
26
-        photoDetailViewController.listViewModel = shareListViewModel
27 25
         photoDetailViewController.viewModel = viewModel
28 26
         
29 27
         viewModel.delegate = self
30
-        shareListViewModel.synchronization = viewModel
31
-        shareListViewModel.delegate = self
32 28
     }
33 29
     
34 30
     func start() {
@@ -46,12 +42,10 @@ extension PhotoDetailCoordinator: PhotoDetailViewModelDelegate {
46 42
         
47 43
         navigationController.pushViewController(vc)
48 44
     }
49
-}
50
-
51
-extension PhotoDetailCoordinator: PhotoDetailListViewModelDelegate {
45
+    
52 46
     func didSelected() {
53 47
         let vc = UIStoryboard.photoDetail.instantiateController(PhotoPreviewViewController.self)
54
-        vc.viewModel = shareListViewModel
48
+        vc.viewModel = shareViewModel
55 49
         photoDetailViewController.presentController(vc)
56 50
     }
57 51
 }

+ 28 - 11
PaiAi/Paiai_iOS/App/PhotoDetail/PhotoDetailViewController.swift

@@ -13,9 +13,6 @@ import RxDataSources
13 13
 import PaiaiDataKit
14 14
 import PaiaiUIKit
15 15
 
16
-let kPhotographerMark = 1
17
-
18
-
19 16
 final class PhotoDetailViewController: UIViewController {
20 17
 
21 18
     @IBOutlet weak var enterGroupView: UIView!
@@ -50,7 +47,6 @@ final class PhotoDetailViewController: UIViewController {
50 47
     
51 48
     // MARK: data property
52 49
     var viewModel: PhotoDetailViewModel!
53
-    var listViewModel: PhotoDetailListViewModel!
54 50
     
55 51
     let disposeBag = DisposeBag()
56 52
 
@@ -90,11 +86,11 @@ extension PhotoDetailViewController {
90 86
     }
91 87
     
92 88
     @IBAction func purchase(_ sender: UITapGestureRecognizer) {
93
-        
89
+        viewModel.purchase()
94 90
     }
95 91
     
96 92
     @IBAction func enterGroup(_ sender: UITapGestureRecognizer) {
97
-        self.viewModel.navigateToGroup()
93
+        viewModel.navigateToGroup()
98 94
     }
99 95
 }
100 96
 
@@ -139,7 +135,7 @@ extension PhotoDetailViewController {
139 135
     var photoCollectionViewDataSource: RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>> {
140 136
         return RxCollectionViewSectionedAnimatedDataSource<AnimatableSectionModel<Int, PhotoItem>>(configureCell: { (dataSource, collectionView, indexPath, item) in
141 137
             let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "photoDetailImageCell", for: indexPath) as! PhotoDetailImageCell
142
-            cell.imageView.setImage(item.photo_thumbnail2_url, placeholder: UIImage.photoPlaceholder)
138
+            cell.imageView.setImage(item.murl.isEmpty ? item.photo_thumbnail2_url : item.murl, placeholder: UIImage.photoPlaceholder)
143 139
             return cell
144 140
         })
145 141
     }
@@ -168,6 +164,11 @@ extension PhotoDetailViewController {
168 164
         bindCollectionViewToListViewModel()
169 165
         bindListViewModelToCollectionView()
170 166
         
167
+        bindViewModelToWatermarkImage()
168
+        bindViewModelToWatermarkLabel()
169
+        bindViewModelToWatermarkImageWithBought()
170
+        bindViewModelToWatermarkLabelWithBought()
171
+        
171 172
         bindViewWillAppear()
172 173
         
173 174
         monitorKeyboardWillShow()
@@ -244,7 +245,7 @@ extension PhotoDetailViewController {
244 245
     }
245 246
     
246 247
     func bindListViewModelToCollectionView() {
247
-        listViewModel.content
248
+        viewModel.content
248 249
             .bind(to: photoCollectionView.rx.items(dataSource: photoCollectionViewDataSource))
249 250
             .disposed(by: disposeBag)
250 251
     }
@@ -253,7 +254,7 @@ extension PhotoDetailViewController {
253 254
         photoCollectionView.rx.willDisplayCell
254 255
             .asDriver()
255 256
             .drive(onNext: { [unowned self] in
256
-                self.listViewModel.willShow(index: $0.at.row)
257
+                self.viewModel.willShow(index: $0.at.row)
257 258
             })
258 259
             .disposed(by: disposeBag)
259 260
     }
@@ -261,15 +262,31 @@ extension PhotoDetailViewController {
261 262
     func bindCollectionViewSelected() {
262 263
         photoCollectionView.rx.itemSelected
263 264
             .asDriver(onErrorJustReturn: IndexPath(item: 0, section: 0))
264
-            .drive(onNext: { [unowned self] _ in self.listViewModel.didSelected() })
265
+            .drive(onNext: { [unowned self] _ in self.viewModel.didSelected() })
265 266
             .disposed(by: disposeBag)
266 267
     }
267 268
     
269
+    func bindViewModelToWatermarkImage() {
270
+        viewModel.watermarkImage.bind(to: waterMarkImage.rx.isHidden).disposed(by: disposeBag)
271
+    }
272
+    
273
+    func bindViewModelToWatermarkLabel() {
274
+        viewModel.watermarkText.bind(to: waterMarkLabel.rx.text).disposed(by: disposeBag)
275
+    }
276
+    
277
+    func bindViewModelToWatermarkImageWithBought() {
278
+        viewModel.watermarkImageWithBought.bind(to: waterMarkImage.rx.isHidden).disposed(by: disposeBag)
279
+    }
280
+    
281
+    func bindViewModelToWatermarkLabelWithBought() {
282
+        viewModel.watermarkTextWithBought.bind(to: waterMarkLabel.rx.text).disposed(by: disposeBag)
283
+    }
284
+    
268 285
     func bindViewWillAppear() {
269 286
         viewModel.viewWillAppear
270 287
             .asDriver()
271 288
             .drive(onNext: { [unowned self] _ in
272
-                self.photoCollectionView.scrollToItem(at: IndexPath(item: self.listViewModel.currIndex, section: 0), at: .right, animated: false)
289
+                self.photoCollectionView.scrollToItem(at: IndexPath(item: self.viewModel.currIndex, section: 0), at: .right, animated: false)
273 290
             })
274 291
             .disposed(by: disposeBag)
275 292
     }

+ 1 - 2
PaiAi/Paiai_iOS/App/PhotoDetail/PhotoPreviewViewController.swift

@@ -17,7 +17,7 @@ final class PhotoPreviewViewController: UIViewController {
17 17
 
18 18
     /// MARK: Storyboard property
19 19
     @IBOutlet weak var collectionView: UICollectionView!
20
-    var viewModel: PhotoDetailListViewModel!
20
+    var viewModel: PhotoDetailViewModel!
21 21
     var disposeBag = DisposeBag()
22 22
     
23 23
     override var prefersStatusBarHidden: Bool {
@@ -29,7 +29,6 @@ final class PhotoPreviewViewController: UIViewController {
29 29
         binding()
30 30
         scrollToSpecifiedImage()
31 31
         navigationController?.setNavigationBarHidden(true, animated: true)
32
-        
33 32
     }
34 33
     
35 34
     func scrollToSpecifiedImage() {

kodo - Gogs: Go Git Service

説明なし

FFIB: c25c1f86d3 处理解绑后,再次扫码,不发放相关权益 3 年 前
..
0001_initial.py aa31a5f59a Add kodo 8 年 前
0002_auto_20180104_0414.py 018d52f61d Update package django_xxx 8 年 前
0003_auto_20180104_0428.py 9ec76d526a TextField => CharField 8 年 前
0004_latestappinfo.py 018d52f61d Update package django_xxx 8 年 前
0005_auto_20180115_0021.py 49634dc097 Add api operator login 8 年 前
0006_auto_20180115_0047.py 49634dc097 Add api operator login 8 年 前
0007_consumeinfosubmitloginfo.py 1b1f0192f8 ConsumeInfoSubmitLogInfo 8 年 前
0008_auto_20180129_0422.py a77c4993f8 FloatField 8 年 前
0009_auto_20180129_0426.py e04f95dc5e long => lon 8 年 前
0010_modelinfo_integral.py 71993af1e4 Add integral for ModelInfo 8 年 前
0011_modelinfo_model_full_name.py 145973f8f0 Add brand_full_name for BrandInfo 8 年 前
0012_auto_20180401_2012.py f1260953bf Move image/url from ModelImageInfo to ModelInfo 8 年 前
0013_consumeinfosubmitloginfo_test_user.py e47aa7f8c4 Add field test_user 8 年 前
0014_auto_20180508_1058.py c7b55979c0 Add province code/name for DistributorInfo 8 年 前
0015_auto_20180508_1433.py d10bd672ea AdministratorInfo/BrandModelDistributorPriceInfo 8 年 前
0016_auto_20180508_1507.py d10bd672ea AdministratorInfo/BrandModelDistributorPriceInfo 8 年 前
0017_auto_20180508_1830.py 537c495621 Statistic 8 年 前
0018_auto_20180514_1519.py 62948fb5c3 Operator add/delete/update/list 8 年 前
0019_saleclerkinfo.py 137ed6dee2 Clerk add/delete/update/list 8 年 前
0020_auto_20180517_1819.py 2988703c52 Update 8 年 前
0021_auto_20180522_1100.py e7dcf47e22 SaleclerkInfo 8 年 前
0022_auto_20180522_1355.py b90bf186bc brand_domain 8 年 前
0023_auto_20180826_0448.py 3f9969cafc Support scan jancode 8 年 前
0024_latestappscreeninfo.py 900c3fd386 Makemigrations 8 年 前
0025_auto_20180917_1554.py 9c585b197e Mch migrations 7 年 前
0026_auto_20180930_1159.py 66a598b30c Makemigrations 7 年 前
0027_distributorinfo_distributor_short_name.py deb84bfcb5 Makemigrations 7 年 前
0028_consumeinfosubmitloginfo_dupload.py e9f8a35b9d Makemigrations 7 年 前
0029_auto_20181117_0052.py b8784eee8a Makemigrations 7 年 前
0030_auto_20190301_1402.py ff3a23ccf0 Activity 7 年 前
0031_activityinfo_model_uni_names.py ded4db2cda activityinfo_model_uni_names 7 年 前
0032_auto_20190521_1544.py 5a8859fa5e Makemigrations 7 年 前
0033_consumeinfosubmitloginfo_activity_id.py 3ade638ea3 Makemigrations 7 年 前
0034_auto_20190620_1709.py d666c88eac COUPON_EXPIRED_TIME_TUPLE 7 年 前
0035_auto_20190625_1443.py 219acdedb1 Add field has_used 7 年 前
0036_auto_20190701_1441.py 77c612316a queryusedsn 7 年 前
0037_auto_20190826_1537.py 8d998319f7 Makemigrations 7 年 前
0038_auto_20190826_1625.py 9db41fee66 default False 7 年 前
0039_auto_20191119_1348.py 3d0d214667 :sparkles: Member Infos 6 年 前
0040_modelinfo_shot_member_name.py 4ce7f5c87b :art: Member Relative APIs 6 年 前
0041_activityinfo_coupon_id.py a8239c077f :art: CouponInfo for coupon app 6 年 前
0042_auto_20200113_1832.py 212f24c882 MarketCode 6 年 前
0043_modelcamerabodyinfo.py 72656ceaff :art: model/cameras 6 年 前
0044_modelcamerabodyinfo_camera_brand_name.py 9619c195e6 :art: Makemigrations 6 年 前
0045_auto_20200304_1826.py dccd94c448 :art: Opt api model/cameras 6 年 前
0046_cameramodelinfo.py dccd94c448 :art: Opt api model/cameras 6 年 前
0047_auto_20200304_1848.py dccd94c448 :art: Opt api model/cameras 6 年 前
0048_modelcamerabodyinfo_is_important.py 43455cdf4e :art: Support is_important 6 年 前
0049_modelcamerabodyinfo_camera_market_time.py da799e7af6 :art: Add field camera_market_time for CameraModelInfo/ModelCameraBodyInfo 6 年 前
0050_cameramodelinfo_camera_market_time.py da799e7af6 :art: Add field camera_market_time for CameraModelInfo/ModelCameraBodyInfo 6 年 前
0051_auto_20200314_2340.py 7dc0b7fc6b :art: Makemigrations 6 年 前
0052_consumeinfosubmitloginfo_code_version.py 03631cb847 add code_version 6 年 前
0053_auto_20200407_1118.py 608bdf8508 makemigrations 6 年 前
0054_auto_20200411_2143.py 58c38a0546 整理 优惠券 6 年 前
0055_auto_20200601_1634.py 89c3cefcc7 saleclerk migrate 6 年 前
0056_auto_20200601_1640.py 3872355991 add department_name 6 年 前
0057_auto_20200602_1403.py 11df57b63d support qy login 6 年 前
0058_auto_20201202_1203.py 6a9e324f6f :art: Re Makemigrations 5 年 前
0059_auto_20201221_1115.py 4ba79f76cd 后台管理,添加运营人员角色 5 年 前
0060_modelinfo_is_show_shot.py 45f886651e 添加 is_show_shot 用于控制是否在前端显示 5 年 前
0061_consumeinfosubmitloginfo_integral.py 39290e111b ConsumeInfoSubmitLogInfo 记录用户积分 5 年 前
0062_distributorinfo_office.py 8dcde2c80c 销售员提交新增事务所和销售担当,以及经销商ID 5 年 前
0063_auto_20210915_1653.py 414cc1ada2 :art: back_express_name / back_tracking_number 4 年 前
0064_alter_modelinfo_display.py 28f8bc3cb9 :art: Models update for tenancy 3 年 前
0065_auto_20221118_1657.py 7f990a3af6 增加型号卡口, 3 年 前
0066_auto_20230208_1344.py ed0e1dba9a 清除一些无用字段 3 年 前
0067_consumeshotunbindinginfo.py 0a9dd97a7e 增加解绑功能 3 年 前
0068_alter_consumeshotunbindinginfo_reason.py 0a9dd97a7e 增加解绑功能 3 年 前
0069_auto_20230302_1754.py c25c1f86d3 处理解绑后,再次扫码,不发放相关权益 3 年 前
__init__.py aa31a5f59a Add kodo 8 年 前
kodo - Gogs: Go Git Service

No Description

0001_initial.py 1.9KB

    # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db import models, migrations import shortuuidfield.fields class Migration(migrations.Migration): dependencies = [ ] operations = [ migrations.CreateModel( name='LensmanInfo', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')), ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)), ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)), ('lensman_id', shortuuidfield.fields.ShortUUIDField(help_text='\u6444\u5f71\u5e08\u552f\u4e00\u6807\u8bc6', max_length=22, editable=False, db_index=True, blank=True)), ('name', models.CharField(help_text='\u6444\u5f71\u5e08\u59d3\u540d', max_length=255, null=True, verbose_name='name', blank=True)), ('sex', models.IntegerField(default=0, help_text='\u6444\u5f71\u5e08\u6027\u522b', verbose_name='sex', choices=[(0, '\u7537'), (1, '\u5973')])), ('phone', models.CharField(null=True, max_length=255, blank=True, help_text='\u6444\u5f71\u5e08\u7535\u8bdd', unique=True, verbose_name='phone', db_index=True)), ('location', models.CharField(help_text='\u6444\u5f71\u5e08\u5730\u5740', max_length=255, null=True, verbose_name='location', blank=True)), ('proportion', models.FloatField(default=1.0, help_text='\u6444\u5f71\u5e08\u5206\u6210\u6bd4\u4f8b\uff080.0 \uff5e 1.0\uff09', verbose_name='proportion')), ], options={ 'verbose_name': 'lensmaninfo', 'verbose_name_plural': 'lensmaninfo', }, ), ]
kodo - Gogs: Go Git Service

Brak opisu

0024_latestappscreeninfo.py 2.4KB

    # -*- coding: utf-8 -*- # Generated by Django 1.11.15 on 2018-09-02 18:08 from __future__ import unicode_literals from django.db import migrations, models import django_models_ext.fileext class Migration(migrations.Migration): dependencies = [ ('mch', '0023_auto_20180826_0448'), ] operations = [ migrations.CreateModel( name='LatestAppScreenInfo', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('status', models.BooleanField(db_index=True, default=True, help_text='Status', verbose_name='status')), ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')), ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')), ('latest_adr_version_code', models.IntegerField(default=0, help_text='\u6700\u65b0\u5b89\u5353\u7248\u672c\u53f7', verbose_name='latest_adr_version_code')), ('latest_adr_version_name', models.CharField(blank=True, help_text='\u6700\u65b0\u5b89\u5353\u7248\u672c\u540d', max_length=16, null=True, verbose_name='latest_adr_version_name')), ('latest_adr_app', models.FileField(blank=True, help_text='\u6700\u65b0\u7248\u5b89\u5353 APP', null=True, upload_to=django_models_ext.fileext.upload_path, verbose_name='latest_adr_app')), ('latest_adr_url', models.URLField(blank=True, help_text='\u6700\u65b0\u7248 APP \u94fe\u63a5', max_length=255, null=True, verbose_name='latest_adr_url')), ('latest_ios_version_code', models.IntegerField(default=0, help_text='\u6700\u65b0 iOS \u7248\u672c\u53f7', verbose_name='latest_ios_version_code')), ('latest_ios_version_name', models.CharField(blank=True, help_text='\u6700\u65b0 iOS \u7248\u672c\u540d', max_length=16, null=True, verbose_name='latest_ios_version_name')), ('latest_ios_url', models.URLField(blank=True, help_text='\u6700\u65b0\u7248 iOS \u94fe\u63a5', max_length=255, null=True, verbose_name='latest_ios_url')), ], options={ 'verbose_name': '\u5347\u7ea7\u914d\u7f6e\u4fe1\u606f(\u6570\u636e\u5927\u5c4f)', 'verbose_name_plural': '\u5347\u7ea7\u914d\u7f6e\u4fe1\u606f(\u6570\u636e\u5927\u5c4f)', }, ), ]