修复样片详情解析并优化列表上下架交互。

兼容 Android 媒体项 size 字段格式,增强灵活解码容错,并统一样片列表开关确认逻辑与安全区布局。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-13 15:14:40 +08:00
parent afcd412f11
commit 07b2b9d459
7 changed files with 96 additions and 47 deletions

View File

@ -68,7 +68,7 @@ final class SampleDetailViewController: SampleBaseViewController {
override func setupConstraints() {
scrollView.snp.makeConstraints { make in
make.top.equalToSuperview()
make.top.equalTo(view.safeAreaLayoutGuide)
make.leading.trailing.bottom.equalTo(view.safeAreaLayoutGuide)
}
contentStack.snp.makeConstraints { make in

View File

@ -97,15 +97,10 @@ final class SampleListViewController: SampleBaseViewController {
withIdentifier: SampleListCell.reuseIdentifier,
for: indexPath
) as! SampleListCell
cell.apply(item: item, isOperating: self?.viewModel.operatingSampleIDs.contains(item.id) == true)
cell.onToggle = { [weak self, weak cell] checked in
cell.apply(item: item)
cell.onToggle = { [weak self] checked in
guard let self else { return }
Task {
let resolved = await self.viewModel.toggleListing(sampleId: item.id, checked: checked, api: self.api)
await MainActor.run {
cell?.resolveToggle(sampleId: item.id, isOn: resolved)
}
}
Task { await self.viewModel.toggleListing(sampleId: item.id, checked: checked, api: self.api) }
}
return cell
}
@ -142,7 +137,7 @@ final class SampleListViewController: SampleBaseViewController {
override func setupConstraints() {
searchContainer.snp.makeConstraints { make in
make.top.equalToSuperview()
make.top.equalTo(view.safeAreaLayoutGuide)
make.leading.trailing.equalToSuperview()
make.height.equalTo(68)
}
@ -349,13 +344,12 @@ private final class SampleListCell: UITableViewCell {
private let scenicSpotLabel = UILabel()
private let statusBadge = SampleStatusBadgeView()
private let listingSwitch = UISwitch()
private let listingActivityIndicator = UIActivityIndicatorView(style: .medium)
private let statsStack = UIStackView()
private let shareStatView = SampleStatView(iconName: "sample_ic_share_count")
private let likeStatView = SampleStatView(iconName: "sample_ic_like_count")
private let collectStatView = SampleStatView(iconName: "sample_ic_collect_count")
private var isApplying = false
private var representedSampleID: Int?
private var confirmedListingState = false
var onToggle: ((Bool) -> Void)?
@ -371,21 +365,17 @@ private final class SampleListCell: UITableViewCell {
override func prepareForReuse() {
super.prepareForReuse()
representedSampleID = nil
onToggle = nil
}
func apply(item: SampleMaterialItem, isOperating: Bool) {
func apply(item: SampleMaterialItem) {
isApplying = true
representedSampleID = item.id
confirmedListingState = item.listingStatus == 1
titleLabel.text = item.name
projectLabel.text = "项目: \(item.projectName)"
scenicSpotLabel.text = "打卡地: \(item.scenicSpotName)"
statusBadge.apply(status: item.status)
listingSwitch.setOn(item.listingStatus == 1, animated: false)
listingSwitch.isEnabled = item.status == 1 && !isOperating
listingSwitch.isHidden = isOperating
isOperating ? listingActivityIndicator.startAnimating() : listingActivityIndicator.stopAnimating()
listingSwitch.setOn(confirmedListingState, animated: false)
shareStatView.setCount(item.shareCount)
likeStatView.setCount(item.likesCount)
collectStatView.setCount(item.collectCount)
@ -400,17 +390,6 @@ private final class SampleListCell: UITableViewCell {
isApplying = false
}
///
func resolveToggle(sampleId: Int, isOn: Bool) {
guard representedSampleID == sampleId else { return }
isApplying = true
listingSwitch.setOn(isOn, animated: true)
listingSwitch.isEnabled = true
listingSwitch.isHidden = false
listingActivityIndicator.stopAnimating()
isApplying = false
}
private func setupUI() {
selectionStyle = .none
backgroundColor = SampleManagementUITokens.pageBackground
@ -443,8 +422,6 @@ private final class SampleListCell: UITableViewCell {
listingSwitch.onTintColor = AppColor.primary
listingSwitch.accessibilityLabel = "样片上下架"
listingSwitch.addTarget(self, action: #selector(switchChanged), for: .valueChanged)
listingActivityIndicator.color = AppColor.primary
listingActivityIndicator.hidesWhenStopped = true
statsStack.axis = .horizontal
statsStack.spacing = 16
@ -458,7 +435,6 @@ private final class SampleListCell: UITableViewCell {
cardView.addSubview(scenicSpotLabel)
cardView.addSubview(statusBadge)
cardView.addSubview(listingSwitch)
cardView.addSubview(listingActivityIndicator)
cardView.addSubview(statsStack)
[shareStatView, likeStatView, collectStatView].forEach(statsStack.addArrangedSubview)
@ -498,9 +474,6 @@ private final class SampleListCell: UITableViewCell {
make.trailing.equalToSuperview().inset(12)
make.leading.greaterThanOrEqualTo(statusBadge.snp.trailing).offset(8)
}
listingActivityIndicator.snp.makeConstraints { make in
make.center.equalTo(listingSwitch)
}
statsStack.snp.makeConstraints { make in
make.top.equalTo(statusBadge.snp.bottom).offset(10)
make.leading.equalTo(titleLabel)
@ -511,10 +484,9 @@ private final class SampleListCell: UITableViewCell {
@objc private func switchChanged() {
guard !isApplying else { return }
listingSwitch.isEnabled = false
listingSwitch.isHidden = true
listingActivityIndicator.startAnimating()
onToggle?(listingSwitch.isOn)
let requestedState = listingSwitch.isOn
listingSwitch.setOn(confirmedListingState, animated: true)
onToggle?(requestedState)
}
}

View File

@ -138,7 +138,7 @@ final class UploadSampleViewController: SampleBaseViewController {
make.trailing.equalToSuperview().inset(15)
}
scrollView.snp.makeConstraints { make in
make.top.equalToSuperview()
make.top.equalTo(view.safeAreaLayoutGuide)
make.leading.trailing.equalTo(view.safeAreaLayoutGuide)
make.bottom.equalTo(bottomBar.snp.top)
}
@ -698,6 +698,10 @@ private final class SampleUploadThumbView: UIControl {
deleteButton.layer.cornerRadius = 10
playIcon.tintColor = .white
playIcon.isHidden = true
[imageView, addCircle, addIcon, textLabel, playIcon].forEach {
$0.isUserInteractionEnabled = false
}
accessibilityLabel = mediaType == .image ? "上传图片" : "上传视频"
addSubview(imageView)
addSubview(addCircle)
@ -828,6 +832,10 @@ private final class SampleCoverUploadView: UIControl {
hintLabel.font = .systemFont(ofSize: 12)
hintLabel.textColor = UIColor(hex: 0xB6BECA)
hintLabel.textAlignment = .center
[imageView, addCircle, addIcon, titleLabel, hintLabel].forEach {
$0.isUserInteractionEnabled = false
}
accessibilityLabel = "上传封面图片"
deleteButton.setImage(UIImage(named: "material_ic_clear"), for: .normal)
deleteButton.tintColor = .white
deleteButton.backgroundColor = UIColor.black.withAlphaComponent(0.6)