Files
suixinkan_ios_new/suixinkan/Features/Orders/Views/OrderListCardView.swift

238 lines
9.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// OrderListCardView.swift
// suixinkan
//
// Created by Codex on 2026/6/29.
//
import SwiftUI
/// Android OrderView
struct OrderListCardView: View {
let item: OrderEntity
let hideOrderWriteActions: Bool
let showOrderSource: Bool
let sourceSelection: OrderSourceSelection?
let orderSourcePeople: [OrderSourcePerson]
let leadsForPerson: (OrderSourcePerson) -> [OrderSourceLead]
let leadsLoading: Bool
let onRefund: () -> Void
let onVerify: () -> Void
let onUploadTask: () -> Void
let onRefinedChange: (Int) -> Void
let onSendGift: () -> Void
let onCancelOrder: () -> Void
let onHistoricalPhoto: () -> Void
let onCallPhone: () -> Void
let onOrderSourceSheetOpen: () -> Void
let onOrderSourcePersonClick: (OrderSourcePerson) -> Void
let onOrderSourceSelectionChange: (OrderSourceSelection) -> Void
let callSourcePhone: (String) -> Void
private var showRefundButton: Bool {
!hideOrderWriteActions &&
(item.orderStatus == 18 || item.orderStatus == 30) &&
item.orderType != 19
}
private var showVerifyButton: Bool {
!hideOrderWriteActions && (
(item.photoTravel?.needCheckIn == true && item.orderStatus != 30) ||
item.orderType == 19
)
}
var body: some View {
VStack(alignment: .leading, spacing: 0) {
HStack(alignment: .center) {
Text("订单号:\(item.orderNumber)")
.font(.system(size: 14))
.foregroundStyle(.black)
.lineLimit(1)
.minimumScaleFactor(0.72)
Spacer()
OrderStatusChip(text: item.orderStatusName, status: item.orderStatus)
}
Text(item.createdAt.isEmpty ? "--" : item.createdAt)
.font(.system(size: 12))
.foregroundStyle(AppDesign.textSecondary)
.padding(.top, 4)
if !item.orderTypeLabel.isEmpty {
Text(item.orderTypeLabel)
.font(.system(size: 12))
.foregroundStyle(AppDesign.primary)
.padding(.horizontal, 4)
.padding(.vertical, 2)
.background(AppDesign.primarySoft, in: RoundedRectangle(cornerRadius: 4))
.padding(.top, 4)
}
if showOrderSource {
OrderSourcePicker(
selection: sourceSelection,
people: orderSourcePeople,
leadsForPerson: leadsForPerson,
leadsLoading: leadsLoading,
onSheetOpen: onOrderSourceSheetOpen,
onPersonClick: onOrderSourcePersonClick,
onSelectionChange: onOrderSourceSelectionChange,
callPhone: callSourcePhone
)
.padding(.top, 10)
}
if showRefundButton || showVerifyButton {
HStack(spacing: 12) {
if showRefundButton {
OrderActionButton(
title: "退款",
textColor: AppDesign.orderRefundText,
backgroundColor: AppDesign.orderRefundBackground,
maxWidth: showVerifyButton ? nil : .infinity,
action: onRefund
)
.frame(maxWidth: showVerifyButton ? .infinity : nil)
}
if showVerifyButton {
OrderActionButton(title: "核销订单", action: onVerify)
}
}
.padding(.top, 12)
}
if !hideOrderWriteActions && item.orderType == 19 {
Button(action: onUploadTask) {
Text("上传任务")
.font(.system(size: 16))
.foregroundStyle(AppDesign.primary)
.frame(maxWidth: .infinity)
.frame(height: 48)
.background(AppDesign.primarySoft, in: RoundedRectangle(cornerRadius: 12))
}
.buttonStyle(.plain)
.padding(.top, 12)
}
if item.orderStatus == 18 || item.orderStatus == 30 {
OrderRefinedChoiceSection(
currentSelection: item.isRefined,
readOnly: hideOrderWriteActions,
onSelectionChange: onRefinedChange
)
.padding(.top, 12)
}
if item.orderStatus == 50,
!item.actualRefundAmount.isEmpty,
item.actualRefundAmount != "0" {
OrderInfoRow(title: "退款金额", value: "¥\(item.actualRefundAmount)", valueColor: AppDesign.primary)
.padding(.top, 8)
}
VStack(spacing: 8) {
OrderInfoRow(title: "付款金额", value: "¥\(item.actualPayAmount)", valueColor: AppDesign.primary)
OrderInfoRow(
title: "付款时间",
value: OrderListUI.displayPayTime(payTime: item.payTime, depositPayTime: item.depositPayTime)
)
OrderInfoRow(title: "完成时间", value: item.completeTime.isEmpty ? "--" : item.completeTime)
OrderInfoRow(title: "付款方式", value: item.payTypeName.isEmpty ? "--" : item.payTypeName)
OrderInfoRow(title: "用户 UID", value: "\(item.userId)")
OrderInfoRow(title: "手机号", value: OrderListUI.maskPhone(item.phone)) {
HStack(spacing: 7) {
Text(OrderListUI.maskPhone(item.phone))
.font(.system(size: 14, weight: .medium))
.foregroundStyle(.black)
if !hideOrderWriteActions {
OrderPhoneCallButton(action: onCallPhone)
}
}
}
OrderInfoRow(title: "关联项目", value: item.projectName.isEmpty ? "--" : item.projectName)
if let photoTravel = item.photoTravel, !photoTravel.checkInTime.isEmpty {
OrderInfoRow(title: "核销时间", value: photoTravel.checkInTime)
}
if let photoTravel = item.photoTravel,
item.orderType != 19,
item.orderType != 14 {
OrderGiftStepperRow(
title: "修图张数",
valueText: "\(photoTravel.orderPhotoNum + photoTravel.retouchGiftPhotoNum)",
editable: photoTravel.canGiftRetouch && !hideOrderWriteActions,
onTap: onSendGift
)
OrderGiftStepperRow(
title: "视频剪辑",
valueText: "\(photoTravel.orderVideoNum + photoTravel.retouchGiftVideoNum)",
editable: photoTravel.canGiftRetouch && !hideOrderWriteActions,
onTap: onSendGift
)
}
}
.padding(.top, 13)
if !item.remark.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
Divider().overlay(AppDesign.orderInputBackground).padding(.top, 14)
Text("备注信息:")
.font(.system(size: 14))
.foregroundStyle(AppDesign.orderLabelColor)
.padding(.top, 10)
Text(item.remark)
.font(.system(size: 14))
.foregroundStyle(AppDesign.orderLabelColor)
.padding(.top, 6)
}
if let materials = item.multiTravel?.materialList, !materials.isEmpty {
Divider().overlay(AppDesign.orderInputBackground).padding(.top, 12)
Text("历史拍摄信息:")
.font(.system(size: 14))
.foregroundStyle(AppDesign.orderLabelColor)
.padding(.top, 12)
Button(action: onHistoricalPhoto) {
HStack(spacing: 8) {
ForEach(Array(materials.prefix(3).enumerated()), id: \.offset) { index, material in
ZStack {
RemoteImage(
urlString: material.previewURLString,
contentMode: .fill
) {
Color(hex: 0xF4F4F4)
}
.aspectRatio(1.59, contentMode: .fill)
.clipShape(RoundedRectangle(cornerRadius: 8))
if materials.count > 3 && index == 2 {
RoundedRectangle(cornerRadius: 8)
.fill(Color.black.opacity(0.5))
Text("查看更多")
.font(.system(size: 14, weight: .medium))
.foregroundStyle(.white)
}
}
.frame(maxWidth: .infinity)
}
}
}
.buttonStyle(.plain)
.padding(.top, 8)
}
if item.photoTravel?.canCancelOrder == true && !hideOrderWriteActions {
OrderActionButton(title: "取消订单", action: onCancelOrder)
.padding(.top, 12)
}
}
.padding(16)
.frame(maxWidth: .infinity, alignment: .leading)
.background(.white, in: RoundedRectangle(cornerRadius: 12))
.accessibilityIdentifier("orders.store.card.\(item.orderNumber)")
}
}