import UIKit final class CategoryListViewController: UITableViewController { private let store: WordStore init(store: WordStore) { self.store = store super.init(style: .plain) } @available(*, unavailable) required init?(coder: NSCoder) { fatalError() } override func viewDidLoad() { super.viewDidLoad() title = "背单词" tableView.register(CategoryCardCell.self, forCellReuseIdentifier: "cell") tableView.separatorStyle = .none tableView.backgroundColor = .systemBackground tableView.contentInset.top = 8 if let error = store.loadError { showError(error) } } private func showError(_ message: String) { let label = UILabel() label.text = "词库加载失败\n\(message)" label.numberOfLines = 0 label.textAlignment = .center label.textColor = .secondaryLabel let background = UIView() background.addSubview(label) label.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ label.centerXAnchor.constraint(equalTo: background.centerXAnchor), label.centerYAnchor.constraint(equalTo: background.centerYAnchor), label.leadingAnchor.constraint(greaterThanOrEqualTo: background.leadingAnchor, constant: 24) ]) tableView.backgroundView = background } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { store.categories.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CategoryCardCell cell.configure(with: store.categories[indexPath.row], color: Theme.Color.category(at: indexPath.row)) return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { Haptics.selection() let category = store.categories[indexPath.row] if let subs = category.subcategories, !subs.isEmpty { let vc = SubcategoryListViewController(category: category, colorIndex: indexPath.row) navigationController?.pushViewController(vc, animated: true) } else { navigationController?.pushViewController( WordListViewController(category: category, colorIndex: indexPath.row), animated: true) } } }