| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- //
- // LNOrderListItemCell.swift
- // Lanu
- //
- // Created by OneeChan on 2025/11/18.
- //
- import Foundation
- import UIKit
- import SnapKit
- class LNOrderListItemCell: UITableViewCell {
- private let dateLabel = UILabel()
- private let stateLabel = UILabel()
-
- private let avatar = UIImageView()
- private let userNameLabel = UILabel()
- private let gameLabel = UILabel()
-
- private let priceLabel = UILabel()
- private let countLabel = UILabel()
-
- private let operationButton = UIButton()
- private let descLabel = UILabel()
- private let discountView = UIView()
- private let totalLabel = UILabel()
- private var curItem: LNOrderListItemVO?
-
- override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
- super.init(style: style, reuseIdentifier: reuseIdentifier)
-
- setupViews()
- }
-
- func update(_ item: LNOrderListItemVO) {
- avatar.showAvatar(item.avatar)
- dateLabel.text = TimeInterval(item.createTime / 1_000).formattedFullDate()
- userNameLabel.text = item.nickname
- gameLabel.text = item.bizCategoryName
-
- priceLabel.text = "\(item.price.toDisplay)"
- countLabel.text = "\(item.unit) x \(item.purchaseQty)"
-
- totalLabel.text = item.totalAmount.toDisplay
- discountView.isHidden = item.totalAmount >= item.price * Double(item.purchaseQty)
-
- curItem = item
-
- updateByStateChanged()
- }
-
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- }
- extension LNOrderListItemCell {
- @objc
- private func handleOperationButtonClick() {
- guard let orderItem = curItem else { return }
- switch orderItem.status {
- case .created, .waitingForAccept: // 可以取消
- LNCommonAlertView.showCancelOrderAlert(orderId: orderItem.orderId) { success in
- guard success else { return }
- orderItem.status = .cancelled
- }
- break
- case .completed: // 可以评价
- let panel = LNOrderCommentPanel()
- panel.update(orderItem.avatar, orderId: orderItem.orderId)
- panel.handler = { star, comment in
- orderItem.star = star
- }
- panel.popup()
- break
- case .serviceDone: // 可以点击完成
- LNCommonAlertView.showFinishOrderAlert(orderId: orderItem.orderId) { success in
- guard success else { return }
- orderItem.status = .completed
- }
- break
- case .refunded, .accepted, .rejected, .cancelled, .servicing:
- // 无操作选项
- break
- }
- }
- }
- extension LNOrderListItemCell {
- private func updateByStateChanged() {
- guard let curItem else { return }
-
- if curItem.refundApply {
- stateLabel.text = .init(key: "A00049")
- stateLabel.textColor = .init(hex: "#FFB836")
-
- operationButton.isHidden = true
- descLabel.isHidden = false
- descLabel.text = .init(key: "A00148")
- return
- }
-
- operationButton.isHidden = true
- operationButton.setBackgroundImage(nil, for: .normal)
- descLabel.isHidden = true
-
- switch curItem.status {
- case .created, .waitingForAccept:
- stateLabel.text = .init(key: "A00055")
- stateLabel.textColor = .init(hex: "#FFB836")
-
- operationButton.isHidden = false
- operationButton.layer.borderColor = UIColor.fill_3.cgColor
- operationButton.setTitleColor(.text_3, for: .normal)
- operationButton.setTitle(.init(key: "A00003"), for: .normal)
- case .completed:
- stateLabel.text = .init(key: "A00137")
- stateLabel.textColor = .text_6
-
- if curItem.star == 0 {
- operationButton.isHidden = false
- operationButton.layer.borderColor = UIColor.text_6.cgColor
- operationButton.setTitleColor(.text_6, for: .normal)
- operationButton.setTitle(.init(key: "A00149"), for: .normal)
- }
- case .refunded:
- stateLabel.text = .init(key: "A00138")
- stateLabel.textColor = .text_3
-
- operationButton.isHidden = true
- descLabel.isHidden = false
- descLabel.text = .init(key: "A00150")
- case .accepted:
- stateLabel.text = .init(key: "A00139")
- stateLabel.textColor = .text_6
- case .rejected:
- stateLabel.text = .init(key: "A00140")
- stateLabel.textColor = .text_6
- case .servicing:
- stateLabel.text = .init(key: "A00141")
- stateLabel.textColor = .init(hex: "#FFB836")
- case .serviceDone:
- stateLabel.text = .init(key: "A00141")
- stateLabel.textColor = .init(hex: "#FFB836")
-
- operationButton.isHidden = false
- operationButton.layer.borderColor = UIColor.clear.cgColor
- operationButton.setTitleColor(.text_1, for: .normal)
- operationButton.setTitle(.init(key: "A00151"), for: .normal)
- operationButton.setBackgroundImage(.primary_8, for: .normal)
- case .cancelled:
- stateLabel.text = .init(key: "A00152")
- stateLabel.textColor = .text_3
- }
- }
-
- private func setupViews() {
- backgroundColor = .clear
- onTap { [weak self] in
- guard let self else { return }
- guard let curItem else { return }
- pushToOrderDetail(orderId: curItem.orderId)
- }
-
- let container = UIView()
- container.backgroundColor = .fill
- container.layer.cornerRadius = 12
- contentView.addSubview(container)
- container.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(16)
- make.top.equalToSuperview().offset(6)
- make.bottom.equalToSuperview().offset(-6)
- }
-
- let top = buildTopView()
- container.addSubview(top)
- top.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalToSuperview().offset(5)
- }
-
- let line = UIView()
- line.backgroundColor = .fill_2
- container.addSubview(line)
- line.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(11)
- make.top.equalTo(top.snp.bottom)
- make.height.equalTo(0.5)
- }
-
- let mid = buildMidView()
- container.addSubview(mid)
- mid.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalTo(top.snp.bottom).offset(3)
- }
-
- let bottom = buildBottomView()
- container.addSubview(bottom)
- bottom.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalTo(mid.snp.bottom).offset(3)
- make.bottom.equalToSuperview().offset(-5)
- }
- }
-
- private func buildTopView() -> UIView {
- let container = UIView()
- container.snp.makeConstraints { make in
- make.height.equalTo(30)
- }
-
- stateLabel.font = .heading_h5
- container.addSubview(stateLabel)
- stateLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview().offset(-12)
- make.width.height.equalTo(0).priority(.low)
- }
-
- dateLabel.font = .body_xs
- dateLabel.textColor = .text_3
- container.addSubview(dateLabel)
- dateLabel.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(12)
- make.centerY.equalToSuperview()
- make.trailing.lessThanOrEqualTo(stateLabel.snp.leading).offset(-5)
- }
-
- return container
- }
-
- private func buildMidView() -> UIView {
- let container = UIView()
-
- let price = buildPriceView()
- container.addSubview(price)
- price.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview().offset(-12)
- }
-
- let infoView = buildUserInfoView()
- container.addSubview(infoView)
- infoView.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(12)
- make.verticalEdges.equalToSuperview().inset(4)
- make.trailing.lessThanOrEqualTo(price.snp.leading).offset(-12)
- }
-
- return container
- }
-
- private func buildBottomView() -> UIView {
- let container = UIView()
- container.snp.makeConstraints { make in
- make.height.equalTo(38)
- }
-
- totalLabel.font = .heading_h3
- totalLabel.textColor = .text_5
- container.addSubview(totalLabel)
- totalLabel.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalToSuperview().offset(-12)
- }
-
- let coin = UIImageView.coinImageView()
- container.addSubview(coin)
- coin.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalTo(totalLabel.snp.leading).offset(-2)
- make.width.height.equalTo(20)
- }
-
- let text = UILabel()
- text.font = .body_s
- text.textColor = .text_5
- text.text = .init(key: "A00124")
- container.addSubview(text)
- text.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalTo(coin.snp.leading)
- }
-
- let discount = buildDiscount()
- container.addSubview(discount)
- discount.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.trailing.equalTo(text.snp.leading).offset(-5)
- }
-
- operationButton.layer.cornerRadius = 15
- operationButton.layer.borderWidth = 1
- operationButton.clipsToBounds = true
- operationButton.titleLabel?.font = .heading_h5
- operationButton.addTarget(self, action: #selector(handleOperationButtonClick), for: .touchUpInside)
- container.addSubview(operationButton)
- operationButton.snp.makeConstraints { make in
- make.height.equalTo(30)
- make.centerY.equalToSuperview()
- make.leading.equalToSuperview().offset(12)
- make.width.equalTo(77)
- }
-
- descLabel.font = .body_xs
- descLabel.textColor = .text_3
- descLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
- descLabel.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
- container.addSubview(descLabel)
- descLabel.snp.makeConstraints { make in
- make.leading.equalToSuperview().offset(12)
- make.centerY.equalToSuperview()
- make.trailing.lessThanOrEqualTo(discount.snp.leading).offset(-16)
- }
-
- return container
- }
-
- private func buildUserInfoView() -> UIView {
- let container = UIView()
- container.onTap { [weak self] in
- guard let self else { return }
- guard let curItem else { return }
- pushToProfile(uid: curItem.sellerUserNo)
- }
-
- avatar.layer.cornerRadius = 20
- avatar.clipsToBounds = true
- container.addSubview(avatar)
- avatar.snp.makeConstraints { make in
- make.leading.verticalEdges.equalToSuperview()
- make.width.height.equalTo(40)
- }
-
-
- let textInfo = UIView()
- container.addSubview(textInfo)
- textInfo.snp.makeConstraints { make in
- make.centerY.equalToSuperview()
- make.leading.equalTo(avatar.snp.trailing).offset(8)
- make.trailing.equalToSuperview()
- }
-
- userNameLabel.textColor = .text_5
- userNameLabel.font = .heading_h4
- textInfo.addSubview(userNameLabel)
- userNameLabel.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.top.equalToSuperview()
- }
-
- gameLabel.font = .body_m
- gameLabel.textColor = .text_5
- textInfo.addSubview(gameLabel)
- gameLabel.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.bottom.equalToSuperview()
- make.top.equalTo(userNameLabel.snp.bottom).offset(2)
- }
-
- return container
- }
-
- private func buildPriceView() -> UIView {
- let container = UIView()
-
- let coin = UIImageView.coinImageView()
- container.addSubview(coin)
- coin.snp.makeConstraints { make in
- make.top.equalToSuperview()
- make.leading.equalToSuperview()
- make.width.height.equalTo(16)
- }
-
- priceLabel.font = .body_s
- priceLabel.textColor = .text_5
- container.addSubview(priceLabel)
- priceLabel.snp.makeConstraints { make in
- make.trailing.equalToSuperview()
- make.leading.equalTo(coin.snp.trailing)
- make.centerY.equalTo(coin)
- }
-
- countLabel.font = .body_xs
- countLabel.textColor = .text_4
- countLabel.setContentHuggingPriority(.defaultHigh, for: .horizontal)
- countLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)
- container.addSubview(countLabel)
- countLabel.snp.makeConstraints { make in
- make.trailing.bottom.equalToSuperview()
- make.top.equalTo(coin.snp.bottom).offset(2)
- }
-
- return container
- }
-
- private func buildDiscount() -> UIView {
- discountView.layer.cornerRadius = 4
- discountView.backgroundColor = .init(hex: "#FF6F32")
-
- let titleLabel = UILabel()
- titleLabel.text = .init(key: "A00129")
- titleLabel.font = .body_xs
- titleLabel.textColor = .text_1
- discountView.addSubview(titleLabel)
- titleLabel.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview().inset(6)
- make.verticalEdges.equalToSuperview().inset(3)
- }
-
- return discountView
- }
- }
- #if DEBUG
- import SwiftUI
- struct LNOrderListItemCellPreview: UIViewRepresentable {
- func makeUIView(context: Context) -> some UIView {
- let container = UIView()
- container.backgroundColor = .lightGray
-
- let view = LNOrderListItemCell()
- container.addSubview(view)
- view.snp.makeConstraints { make in
- make.horizontalEdges.equalToSuperview()
- make.centerY.equalToSuperview()
- make.height.equalTo(133)
- }
-
- return container
- }
-
- func updateUIView(_ uiView: UIViewType, context: Context) { }
- }
- #Preview(body: {
- LNOrderListItemCellPreview()
- })
- #endif // DEBUG
|