Initial commit: suixinkan_ios UIKit rewrite project.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-26 14:33:31 +08:00
commit 9edf993432
297 changed files with 47151 additions and 0 deletions

View File

@ -0,0 +1,231 @@
//
// AssetsViewControllers.swift
// suixinkan
//
// Created by Codex on 2026/6/26.
//
import UIKit
///
final class CloudStorageViewController: ModuleTableViewController {
private let viewModel = CloudStorageViewModel()
override func viewDidLoad() {
title = "云盘"
navigationItem.rightBarButtonItem = UIBarButtonItem(
title: "传输",
style: .plain,
target: self,
action: #selector(openTransit)
)
super.viewDidLoad()
wireViewModel(viewModel) { }
}
override func tableRowCount() -> Int { viewModel.files.count }
override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) {
let file = viewModel.files[indexPath.row]
cell.configure(title: file.name, subtitle: file.updatedAt, detail: "\(file.fileSize)")
}
override func reloadContent() async {
await viewModel.reload(api: services.assetsAPI)
}
override func willDisplayTableRow(at indexPath: IndexPath) {
guard indexPath.row >= viewModel.files.count - 2 else { return }
Task { await viewModel.loadMore(api: services.assetsAPI) }
}
@objc private func openTransit() {
navigationController?.pushViewController(CloudStorageTransitViewController(), animated: true)
}
}
extension CloudStorageViewModel: ViewModelBindable {}
///
final class CloudStorageTransitViewController: ModuleTableViewController {
private let store = CloudTransferStore.shared
override func viewDidLoad() {
title = "传输记录"
super.viewDidLoad()
store.onChange = { [weak self] in self?.reloadTable() }
}
override func tableRowCount() -> Int { store.records.count }
override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) {
let record = store.records[indexPath.row]
cell.configure(title: record.fileName, subtitle: record.message, detail: "\(record.progress)%")
}
override func reloadContent() async {}
}
enum MediaLibraryKindRoute {
case material
case sample
}
/// /
final class MediaLibraryViewController: ModuleTableViewController {
private let kind: MediaLibraryKindRoute
private let viewModel: MediaLibraryViewModel
init(kind: MediaLibraryKindRoute = .material) {
self.kind = kind
switch kind {
case .material:
viewModel = MediaLibraryViewModel(kind: .material)
case .sample:
viewModel = MediaLibraryViewModel(kind: .sample)
}
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
title = kind == .sample ? "样片库" : "素材库"
navigationItem.rightBarButtonItem = UIBarButtonItem(
title: "上传",
style: .plain,
target: self,
action: #selector(openUpload)
)
super.viewDidLoad()
wireViewModel(viewModel) { }
}
override func tableRowCount() -> Int { viewModel.items.count }
override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) {
let item = viewModel.items[indexPath.row]
cell.configure(title: item.name, subtitle: item.projectName, detail: item.createdAt)
}
override func reloadContent() async {
await viewModel.reload(api: services.assetsAPI)
}
@objc private func openUpload() {
navigationController?.pushViewController(MediaLibraryUploadViewController(kind: kind), animated: true)
}
}
extension MediaLibraryViewModel: ViewModelBindable {}
/// /
final class MediaLibraryUploadViewController: ModuleTableViewController {
private let kind: MediaLibraryKindRoute
private let viewModel = MediaLibraryEditorViewModel()
private let nameField = UITextField()
init(kind: MediaLibraryKindRoute) {
self.kind = kind
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
title = kind == .sample ? "上传样片" : "上传素材"
navigationItem.rightBarButtonItem = UIBarButtonItem(
title: "提交",
style: .done,
target: self,
action: #selector(submit)
)
super.viewDidLoad()
nameField.placeholder = "素材名称"
nameField.borderStyle = .roundedRect
nameField.frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: 52)
tableView.tableHeaderView = nameField
wireViewModel(viewModel) { }
}
override func tableRowCount() -> Int { viewModel.projects.count }
override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) {
let project = viewModel.projects[indexPath.row]
cell.configure(title: project.name, subtitle: project.statusName)
}
override func reloadContent() async {
await viewModel.loadProjects(scenicId: services.currentScenicId, api: services.assetsAPI)
}
@objc private func submit() {
viewModel.name = nameField.text ?? ""
Task {
let mediaKind: MediaLibraryKind = kind == .sample ? .sample : .material
let success = await viewModel.submit(
kind: mediaKind,
scenicId: services.currentScenicId,
api: services.assetsAPI,
uploadService: services.ossUploadService
)
if success { navigationController?.popViewController(animated: true) }
}
}
}
extension MediaLibraryEditorViewModel: ViewModelBindable {}
///
final class AlbumListViewController: ModuleTableViewController {
private let viewModel = AlbumListViewModel()
override func viewDidLoad() {
title = "相册"
super.viewDidLoad()
wireViewModel(viewModel) { }
}
override func tableRowCount() -> Int { viewModel.folders.count }
override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) {
let folder = viewModel.folders[indexPath.row]
cell.configure(title: folder.name, subtitle: folder.createTime, detail: "\(folder.totalCount)")
}
override func reloadContent() async {
await viewModel.reload(api: services.assetsAPI, scenicId: services.currentScenicId)
}
}
extension AlbumListViewModel: ViewModelBindable {}
///
final class AlbumTrailerViewController: ModuleTableViewController {
private let viewModel = AlbumTrailerViewModel()
override func viewDidLoad() {
title = "相册预告"
super.viewDidLoad()
wireViewModel(viewModel) { }
}
override func tableRowCount() -> Int { viewModel.folders.count }
override func configureCell(_ cell: TitleSubtitleTableViewCell, at indexPath: IndexPath) {
let folder = viewModel.folders[indexPath.row]
cell.configure(title: folder.name, subtitle: folder.createTime, detail: "\(folder.totalCount)")
}
override func reloadContent() async {
await viewModel.loadFolders(api: services.assetsAPI, scenicId: services.currentScenicId)
}
}
extension AlbumTrailerViewModel: ViewModelBindable {}