重构首页为单一集合视图并添加全部功能自定义

This commit is contained in:
2026-07-07 09:57:41 +08:00
parent 16e86c8899
commit af450fb4cc
14 changed files with 1222 additions and 209 deletions

View File

@ -0,0 +1,165 @@
//
// HomeCollectionModels.swift
// suixinkan
//
import Foundation
import UIKit
/// CollectionView
enum HomeCollectionSection: Hashable {
case workStatus
case locationReport
case quickActions
case store
case commonApps
}
/// CollectionView 使 case Diffable
enum HomeCollectionItem: Hashable {
case workStatus
case locationReport
case quickActions
case store
case menu(HomeMenuItem)
}
/// CollectionView snapshot
enum HomeCollectionLayoutBuilder {
private static let menuColumns = 3
private static let menuSpacing: CGFloat = 15
private static let menuAspectRatio: CGFloat = 1.3
private static let sectionSpacing = AppSpacing.sm
/// Compositional Layout section
static func makeLayout(sections: [HomeCollectionSection]) -> UICollectionViewCompositionalLayout {
UICollectionViewCompositionalLayout { sectionIndex, environment in
guard sectionIndex < sections.count else { return nil }
switch sections[sectionIndex] {
case .workStatus:
return fullWidthSection(height: AppSpacing.formRowHeight)
case .locationReport:
return fullWidthSection(height: 100)
case .quickActions:
return fullWidthSection(height: 72)
case .store:
return fullWidthSection(height: 96)
case .commonApps:
return menuGridSection(environment: environment)
}
}
}
/// ViewModel Diffable Snapshot
static func makeSnapshot(
showWorkBlock: Bool,
showStore: Bool,
storeItem: StoreItem?,
commonMenus: [HomeMenuItem]
) -> NSDiffableDataSourceSnapshot<HomeCollectionSection, HomeCollectionItem> {
var snapshot = NSDiffableDataSourceSnapshot<HomeCollectionSection, HomeCollectionItem>()
if showWorkBlock {
snapshot.appendSections([.workStatus, .locationReport, .quickActions])
snapshot.appendItems([.workStatus], toSection: .workStatus)
snapshot.appendItems([.locationReport], toSection: .locationReport)
snapshot.appendItems([.quickActions], toSection: .quickActions)
}
if showStore, storeItem != nil {
snapshot.appendSections([.store])
snapshot.appendItems([.store], toSection: .store)
}
let menus = commonMenus + [HomeMenuItem.moreFunctions]
snapshot.appendSections([.commonApps])
snapshot.appendItems(menus.map { HomeCollectionItem.menu($0) }, toSection: .commonApps)
return snapshot
}
/// snapshot layout 使
static func sectionOrder(
showWorkBlock: Bool,
showStore: Bool,
storeItem: StoreItem?
) -> [HomeCollectionSection] {
var sections: [HomeCollectionSection] = []
if showWorkBlock {
sections.append(contentsOf: [.workStatus, .locationReport, .quickActions])
}
if showStore, storeItem != nil {
sections.append(.store)
}
sections.append(.commonApps)
return sections
}
private static let horizontalInset = AppSpacing.screenHorizontalInset
private static func fullWidthSection(height: CGFloat) -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .absolute(height)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .absolute(height)
)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(
top: 0,
leading: horizontalInset,
bottom: sectionSpacing,
trailing: horizontalInset
)
return section
}
private static func menuGridSection(environment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection {
let availableWidth = environment.container.effectiveContentSize.width - horizontalInset * 2
let totalSpacing = menuSpacing * CGFloat(menuColumns - 1)
let itemWidth = max(0, (availableWidth - totalSpacing) / CGFloat(menuColumns))
let itemHeight = itemWidth / menuAspectRatio
let itemSize = NSCollectionLayoutSize(
widthDimension: .absolute(itemWidth),
heightDimension: .absolute(itemHeight)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .absolute(itemHeight)
)
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: groupSize,
repeatingSubitem: item,
count: menuColumns
)
group.interItemSpacing = .fixed(menuSpacing)
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = menuSpacing
section.contentInsets = NSDirectionalEdgeInsets(
top: 0,
leading: horizontalInset,
bottom: sectionSpacing,
trailing: horizontalInset
)
let headerSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1),
heightDimension: .absolute(36)
)
let header = NSCollectionLayoutBoundarySupplementaryItem(
layoutSize: headerSize,
elementKind: UICollectionView.elementKindSectionHeader,
alignment: .top
)
section.boundarySupplementaryItems = [header]
return section
}
}