Files
汉秋 d99a5b1bf8 Advance UIKit rewrite with AMap integration and core UI modules.
Integrate高德 SDK with simulator-safe build flags, add map views for operating area and punch points, refactor main tabs and key feature screens to UIKit with Diffable lists, and document Swift concurrency defaults in AGENTS.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-26 15:16:12 +08:00

166 lines
5.9 KiB
Swift

//
// 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() }
}
/// tableCount
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
}
/// tableCount
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 {}