| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- //
- // LNOrderManager.swift
- // Lanu
- //
- // Created by OneeChan on 2025/11/6.
- //
- import Foundation
- protocol LNOrderManagerNotify {
- func onOrderInfoChanged(orderId: String)
- func onMyDiscountInfoChanged(info: LNOrderDiscountVO?)
- }
- extension LNOrderManagerNotify {
- func onOrderInfoChanged(orderId: String) { }
- func onMyDiscountInfoChanged(info: LNOrderDiscountVO?) { }
- }
- enum LNOrderErrorCode: Int {
- case NotEnoughMoney = 100018
- }
- protocol LNOrderProtocol {
- var buyerUserNo: String { get }
- var refundApply: Bool { get }
- var status: LNOrderStatus { get }
- }
- extension LNOrderProtocol {
- var statusUI: (title: String, icon: UIImage) {
- let isCreator = buyerUserNo.isMyUid
-
- if refundApply {
- return if isCreator {
- (.init(key: "A00049"), .icImChatOrderPending)
- } else {
- (.init(key: "A00051"), .icImChatOrderRefunding)
- }
- }
-
- return switch status {
- case .created, .waitingForAccept:
- if isCreator {
- (.init(key: "A00053"), .icImChatOrderSuccess)
- } else {
- (.init(key: "A00055"), .icImChatOrderPending)
- }
- case .completed: (.init(key: "A00057"), .icImChatOrderComplete)
- case .refunded: (.init(key: "A00060"), .icImChatOrderRefunded)
- case .accepted: (.init(key: "A00062"), .icImChatOrderAccepted)
- case .rejected: (.init(key: "A00065"), .icImChatOrderCancel)
- case .servicing: (.init(key: "A00068"), .icImChatOrderProcessing)
- case .serviceDone: (.init(key: "A00070"), .icImChatOrderComplete)
- case .cancelled: (.init(key: "A00071"), .icImChatOrderCancel)
- }
- }
- }
- class LNOrderManager {
- static var shared = LNOrderManager()
- static let orderExtraMaxLength = 150
- static let orderProtestMaxLength = 500
- static let orderRefundMaxLength = 500
- static let orderCommentMaxLength = 200
-
- private var discount: LNOrderDiscountVO?
-
- func discountFor(_ price: Double) -> Double? {
- if let discount, discount.hasChance, discount.eligiblePrice == price {
- discount.discountRate
- } else {
- nil
- }
- }
-
- private init() {
- LNEventDeliver.addObserver(self)
- }
- }
- // MARK: 订单信息
- extension LNOrderManager {
- func getList(size: Int, next: String? = nil, queue: DispatchQueue = .main,
- handler: @escaping ([LNOrderListItemVO]?, String?) -> Void) {
- LNHttpManager.shared.getOrderList(size: size, next: next ?? "") { res, err in
- queue.asyncIfNotGlobal {
- handler(res?.list, res?.next)
- }
- }
- }
-
- func getOrderDetail(orderId: String, queue: DispatchQueue = .main,
- handler: @escaping (LNOrderDetailResponse?) -> Void) {
- LNHttpManager.shared.getOrderDetail(orderId: orderId) { res, err in
- queue.asyncIfNotGlobal {
- handler(res)
- }
- }
- }
-
- func getRecordList(size: Int, next: String? = nil, queue: DispatchQueue = .main,
- handler: @escaping ([LNOrderRecordItemVO]?, String) -> Void) {
- LNHttpManager.shared.getOrderRecordList(size: size, next: next ?? "") { res, err in
- guard err == nil, let res else {
- queue.asyncIfNotGlobal {
- handler(nil, "")
- }
- return
- }
- queue.asyncIfNotGlobal {
- handler(res.list, res.next)
- }
- }
- }
-
- func getUnfinishedOrderWith(uid: String, size: Int, next: String?,
- queue: DispatchQueue = .main,
- handler: @escaping ([LNUnfinishedOrderVO]?, String?) -> Void) {
- LNHttpManager.shared.getUnfinishedOrderWith(uid: uid, size: size, next: next ?? "") { res, err in
- queue.asyncIfNotGlobal {
- handler(res?.list, res?.next)
- }
- }
- }
-
- func getLastOrder(queue: DispatchQueue = .main, handler: @escaping (LNLastOrderResponse?) -> Void) {
- LNHttpManager.shared.getLastOrder { res, err in
- queue.asyncIfNotGlobal {
- handler(res)
- }
- }
- }
- }
- // MARK: 订单操作
- extension LNOrderManager {
- func createOrder(skillId: String, count: Int,
- remark: String, scene: LNOrderScene = .normal,
- queue: DispatchQueue = .main,
- handler: @escaping (String?) -> Void)
- {
- LNHttpManager.shared.createOrderBySkill(skillId: skillId, count: count, remark: remark, scene: scene)
- { [weak self] res, err in
- guard let self else { return }
- if let res, err == nil {
- LNPurchaseManager.shared.reloadWalletInfo()
- notifyOrderInfoChanged(orderId: res.orderNo)
- reloadMyOrderDiscountInfo()
- }
- queue.asyncIfNotGlobal {
- handler(res?.orderNo)
- }
-
- if case .serverError(let code, let err) = err {
- DispatchQueue.main.async {
- if code == LNOrderErrorCode.NotEnoughMoney.rawValue {
- let panel = LNPurchasePanel()
- panel.update(.coin)
- panel.popup()
- showToast(err)
- } else {
- showToast(err)
- }
- }
- }
- }
- }
-
- func cancelOrder(orderId: String,
- queue: DispatchQueue = .main,
- handler: @escaping (Bool) -> Void) {
- LNHttpManager.shared.cancelOrder(orderId: orderId) { [weak self] err in
- guard let self else { return }
-
- queue.asyncIfNotGlobal { [weak self] in
- handler(err == nil)
-
- guard let self else { return }
- if err == nil {
- notifyOrderInfoChanged(orderId: orderId)
- reloadMyOrderDiscountInfo()
- LNPurchaseManager.shared.reloadWalletInfo()
- } else {
- showToast(err?.errorDesc)
- }
- }
- }
- }
-
- func finishOrder(orderId: String, queue: DispatchQueue = .main,
- handler: @escaping (Bool) -> Void) {
- LNHttpManager.shared.finishOrder(orderId: orderId) { [weak self] err in
- guard let self else { return }
- queue.asyncIfNotGlobal { [weak self] in
- handler(err == nil)
-
- guard let self else { return }
- if err == nil {
- notifyOrderInfoChanged(orderId: orderId)
- } else {
- showToast(err?.errorDesc)
- }
- }
- }
- }
-
- func refundOrder(orderId: String, reason: String,
- attachments: [String], queue: DispatchQueue = .main,
- handler: @escaping (Bool) -> Void) {
- LNHttpManager.shared.refundOrder(orderId: orderId, reason: reason, attachments: attachments)
- { [weak self] err in
- guard let self else { return }
- queue.asyncIfNotGlobal { [weak self] in
- handler(err == nil)
-
- guard let self else { return }
- if err == nil {
- notifyOrderInfoChanged(orderId: orderId)
- reloadMyOrderDiscountInfo()
- } else {
- showToast(err?.errorDesc)
- }
- }
- }
- }
-
- func commentOrder(orderId: String, star: Double, comment: String,
- queue: DispatchQueue = .main,
- handler: @escaping (Bool) -> Void) {
- LNHttpManager.shared.commentOrder(
- orderId: orderId, star: star, comment: comment)
- { [weak self] err in
- guard let self else { return }
- queue.asyncIfNotGlobal { [weak self] in
- handler(err == nil)
- guard let self else { return }
- if err == nil {
- notifyOrderInfoChanged(orderId: orderId)
- } else {
- showToast(err?.errorDesc)
- }
- }
- }
- }
-
- func rejectOrder(orderId: String, queue: DispatchQueue = .main,
- handler: @escaping (Bool) -> Void) {
- LNHttpManager.shared.rejectOrder(orderId: orderId) { [weak self] err in
- guard let self else { return }
- queue.asyncIfNotGlobal { [weak self] in
- handler(err == nil)
-
- guard let self else { return }
- if err == nil {
- notifyOrderInfoChanged(orderId: orderId)
- } else {
- showToast(err?.errorDesc)
- }
- }
- }
- }
-
- func acceptOrder(orderId: String, queue: DispatchQueue = .main,
- handler: @escaping (Bool) -> Void) {
- LNHttpManager.shared.acceptOrder(orderId: orderId) { [weak self] err in
- guard let self else { return }
- queue.asyncIfNotGlobal { [weak self] in
- handler(err == nil)
- guard let self else { return }
- if err == nil {
- notifyOrderInfoChanged(orderId: orderId)
- } else {
- showToast(err?.errorDesc)
- }
- }
- }
- }
-
- func startOrderService(orderId: String, queue: DispatchQueue = .main,
- handler: @escaping (Bool) -> Void) {
- LNHttpManager.shared.startOrderService(orderId: orderId) { [weak self] err in
- guard let self else { return }
- queue.asyncIfNotGlobal { [weak self] in
- handler(err == nil)
- guard let self else { return }
- if err == nil {
- notifyOrderInfoChanged(orderId: orderId)
- } else {
- showToast(err?.errorDesc)
- }
- }
- }
- }
-
- func finishOrderService(orderId: String, queue: DispatchQueue = .main,
- handler: @escaping (Bool) -> Void) {
- LNHttpManager.shared.finishOrderService(orderId: orderId) { [weak self] err in
- guard let self else { return }
- queue.asyncIfNotGlobal { [weak self] in
- handler(err == nil)
- guard let self else { return }
- if err == nil {
- notifyOrderInfoChanged(orderId: orderId)
- } else {
- showToast(err?.errorDesc)
- }
- }
- }
- }
-
- func protestOrder(orderId: String, reason: String,
- queue: DispatchQueue = .main,
- attachments: [String], handler: @escaping (Bool) -> Void)
- {
- LNHttpManager.shared.protestOrder(orderId: orderId, reason: reason, attachments: attachments)
- { [weak self] err in
- guard let self else { return }
- queue.asyncIfNotGlobal { [weak self] in
- handler(err == nil)
-
- guard let self else { return }
- if err == nil {
- notifyOrderInfoChanged(orderId: orderId)
- } else {
- showToast(err?.errorDesc)
- }
- }
- }
- }
- }
- // MARK: 二维码
- extension LNOrderManager {
- func createOrderQR(skillId: String,
- count: Int, type: LNOrderSource,
- queue: DispatchQueue = .main,
- handler: @escaping (String?) -> Void) {
- LNHttpManager.shared.createOrderQR(skillId: skillId, count: count, type: type) { [weak self] data, err in
- queue.asyncIfNotGlobal {
- handler(data?.qrCode)
- }
- if let err {
- showToast(err.errorDesc)
- } else if let self {
- reloadMyOrderDiscountInfo()
- }
- }
- }
-
- func getQRDetail(data: String,
- queue: DispatchQueue = .main,
- handler: @escaping (LNQRCodeDetailResponse?) -> Void) {
- LNHttpManager.shared.getQRDetail(data: data) { res, err in
- queue.asyncIfNotGlobal {
- handler(res)
- }
-
- if let err {
- showToast(err.errorDesc)
- }
- }
- }
-
- func createQRCodeOrder(data: String, count: Int,
- extra: String, scene: LNOrderScene = .normal,
- queue: DispatchQueue = .main,
- handler: @escaping (String?) -> Void) {
- LNHttpManager.shared.createQROrder(data: data, count: count, extra: extra, scene: scene) { [weak self] res, err in
- queue.asyncIfNotGlobal {
- handler(res?.orderNo)
- }
-
- if let err {
- showToast(err.errorDesc)
- } else if let self {
- LNPurchaseManager.shared.reloadWalletInfo()
- reloadMyOrderDiscountInfo()
- }
- }
- }
- }
- // MARK: 折扣
- extension LNOrderManager {
- func reloadMyOrderDiscountInfo() {
- LNHttpManager.shared.fetchOrderDiscount { [weak self] info, err in
- guard let self else { return }
- if err != nil { return }
- discount = info
- notifyDiscountInfoChange(info: info)
- }
- }
- }
- extension LNOrderManager: LNAccountManagerNotify {
- func onUserLogin() {
- reloadMyOrderDiscountInfo()
- }
- }
- extension LNOrderManager {
- private func notifyOrderInfoChanged(orderId: String) {
- LNEventDeliver.notifyEvent {
- ($0 as? LNOrderManagerNotify)?.onOrderInfoChanged(orderId: orderId)
- }
- }
-
- private func notifyDiscountInfoChange(info: LNOrderDiscountVO?) {
- LNEventDeliver.notifyEvent {
- ($0 as? LNOrderManagerNotify)?.onMyDiscountInfoChanged(info: info)
- }
- }
- }
|