// // OrderDialogViews.swift // suixinkan // // Created by Codex on 2026/6/29. // import SwiftUI /// 普通订单退款弹窗,对齐 Android OrderRefundDialog。 struct OrderRefundDialogView: View { @ObservedObject var viewModel: OrderRefundViewModel let order: OrderEntity let onDismiss: () -> Void let onSuccess: () -> Void @Environment(\.ordersAPI) private var ordersAPI var body: some View { NavigationStack { Form { Section("订单号") { Text(order.orderNumber) } Section("退款方式") { Picker("退款方式", selection: $viewModel.mode) { ForEach(OrderRefundMode.allCases) { mode in Text(mode.title).tag(mode) } } .pickerStyle(.segmented) if viewModel.mode == .partial { TextField("退款金额", text: $viewModel.amount) .keyboardType(.decimalPad) } else { Text("可退金额:¥\(viewModel.availableAmountText(for: order))") .foregroundStyle(AppDesign.textSecondary) } } Section("退款原因") { TextField("请输入退款原因", text: $viewModel.reason, axis: .vertical) .lineLimit(3...6) } if let errorMessage = viewModel.errorMessage { Section { Text(errorMessage) .foregroundStyle(.red) } } } .navigationTitle("订单退款") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("取消", action: onDismiss) } ToolbarItem(placement: .confirmationAction) { Button(viewModel.submitting ? "提交中" : "确认") { Task { let success = await viewModel.submit(api: ordersAPI, item: order) if success { onSuccess() } } } .disabled(viewModel.submitting) } } } } } /// 赠送修图/视频弹窗,对齐 Android SendGiftDialog。 struct SendGiftDialogView: View { @State private var photoNum: Int @State private var videoNum: Int let context: OrdersViewModel.SendGiftContext let onDismiss: () -> Void let onConfirm: (Int, Int) -> Void init(context: OrdersViewModel.SendGiftContext, onDismiss: @escaping () -> Void, onConfirm: @escaping (Int, Int) -> Void) { self.context = context self.onDismiss = onDismiss self.onConfirm = onConfirm _photoNum = State(initialValue: context.sendPhotoNum) _videoNum = State(initialValue: context.sendVideoNum) } var body: some View { NavigationStack { Form { Section { stepperRow( title: "修图张数(已有\(context.nowPhotoNum)张,最多赠20张)", value: $photoNum, range: 0...20 ) stepperRow( title: "视频剪辑(已有\(context.nowVideoNum)条,最多赠5条)", value: $videoNum, range: 0...5 ) } } .navigationTitle("赠送修图/视频") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("取消", action: onDismiss) } ToolbarItem(placement: .confirmationAction) { Button("确认") { onConfirm(photoNum, videoNum) } } } } } private func stepperRow(title: String, value: Binding, range: ClosedRange) -> some View { HStack { Text(title) .font(.system(size: 13)) .foregroundStyle(AppDesign.orderLabelColor) Spacer() Button("-") { value.wrappedValue = max(range.lowerBound, value.wrappedValue - 1) } .buttonStyle(.plain) Text("\(value.wrappedValue)") .frame(minWidth: 30) Button("+") { value.wrappedValue = min(range.upperBound, value.wrappedValue + 1) } .buttonStyle(.plain) } } } /// 店长订单退款弹窗,支持全额/部分退款。 struct StoreOrderRefundDialogView: View { let orderNumber: String let actualPayAmount: String let initialMode: OrderRefundMode let onDismiss: () -> Void let onConfirm: (OrderRefundMode, String, String) -> Void @State private var mode: OrderRefundMode @State private var amount = "" @State private var reason = "" init( orderNumber: String, actualPayAmount: String, initialMode: OrderRefundMode, onDismiss: @escaping () -> Void, onConfirm: @escaping (OrderRefundMode, String, String) -> Void ) { self.orderNumber = orderNumber self.actualPayAmount = actualPayAmount self.initialMode = initialMode self.onDismiss = onDismiss self.onConfirm = onConfirm _mode = State(initialValue: initialMode) _amount = State(initialValue: actualPayAmount) } var body: some View { NavigationStack { Form { Section("订单号") { Text(orderNumber) } Section("退款方式") { Picker("退款方式", selection: $mode) { ForEach(OrderRefundMode.allCases) { item in Text(item.title).tag(item) } } .pickerStyle(.segmented) if mode == .partial { TextField("退款金额", text: $amount) .keyboardType(.decimalPad) } } Section("退款原因") { TextField("请输入退款原因", text: $reason, axis: .vertical) .lineLimit(3...6) } } .navigationTitle("申请退款") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("取消", action: onDismiss) } ToolbarItem(placement: .confirmationAction) { Button("提交") { let refundAmount = mode == .full ? actualPayAmount : amount onConfirm(mode, refundAmount, reason) } .disabled(reason.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) } } } } }