新增门店订单与核销管理列表,对齐 Android 订单能力并完善账号级缓存。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
237
suixinkan/Features/Orders/Views/OrderListCardView.swift
Normal file
237
suixinkan/Features/Orders/Views/OrderListCardView.swift
Normal file
@ -0,0 +1,237 @@
|
||||
//
|
||||
// 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)")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user