// // ScheduleViewControllers.swift // suixinkan // // Created by Codex on 2026/6/26. // import UIKit /// 排班管理页。 final class ScheduleManagementViewController: ModuleTableViewController { private let viewModel = ScheduleManagementViewModel() /// 视图加载完成后的 UI 初始化与数据绑定。 override func viewDidLoad() { title = "排班管理" navigationItem.rightBarButtonItems = [ UIBarButtonItem(title: "新增", style: .plain, target: self, action: #selector(addSchedule)), UIBarButtonItem(title: "下月", style: .plain, target: self, action: #selector(nextMonth)) ] navigationItem.leftBarButtonItem = UIBarButtonItem( title: "上月", style: .plain, target: self, action: #selector(previousMonth) ) super.viewDidLoad() wireViewModel(viewModel) { [weak self] in self?.updateTitle() } } /// table行Count相关逻辑。 override func tableRowCount() -> Int { viewModel.items.count } /// 配置Cell展示内容。 override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) { let item = viewModel.items[indexPath.row] cell.configure( title: item.name, subtitle: "\(item.startTime) - \(item.endTime)", detail: item.orderNumber ?? item.remark ) } /// didSelectTableRow 回调处理。 override func didSelectTableRow(at indexPath: IndexPath) { let item = viewModel.items[indexPath.row] let alert = UIAlertController(title: item.name, message: "删除该排班?", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "取消", style: .cancel)) alert.addAction(UIAlertAction(title: "删除", style: .destructive) { [weak self] _ in guard let self else { return } Task { await self.viewModel.delete(item: item, api: self.services.scheduleAPI, scenicId: self.services.currentScenicId) } }) present(alert, animated: true) } /// 刷新Content。 override func reloadContent() async { await viewModel.reload(api: services.scheduleAPI, scenicId: services.currentScenicId) updateTitle() } /// 更新Title状态。 private func updateTitle() { let month = viewModel.monthDate.scheduleYearMonthText title = "排班 \(month)" } /// previousMonth相关逻辑。 @objc private func previousMonth() { Task { await viewModel.previousMonth(api: services.scheduleAPI, scenicId: services.currentScenicId) } } /// nextMonth相关逻辑。 @objc private func nextMonth() { Task { await viewModel.nextMonth(api: services.scheduleAPI, scenicId: services.currentScenicId) } } /// add排班相关逻辑。 @objc private func addSchedule() { navigationController?.pushViewController(ScheduleAddViewController(), animated: true) } } extension ScheduleManagementViewModel: ViewModelBindable {} /// 新增排班页。 final class ScheduleAddViewController: ModuleTableViewController { private let viewModel = ScheduleAddViewModel() private let nameField = UITextField() private let remarkField = UITextField() /// 视图加载完成后的 UI 初始化与数据绑定。 override func viewDidLoad() { title = "新增排班" navigationItem.rightBarButtonItem = UIBarButtonItem( title: "提交", style: .done, target: self, action: #selector(submit) ) super.viewDidLoad() wireViewModel(viewModel) { } setupFormHeader() } /// 初始化FormHeader相关 UI 或状态。 private func setupFormHeader() { nameField.placeholder = "日程名称" nameField.borderStyle = .roundedRect remarkField.placeholder = "备注" remarkField.borderStyle = .roundedRect let stack = UIStackView(arrangedSubviews: [nameField, remarkField]) stack.axis = .vertical stack.spacing = 8 stack.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 96) stack.layoutMargins = UIEdgeInsets(top: 12, left: 16, bottom: 12, right: 16) stack.isLayoutMarginsRelativeArrangement = true tableView.tableHeaderView = stack } /// table行Count相关逻辑。 override func tableRowCount() -> Int { viewModel.availableOrders.count } /// 配置Cell展示内容。 override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) { let order = viewModel.availableOrders[indexPath.row] let selected = viewModel.draft.selectedOrder?.orderNumber == order.orderNumber cell.configure(title: order.orderNumber, subtitle: order.projectName, detail: selected ? "已选择" : nil) cell.accessoryType = selected ? .checkmark : .none } /// didSelectTableRow 回调处理。 override func didSelectTableRow(at indexPath: IndexPath) { viewModel.draft.selectedOrder = viewModel.availableOrders[indexPath.row] reloadTable() } /// 刷新Content。 override func reloadContent() async { await viewModel.loadOrders(api: services.scheduleAPI, scenicId: services.currentScenicId) } /// 提交。 @objc private func submit() { viewModel.draft.name = nameField.text ?? "" viewModel.draft.remark = remarkField.text ?? "" Task { let start = Date() let end = Calendar.current.date(byAdding: .hour, value: 1, to: start) ?? start let success = await viewModel.submit( api: services.scheduleAPI, scenicId: services.currentScenicId, startDate: start, endDate: end ) if success { navigationController?.popViewController(animated: true) } } } } extension ScheduleAddViewModel: ViewModelBindable {}