jsdw_ios/QuickLocation/Section/Group/GroupMemberList/GroupMemberListVC.swift

176 lines
6.8 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// GroupMemberListVC.swift
// QuickLocation
//
// Created by on 2026/6/29.
//
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
import ObjectMapper
class GroupMemberListVC: BaseViewController {
fileprivate var rootView: GroupMemberListView!
override func loadView() {
rootView = GroupMemberListView(frame: UIScreen.main.bounds)
view = rootView
}
private var viewModel: GroupMemberListVM
override func viewDidLoad() {
super.viewDidLoad()
bindViewModel()
reactiveAction()
requestGroupInfo()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
rootView.unlockVipMaskView.isHidden = AppContextManager.shared.vip > 1
}
private func reactiveAction() {
}
private func bindViewModel() {
viewModel.output.sectionedItems
.bind(to: rootView.collectionView.rx.items(dataSource: memberDataSource))
.disposed(by: disposeBag)
viewModel.output.drivingSectionedItems
.bind(to: rootView.drivingEventCV.rx.items(dataSource: drivingDataSource))
.disposed(by: disposeBag)
viewModel.output.scheduleSectionedItems
.bind(to: rootView.tableView.rx.items(dataSource: scheduleDataSource))
.disposed(by: disposeBag)
viewModel.output.scheduleSectionedItems
.subscribe(onNext: { [weak self] items in
self?.rootView.updateTableViewHeight(count: items.first?.items.count ?? 0)
}).disposed(by: disposeBag)
// +
rootView.selectedDate
.skip(1)
.subscribe(onNext: { [weak self] date in
self?.rootView.scrollReportToTop()
self?.requestDrivingEvents(for: date)
}).disposed(by: disposeBag)
// selectedDate API
rootView.collectionView.rx.modelSelected(GroupMemberModel.self)
.subscribe(onNext: { [weak self] model in
guard let self = self else { return }
self.viewModel.memberId = model.user_id
self.rootView.selectedMemberIsSelf = self.viewModel.isCurrentUser(id: model.user_id)
self.rootView.selectedDate.accept(Date())
self.rootView.scrollToToday()
self.rootView.scrollReportToTop()
self.rootView.collectionView.reloadData()
}).disposed(by: disposeBag)
}
///
private func requestDrivingEvents(for date: Date) {
guard !viewModel.memberId.isEmpty else { return }
let calendar = Calendar.current
let start = calendar.startOfDay(for: date)
let end: Date
if calendar.isDateInToday(date) {
end = Date() //
} else {
end = calendar.date(bySettingHour: 23, minute: 59, second: 59, of: date) ?? date
}
requestDrivingEvents(start_time: "\(Int64(start.timeIntervalSince1970 * 1000))",
end_time: "\(Int64(end.timeIntervalSince1970 * 1000))")
requestPlayback(date: "\(Int64(start.timeIntervalSince1970 * 1000))")
}
// MARK: - dataSource
private lazy var scheduleDataSource: RxTableViewSectionedReloadDataSource<ScheduleRecordSection> = {
RxTableViewSectionedReloadDataSource<ScheduleRecordSection> { _, tableView, indexPath, model in
let cell: ScheduleRecordCell = tableView.dequeueReusableCell(for: indexPath)
cell.configure(model)
return cell
}
}()
private lazy var memberDataSource: RxCollectionViewSectionedReloadDataSource<GroupMemberListSectionModel> = {
RxCollectionViewSectionedReloadDataSource<GroupMemberListSectionModel> { [weak self] datasource, collectionView, indexPath, model in
let cell: GroupMemberListCell = collectionView.dequeueReusableCell(for: indexPath)
cell.configure(model: model,
isCurrentUser: self?.viewModel.isCurrentUser(id: model.user_id) ?? false,
isSelected: model.user_id == self?.viewModel.memberId)
return cell
}
}()
private lazy var drivingDataSource: RxCollectionViewSectionedReloadDataSource<DrivingEventSection> = {
RxCollectionViewSectionedReloadDataSource<DrivingEventSection> { _, collectionView, indexPath, item in
let cell: DrivingEventCell = collectionView.dequeueReusableCell(for: indexPath)
cell.configure(item)
return cell
}
}()
// MARK: - API
private func requestGroupInfo() {
DLToast.showLoading()
GroupService.groupInfoByKey(viewModel.groupKey).subscribe { response in
DLToast.dismiss()
guard let model = response.model else { return }
self.viewModel.groupModel = model
self.viewModel.loadData(response.list)
self.rootView.selectedMemberIsSelf = self.viewModel.isCurrentUser(id: self.viewModel.memberId)
//
if !self.viewModel.memberId.isEmpty {
self.requestDrivingEvents(for: Date())
}
}.disposed(by: disposeBag)
}
//
private func requestDrivingEvents(start_time: String, end_time: String) {
DrivingService.drivingEvents(user_id: viewModel.memberId, start_time: start_time, end_time: end_time).subscribe { response in
guard let model = response.model else { return }
self.rootView.mileageLab.text = String(format: "%.1fkm", model.distance_km)
self.rootView.speedLab.text = String(format: "%.0fkm/h", model.max_speed)
self.viewModel.updateDrivingStats(model)
}.disposed(by: disposeBag)
}
//
private func requestPlayback(date: String) {
let start = CFAbsoluteTimeGetCurrent()
dl.showLoading(text: "行程记录获取中...")
DrivingService.playback(user_id: viewModel.memberId, date: date).subscribe(onNext: { [weak self] response in
let elapsed = CFAbsoluteTimeGetCurrent() - start
print("[playback] total: \(String(format: "%.1f", elapsed))s, items: \(response.list.count)")
self?.dl.dismiss()
self?.viewModel.loadScheduleRecords(response.list)
}, onError: { _ in
self.dl.dismiss()
}).disposed(by: disposeBag)
}
// MARK: - Init
init(groupKey: String) {
viewModel = GroupMemberListVM(groupKey: groupKey)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}