完善景区排队设置页与全局按钮配置迁移。

重构排队设置与变更日志交互,补充 Overlay 与资源,并将多页面主操作按钮统一到 UIButton Configuration,同步更新相关单元测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-14 16:21:53 +08:00
parent efb3925257
commit 6336feff27
49 changed files with 1996 additions and 590 deletions

View File

@ -261,33 +261,38 @@ final class ScenicQueueTicketCell: UITableViewCell {
private func rebuildActions(ticket: ScenicQueueTicket, shootingQueueNo: String?, remainSeconds: Int) {
actionsStack.arrangedSubviews.forEach { $0.removeFromSuperview() }
let state = ScenicQueueTicketActionState.make(
ticket: ticket,
shootingQueueNo: shootingQueueNo,
remainSeconds: remainSeconds,
showStartShootingButton: showStartShootingButton
)
let skip = ScenicQueueActionButton(title: "过号", background: ScenicQueueTokens.buttonSkipBackground, foreground: ScenicQueueTokens.buttonSkipForeground)
skip.addTarget(self, action: #selector(skipTapped), for: .touchUpInside)
let primaryTitle: String
if shootingQueueNo == ticket.queueNo {
primaryTitle = "剩余 \(max(0, remainSeconds))"
} else {
primaryTitle = ticket.status == .called ? "开始拍摄" : "叫号"
}
let primary = ScenicQueueActionButton(title: primaryTitle, background: ScenicQueueTokens.bannerBlue, foreground: .white)
primary.isEnabled = shootingQueueNo != ticket.queueNo
primary.alpha = primary.isEnabled ? 1 : 0.65
primary.addTarget(self, action: #selector(primaryTapped), for: .touchUpInside)
let row = UIStackView(arrangedSubviews: [skip, primary])
skip.isEnabled = state.skipEnabled
skip.alpha = state.skipEnabled ? 1 : 0.45
let row = UIStackView(arrangedSubviews: [skip])
row.axis = .horizontal
row.spacing = 10
row.distribution = .fillProportionally
skip.snp.makeConstraints { make in
make.height.equalTo(46)
make.width.equalTo(primary).multipliedBy(0.56)
if state.primaryVisible {
let primary = ScenicQueueActionButton(title: state.primaryTitle, background: ScenicQueueTokens.bannerBlue, foreground: .white)
primary.isEnabled = state.primaryEnabled
primary.alpha = state.primaryEnabled ? 1 : 0.65
primary.addTarget(self, action: #selector(primaryTapped), for: .touchUpInside)
row.addArrangedSubview(primary)
skip.snp.makeConstraints { $0.width.equalTo(primary).multipliedBy(0.56) }
}
row.snp.makeConstraints { $0.height.equalTo(46) }
actionsStack.addArrangedSubview(row)
if ticket.status == .called, shootingQueueNo != ticket.queueNo {
recallButton.removeTarget(nil, action: nil, for: .allEvents)
completeButton.removeTarget(nil, action: nil, for: .allEvents)
if state.recallVisible {
recallButton.addTarget(self, action: #selector(recallTapped), for: .touchUpInside)
recallButton.snp.makeConstraints { make in make.height.equalTo(40) }
actionsStack.addArrangedSubview(recallButton)
}
if ticket.showCompleteAction {
if state.completeVisible {
completeButton.addTarget(self, action: #selector(completeTapped), for: .touchUpInside)
completeButton.snp.makeConstraints { make in make.height.equalTo(40) }
actionsStack.addArrangedSubview(completeButton)
@ -329,17 +334,27 @@ final class ScenicQueueTicketCell: UITableViewCell {
right.backgroundColor = accent ? AppColor.primaryLight : .clear
right.layer.cornerRadius = 2
right.clipsToBounds = true
if let tap {
right.isUserInteractionEnabled = true
right.addGestureRecognizer(UITapGestureRecognizer(target: self, action: tap))
}
row.addSubview(left)
row.addSubview(right)
let valueContainer = UIStackView(arrangedSubviews: [right])
valueContainer.axis = .horizontal
valueContainer.alignment = .center
valueContainer.spacing = 8
if let tap {
let dial = UIButton(type: .system)
dial.backgroundColor = ScenicQueueTokens.bannerBlue
dial.tintColor = .white
dial.setImage(UIImage(systemName: "phone.fill")?.withConfiguration(UIImage.SymbolConfiguration(pointSize: 15, weight: .medium)), for: .normal)
dial.layer.cornerRadius = 16
dial.addTarget(self, action: tap, for: .touchUpInside)
valueContainer.addArrangedSubview(dial)
dial.snp.makeConstraints { $0.size.equalTo(32) }
}
row.addSubview(valueContainer)
left.snp.makeConstraints { make in
make.leading.centerY.equalToSuperview()
make.top.bottom.equalToSuperview()
}
right.snp.makeConstraints { make in
valueContainer.snp.makeConstraints { make in
make.trailing.centerY.equalToSuperview()
make.leading.greaterThanOrEqualTo(left.snp.trailing).offset(12)
}
@ -490,17 +505,27 @@ final class ScenicQueueSkippedCell: UITableViewCell {
right.text = value
right.font = ScenicQueueTokens.phoneMaskedFont
right.textColor = AppColor.textPrimary
if let tap {
right.isUserInteractionEnabled = true
right.addGestureRecognizer(UITapGestureRecognizer(target: self, action: tap))
}
row.addSubview(left)
row.addSubview(right)
let valueContainer = UIStackView(arrangedSubviews: [right])
valueContainer.axis = .horizontal
valueContainer.alignment = .center
valueContainer.spacing = 8
if let tap {
let dial = UIButton(type: .system)
dial.backgroundColor = ScenicQueueTokens.bannerBlue
dial.tintColor = .white
dial.setImage(UIImage(systemName: "phone.fill")?.withConfiguration(UIImage.SymbolConfiguration(pointSize: 15, weight: .medium)), for: .normal)
dial.layer.cornerRadius = 16
dial.addTarget(self, action: tap, for: .touchUpInside)
valueContainer.addArrangedSubview(dial)
dial.snp.makeConstraints { $0.size.equalTo(32) }
}
row.addSubview(valueContainer)
left.snp.makeConstraints { make in
make.leading.centerY.equalToSuperview()
make.top.bottom.equalToSuperview()
}
right.snp.makeConstraints { make in
valueContainer.snp.makeConstraints { make in
make.trailing.centerY.equalToSuperview()
make.leading.greaterThanOrEqualTo(left.snp.trailing).offset(12)
}