238 lines
9.9 KiB
Swift
238 lines
9.9 KiB
Swift
//
|
||
// 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)")
|
||
}
|
||
}
|