feat: add AI retouch before-after comparison

This commit is contained in:
2026-08-13 17:46:06 +08:00
parent e190b5958b
commit 0f3b26991e
12 changed files with 953 additions and 145 deletions
@@ -434,8 +434,13 @@ final class TravelAlbumAIRetouchTemplateViewController: BaseViewController {
}
private func showPreview(for template: TravelAlbumAIRetouchTemplate) {
let controller = TravelAlbumAIRetouchTemplatePreviewViewController(template: template)
controller.modalPresentationStyle = .fullScreen
guard let content = template.comparisonContent else {
showToast("暂无对比预览")
return
}
let controller = BeforeAfterComparisonViewController(
viewModel: BeforeAfterComparisonViewModel(content: content)
)
present(controller, animated: true)
}
}
@@ -908,128 +913,6 @@ final class TravelAlbumAIRetouchSectionHeader: UICollectionReusableView {
}
}
/// AI 修图模板全屏预览,支持双指缩放查看模板细节。
final class TravelAlbumAIRetouchTemplatePreviewViewController: UIViewController {
private let template: TravelAlbumAIRetouchTemplate
private let backButton = UIButton(type: .system)
private let titleLabel = UILabel()
private let subtitleLabel = UILabel()
private let scrollView = UIScrollView()
private let imageView = UIImageView()
/// 创建指定模板的全屏预览页。
init(template: TravelAlbumAIRetouchTemplate) {
self.template = template
super.init(nibName: nil, bundle: nil)
modalPresentationStyle = .fullScreen
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
setupUI()
setupConstraints()
loadPreview()
}
private func setupUI() {
view.backgroundColor = .black
view.accessibilityIdentifier = "travelAlbum.aiRetouchTemplatePreview"
var backConfiguration = UIButton.Configuration.filled()
backConfiguration.image = UIImage(systemName: "chevron.left")
backConfiguration.baseForegroundColor = .white
backConfiguration.baseBackgroundColor = UIColor.white.withAlphaComponent(0.12)
backConfiguration.background.cornerRadius = 24
backButton.configuration = backConfiguration
backButton.accessibilityLabel = "返回模板选择"
backButton.accessibilityIdentifier = "travelAlbum.aiRetouchTemplatePreviewBackButton"
backButton.addTarget(self, action: #selector(backTapped), for: .touchUpInside)
titleLabel.text = template.name
titleLabel.textColor = .white
titleLabel.font = .systemFont(ofSize: 20, weight: .semibold)
titleLabel.textAlignment = .center
titleLabel.lineBreakMode = .byTruncatingTail
subtitleLabel.text = "双指缩放查看细节"
subtitleLabel.textColor = UIColor.white.withAlphaComponent(0.52)
subtitleLabel.font = .systemFont(ofSize: 14, weight: .regular)
subtitleLabel.textAlignment = .center
scrollView.minimumZoomScale = 1
scrollView.maximumZoomScale = 4
scrollView.delegate = self
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
scrollView.accessibilityIdentifier = "travelAlbum.aiRetouchTemplatePreviewScrollView"
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
imageView.backgroundColor = UIColor(hex: 0x111111)
imageView.accessibilityLabel = "\(template.name)模板预览图"
view.addSubview(backButton)
view.addSubview(titleLabel)
view.addSubview(subtitleLabel)
view.addSubview(scrollView)
scrollView.addSubview(imageView)
}
private func setupConstraints() {
backButton.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide).offset(20)
make.leading.equalToSuperview().offset(18)
make.size.equalTo(48)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(view.safeAreaLayoutGuide).offset(20)
make.leading.greaterThanOrEqualTo(backButton.snp.trailing).offset(12)
make.centerX.equalToSuperview()
make.trailing.lessThanOrEqualToSuperview().offset(-66)
make.height.equalTo(26)
}
subtitleLabel.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(2)
make.centerX.equalToSuperview()
}
scrollView.snp.makeConstraints { make in
make.top.equalTo(subtitleLabel.snp.bottom).offset(18)
make.leading.trailing.bottom.equalToSuperview()
}
imageView.snp.makeConstraints { make in
make.center.equalTo(scrollView.frameLayoutGuide)
make.width.equalTo(scrollView.frameLayoutGuide)
make.height.equalTo(imageView.snp.width).multipliedBy(0.75)
}
}
private func loadPreview() {
let placeholder = UIImage(named: "ai_retouch_template_placeholder")
guard let url = URL(string: template.previewURL), !template.previewURL.isEmpty else {
imageView.image = placeholder
return
}
imageView.kf.setImage(
with: url,
placeholder: placeholder
)
}
@objc private func backTapped() {
dismiss(animated: true)
}
}
extension TravelAlbumAIRetouchTemplatePreviewViewController: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
imageView
}
}
/// AI 修图模板页视觉常量。
private enum AIRetouchTemplateStyle {
static let primary = UIColor(hex: 0x1677FF)