import SwiftUI import CoreModel import CoreUI import DesignSystem public struct PlanSubmitScreen: View { private let viewModel: PlanSubmitViewModel private let type: PlanType private let periodKey: String @State private var content = "" @Environment(\.dismiss) private var dismiss public init(viewModel: PlanSubmitViewModel, type: PlanType, periodKey: String) { self.viewModel = viewModel self.type = type self.periodKey = periodKey } public var body: some View { contentView .navigationTitle("\(type.label) · \(periodKey)") .task { viewModel.load() } .onChange(of: viewModel.uiState) { _, newState in if case .success(let data) = newState, content.isEmpty, !data.content.isEmpty { content = data.content } } .onChange(of: viewModel.saved) { _, saved in if saved { dismiss() } } } @ViewBuilder private var contentView: some View { switch viewModel.uiState { case .loading: LoadingView() case .error(let message): ErrorView(message: message) { viewModel.load() } case .success(let data): submitContent(data) } } private func submitContent(_ data: PlanSubmitData) -> some View { ScrollView { VStack(spacing: DS.Spacing.md) { if !data.canSubmit, let message = data.message { Text(message) .font(.caption) .foregroundStyle(DS.Color.brandMuted) .frame(maxWidth: .infinity, alignment: .leading) } VStack(alignment: .trailing, spacing: DS.Spacing.xs) { TextEditor(text: $content) .frame(minHeight: 120) .scrollContentBackground(.hidden) .padding(DS.Spacing.sm) .background(data.canSubmit ? DS.Color.brandPaper : DS.Color.brandChip) .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) .overlay( RoundedRectangle(cornerRadius: 12, style: .continuous) .stroke(DS.Color.disabled, lineWidth: 1) ) Text("\(content.count)/1000") .font(.caption) .foregroundStyle(DS.Color.faintText) } HStack { Text("+ 添加图片(\(data.attachments.count)/4)") .font(.subheadline) .foregroundStyle(data.canSubmit ? DS.Color.brandGold : DS.Color.disabled) Spacer() } .padding(DS.Spacing.sm) .frame(maxWidth: .infinity) .background(Color.white) .overlay( RoundedRectangle(cornerRadius: 12, style: .continuous) .stroke(data.canSubmit ? DS.Color.brandGold : DS.Color.disabled, lineWidth: 1) ) Button(saveTitle(data)) { viewModel.save(content: content) } .buttonStyle(.borderedProminent) .disabled(!(data.canSubmit && !content.isEmpty && !viewModel.saving)) HistorySection(history: data.history) } .padding(DS.Spacing.md) } .background(DS.Color.brandPaper) } private func saveTitle(_ data: PlanSubmitData) -> String { if !data.canSubmit { return "不可提交" } if data.checked { return "保存修改" } return "保存计划" } } private struct HistorySection: View { let history: [MyPlanRecord] var body: some View { VStack(alignment: .leading, spacing: DS.Spacing.sm) { Text("历史计划") .font(.subheadline.bold()) .foregroundStyle(DS.Color.brandDark) if history.isEmpty { EmptyStateView(title: "暂无历史计划", systemImage: "doc") } else { ForEach(history.indices, id: \.self) { index in let item = history[index] VStack(alignment: .leading, spacing: DS.Spacing.xs) { Text("\(item.submittedTime) · \(item.status)") .font(.caption) .foregroundStyle(DS.Color.brandGold) Text(item.content) .font(.subheadline) .foregroundStyle(DS.Color.brandBrown) } .padding(DS.Spacing.md) .frame(maxWidth: .infinity, alignment: .leading) .background(Color.white) .clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous)) } } } } }