253 lines
10 KiB
Swift
253 lines
10 KiB
Swift
//
|
||
// OrderDetailViewControllers.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import SnapKit
|
||
import UIKit
|
||
|
||
/// 门店订单详情页,展示订单接口补全后的支付、客户、项目和拍摄点信息。
|
||
final class StoreOrderDetailViewController: UIViewController {
|
||
|
||
private let item: OrderEntity
|
||
private let viewModel: OrderDetailViewModel
|
||
private let refundViewModel = OrderRefundViewModel()
|
||
|
||
private lazy var tableView: UITableView = {
|
||
let table = UITableView(frame: .zero, style: .insetGrouped)
|
||
table.dataSource = self
|
||
table.delegate = self
|
||
table.backgroundColor = AppDesignUIKit.pageBackground
|
||
return table
|
||
}()
|
||
|
||
init(item: OrderEntity) {
|
||
self.item = item
|
||
self.viewModel = OrderDetailViewModel(item: item)
|
||
super.init(nibName: nil, bundle: nil)
|
||
}
|
||
|
||
@available(*, unavailable)
|
||
required init?(coder: NSCoder) { fatalError() }
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
title = "订单详情"
|
||
view.backgroundColor = AppDesignUIKit.pageBackground
|
||
view.addSubview(tableView)
|
||
tableView.snp.makeConstraints { make in make.edges.equalToSuperview() }
|
||
|
||
viewModel.onChange = { [weak self] in self?.tableView.reloadData() }
|
||
Task { await loadDetail() }
|
||
}
|
||
|
||
private func loadDetail() async {
|
||
await appServices.globalLoading.withLoading(message: "加载详情中...") {
|
||
await viewModel.load(api: appServices.ordersAPI, fallbackStoreId: appServices.accountContext.currentStore?.id)
|
||
}
|
||
if let error = viewModel.errorMessage {
|
||
showToast(error)
|
||
}
|
||
}
|
||
|
||
private func copyOrderNumber() {
|
||
UIPasteboard.general.string = viewModel.display.orderNumber
|
||
showToast("订单号已复制")
|
||
}
|
||
|
||
private func presentRefund() {
|
||
refundViewModel.begin(item: item)
|
||
let alert = UIAlertController(title: "订单退款", message: "可退 ¥\(refundViewModel.availableAmountText(for: item))", preferredStyle: .alert)
|
||
alert.addTextField { $0.placeholder = "退款原因" }
|
||
alert.addAction(UIAlertAction(title: "取消", style: .cancel))
|
||
alert.addAction(UIAlertAction(title: "提交", style: .default) { [weak self] _ in
|
||
guard let self else { return }
|
||
self.refundViewModel.reason = alert.textFields?.first?.text ?? ""
|
||
Task {
|
||
let success = await self.refundViewModel.submit(api: self.appServices.ordersAPI, item: self.item)
|
||
if success {
|
||
self.showToast("退款申请已提交")
|
||
await self.viewModel.load(api: self.appServices.ordersAPI, fallbackStoreId: self.appServices.accountContext.currentStore?.id, forceReload: true)
|
||
} else if let message = self.refundViewModel.errorMessage {
|
||
self.showToast(message)
|
||
}
|
||
}
|
||
})
|
||
present(alert, animated: true)
|
||
}
|
||
}
|
||
|
||
extension StoreOrderDetailViewController: UITableViewDataSource, UITableViewDelegate {
|
||
func numberOfSections(in tableView: UITableView) -> Int { 6 }
|
||
|
||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||
switch section {
|
||
case 0: return viewModel.contextMessage == nil ? 0 : 1
|
||
case 1: return 7
|
||
case 2: return 4
|
||
case 3: return 4
|
||
case 4: return viewModel.shootingList.count
|
||
case 5: return 5
|
||
default: return 0
|
||
}
|
||
}
|
||
|
||
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||
switch section {
|
||
case 1: "订单信息"
|
||
case 2: "支付信息"
|
||
case 3: "客户与项目"
|
||
case 4 where !viewModel.shootingList.isEmpty: "拍摄点"
|
||
case 5: "后续功能"
|
||
default: nil
|
||
}
|
||
}
|
||
|
||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||
let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
|
||
cell.selectionStyle = .none
|
||
let display = viewModel.display
|
||
|
||
switch indexPath.section {
|
||
case 0:
|
||
cell.textLabel?.text = viewModel.contextMessage
|
||
cell.textLabel?.numberOfLines = 0
|
||
case 1:
|
||
let rows = ["订单号", "状态", "类型", "创建时间", "付款时间", "完成时间", "复制订单号"]
|
||
cell.textLabel?.text = rows[indexPath.row]
|
||
switch indexPath.row {
|
||
case 0: cell.detailTextLabel?.text = display.orderNumber
|
||
case 1: cell.detailTextLabel?.text = display.orderStatusName
|
||
case 2: cell.detailTextLabel?.text = display.orderTypeLabel
|
||
case 3: cell.detailTextLabel?.text = display.createdAt
|
||
case 4: cell.detailTextLabel?.text = displayPayTime
|
||
case 5: cell.detailTextLabel?.text = display.completeTime
|
||
default:
|
||
cell.textLabel?.textColor = AppDesignUIKit.primary
|
||
cell.selectionStyle = .default
|
||
}
|
||
case 2:
|
||
let rows = ["付款金额", "退款金额", "付款方式", "用户 UID"]
|
||
cell.textLabel?.text = rows[indexPath.row]
|
||
switch indexPath.row {
|
||
case 0: cell.detailTextLabel?.text = "¥\(emptyToZero(display.actualPayAmount))"
|
||
case 1: cell.detailTextLabel?.text = "¥\(emptyToZero(display.actualRefundAmount))"
|
||
case 2: cell.detailTextLabel?.text = display.payTypeName
|
||
default: cell.detailTextLabel?.text = "\(display.userId)"
|
||
}
|
||
case 3:
|
||
let rows = ["手机号", "关联项目", "项目 ID", "备注"]
|
||
cell.textLabel?.text = rows[indexPath.row]
|
||
switch indexPath.row {
|
||
case 0: cell.detailTextLabel?.text = display.phone
|
||
case 1: cell.detailTextLabel?.text = display.projectName
|
||
case 2: cell.detailTextLabel?.text = "\(display.projectId)"
|
||
default: cell.detailTextLabel?.text = display.remark
|
||
}
|
||
case 4:
|
||
let shooting = viewModel.shootingList[indexPath.row]
|
||
cell.textLabel?.text = shooting.scenicSpotName
|
||
cell.detailTextLabel?.text = shooting.staffName.isEmpty ? "状态 \(shooting.status)" : shooting.staffName
|
||
case 5:
|
||
let actions = ["历史拍摄", "任务上传", "视频预告", "尾片上传", "退款"]
|
||
cell.textLabel?.text = actions[indexPath.row]
|
||
cell.accessoryType = .disclosureIndicator
|
||
cell.selectionStyle = .default
|
||
if indexPath.row == 4, !refundViewModel.canRefund(item) {
|
||
cell.isUserInteractionEnabled = false
|
||
cell.textLabel?.textColor = AppDesignUIKit.textSecondary
|
||
}
|
||
default: break
|
||
}
|
||
return cell
|
||
}
|
||
|
||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||
tableView.deselectRow(at: indexPath, animated: true)
|
||
if indexPath.section == 1, indexPath.row == 6 { copyOrderNumber(); return }
|
||
guard indexPath.section == 5 else { return }
|
||
let orderNumber = viewModel.display.orderNumber
|
||
switch indexPath.row {
|
||
case 0:
|
||
HomeMenuRouting.pushOrders(.historicalShooting(orderNumber: orderNumber), from: self)
|
||
case 1 where item.orderType == 19:
|
||
HomeMenuRouting.pushOrders(.multiTravelTaskUpload(orderNumber: orderNumber), from: self)
|
||
case 2:
|
||
HomeMenuRouting.pushOrders(.orderTrailer(orderNumber: orderNumber, title: "视频预告"), from: self)
|
||
case 3:
|
||
HomeMenuRouting.pushOrders(.orderTrailer(orderNumber: orderNumber, title: "尾片上传"), from: self)
|
||
case 4:
|
||
presentRefund()
|
||
default: break
|
||
}
|
||
}
|
||
|
||
private var displayPayTime: String {
|
||
let payTime = viewModel.display.payTime
|
||
if payTime.isEmpty || payTime == "0" || payTime.hasPrefix("1970") { return item.depositPayTime }
|
||
return payTime
|
||
}
|
||
|
||
private func emptyToZero(_ value: String) -> String {
|
||
value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? "0" : value
|
||
}
|
||
}
|
||
|
||
/// 核销订单详情页,展示核销列表项摘要信息。
|
||
final class WriteOffOrderDetailViewController: UIViewController {
|
||
|
||
private let item: WriteOffOrderItem
|
||
|
||
private lazy var tableView: UITableView = {
|
||
let table = UITableView(frame: .zero, style: .insetGrouped)
|
||
table.dataSource = self
|
||
table.backgroundColor = AppDesignUIKit.pageBackground
|
||
return table
|
||
}()
|
||
|
||
init(item: WriteOffOrderItem) {
|
||
self.item = item
|
||
super.init(nibName: nil, bundle: nil)
|
||
}
|
||
|
||
@available(*, unavailable)
|
||
required init?(coder: NSCoder) { fatalError() }
|
||
|
||
override func viewDidLoad() {
|
||
super.viewDidLoad()
|
||
title = "核销详情"
|
||
view.addSubview(tableView)
|
||
tableView.snp.makeConstraints { make in make.edges.equalToSuperview() }
|
||
}
|
||
}
|
||
|
||
extension WriteOffOrderDetailViewController: UITableViewDataSource {
|
||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 6 }
|
||
|
||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||
let cell = UITableViewCell(style: .value1, reuseIdentifier: nil)
|
||
cell.selectionStyle = .none
|
||
switch indexPath.row {
|
||
case 0:
|
||
cell.textLabel?.text = "订单号"
|
||
cell.detailTextLabel?.text = item.orderNumber
|
||
case 1:
|
||
cell.textLabel?.text = "项目"
|
||
cell.detailTextLabel?.text = item.projectName
|
||
case 2:
|
||
cell.textLabel?.text = "手机号"
|
||
cell.detailTextLabel?.text = item.userPhone
|
||
case 3:
|
||
cell.textLabel?.text = "金额"
|
||
cell.detailTextLabel?.text = "¥\(item.orderAmount)"
|
||
case 4:
|
||
cell.textLabel?.text = "状态"
|
||
cell.detailTextLabel?.text = item.orderStatusName
|
||
default:
|
||
cell.textLabel?.text = "核销时间"
|
||
cell.detailTextLabel?.text = item.orderVerificationTime
|
||
}
|
||
return cell
|
||
}
|
||
}
|