Introduce unified design tokens and migrate Home, Orders, and Statistics UI.
Establish AppColor/AppFont/AppSpacing/AppRadius theming, shared components, and design-system docs so pilot screens align with Android while keeping iOS-native spacing and touch targets. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -32,14 +32,14 @@ final class AppButton: UIButton {
|
||||
}
|
||||
|
||||
private func setupUI(title: String) {
|
||||
titleLabel?.font = .systemFont(ofSize: 14, weight: .regular)
|
||||
layer.cornerRadius = 10
|
||||
titleLabel?.font = .app(.body)
|
||||
layer.cornerRadius = AppRadius.md
|
||||
clipsToBounds = true
|
||||
setTitle(title, for: .normal)
|
||||
updateAppearance()
|
||||
|
||||
snp.makeConstraints { make in
|
||||
make.height.equalTo(46)
|
||||
make.height.equalTo(AppSpacing.buttonHeight)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
44
suixinkan/UI/Common/AppCardView.swift
Normal file
44
suixinkan/UI/Common/AppCardView.swift
Normal file
@ -0,0 +1,44 @@
|
||||
//
|
||||
// AppCardView.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import SnapKit
|
||||
import UIKit
|
||||
|
||||
/// 标准白底卡片容器,统一圆角与可选描边。
|
||||
final class AppCardView: UIView {
|
||||
|
||||
/// 卡片内容区,子视图应添加到此 container。
|
||||
let contentView = UIView()
|
||||
|
||||
private let showsBorder: Bool
|
||||
|
||||
/// - Parameter showsBorder: 是否显示 1px 描边(默认 false,flat 风格)。
|
||||
init(showsBorder: Bool = false) {
|
||||
self.showsBorder = showsBorder
|
||||
super.init(frame: .zero)
|
||||
setupUI()
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func setupUI() {
|
||||
backgroundColor = AppColor.cardBackground
|
||||
layer.cornerRadius = AppRadius.md
|
||||
clipsToBounds = true
|
||||
|
||||
if showsBorder {
|
||||
layer.borderWidth = 1
|
||||
layer.borderColor = AppColor.cardOutline.cgColor
|
||||
}
|
||||
|
||||
addSubview(contentView)
|
||||
contentView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
}
|
||||
}
|
||||
82
suixinkan/UI/Common/AppStatusBadge.swift
Normal file
82
suixinkan/UI/Common/AppStatusBadge.swift
Normal file
@ -0,0 +1,82 @@
|
||||
//
|
||||
// AppStatusBadge.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import SnapKit
|
||||
import UIKit
|
||||
|
||||
/// 统一状态标签,合并订单 / 个人信息等 badge 配色逻辑。
|
||||
final class AppStatusBadge: UIView {
|
||||
|
||||
/// 语义色调。
|
||||
enum Tone {
|
||||
case info
|
||||
case success
|
||||
case warning
|
||||
case danger
|
||||
case neutral
|
||||
}
|
||||
|
||||
private let label = UILabel()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
AppFont.captionMedium.apply(to: label)
|
||||
label.textAlignment = .center
|
||||
addSubview(label)
|
||||
label.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(
|
||||
UIEdgeInsets(
|
||||
top: AppSpacing.xxs,
|
||||
left: AppSpacing.xs,
|
||||
bottom: AppSpacing.xxs,
|
||||
right: AppSpacing.xs
|
||||
)
|
||||
)
|
||||
}
|
||||
layer.cornerRadius = AppRadius.xs
|
||||
clipsToBounds = true
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
/// 按语义色调与文案刷新展示。
|
||||
func apply(tone: Tone, text: String) {
|
||||
label.text = text
|
||||
switch tone {
|
||||
case .info:
|
||||
label.textColor = AppColor.info
|
||||
backgroundColor = AppColor.infoBackground
|
||||
case .success:
|
||||
label.textColor = AppColor.success
|
||||
backgroundColor = AppColor.successBackground
|
||||
case .warning:
|
||||
label.textColor = AppColor.warning
|
||||
backgroundColor = AppColor.warningBackground
|
||||
case .danger:
|
||||
label.textColor = AppColor.danger
|
||||
backgroundColor = AppColor.dangerBackground
|
||||
case .neutral:
|
||||
label.textColor = AppColor.textTabInactive
|
||||
backgroundColor = AppColor.inputBackground
|
||||
}
|
||||
}
|
||||
|
||||
/// 订单状态映射(对齐 Android OrderView)。
|
||||
func applyOrderStatus(_ status: Int, text: String) {
|
||||
switch status {
|
||||
case 18, 20:
|
||||
apply(tone: .info, text: text)
|
||||
case 30:
|
||||
apply(tone: .success, text: text)
|
||||
case 50:
|
||||
apply(tone: .danger, text: text)
|
||||
default:
|
||||
apply(tone: .warning, text: text)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user