引入统一设计令牌并迁移首页、订单和数据 UI
This commit is contained in:
@ -13,7 +13,7 @@ class BaseViewController: UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
view.backgroundColor = .systemBackground
|
||||
view.backgroundColor = AppColor.pageBackground
|
||||
setupNavigationBar()
|
||||
setupUI()
|
||||
setupConstraints()
|
||||
@ -61,14 +61,14 @@ class BaseViewController: UIViewController {
|
||||
|
||||
let container = UIView()
|
||||
container.backgroundColor = UIColor.black.withAlphaComponent(0.8)
|
||||
container.layer.cornerRadius = 8
|
||||
container.layer.cornerRadius = AppRadius.sm
|
||||
container.clipsToBounds = true
|
||||
container.alpha = 0
|
||||
|
||||
let label = UILabel()
|
||||
label.text = message
|
||||
label.textColor = .white
|
||||
label.font = .systemFont(ofSize: 14)
|
||||
label.font = .app(.body)
|
||||
label.textAlignment = .center
|
||||
label.numberOfLines = 0
|
||||
|
||||
|
||||
@ -16,6 +16,8 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
) {
|
||||
guard let windowScene = scene as? UIWindowScene else { return }
|
||||
|
||||
AppNavigationBarAppearance.applyGlobalAppearance()
|
||||
|
||||
let window = UIWindow(windowScene: windowScene)
|
||||
window.rootViewController = AppRouter.makeRootViewController()
|
||||
window.makeKeyAndVisible()
|
||||
|
||||
@ -5,15 +5,56 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 应用主题色,与 Android `theme/Color.kt` 对齐。
|
||||
/// 应用语义色,与 Android `theme/Color.kt` 及 `ScenicQueueTokens` 对齐。
|
||||
enum AppColor {
|
||||
|
||||
static let primary = UIColor(red: 0 / 255, green: 115 / 255, blue: 255 / 255, alpha: 1)
|
||||
static let text333 = UIColor(red: 51 / 255, green: 51 / 255, blue: 51 / 255, alpha: 1)
|
||||
static let text666 = UIColor(red: 102 / 255, green: 102 / 255, blue: 102 / 255, alpha: 1)
|
||||
static let agreementLink = UIColor(red: 32 / 255, green: 139 / 255, blue: 255 / 255, alpha: 1)
|
||||
static let inputBackground = UIColor(red: 244 / 255, green: 244 / 255, blue: 244 / 255, alpha: 1)
|
||||
static let secondaryButtonBackground = UIColor(red: 239 / 255, green: 246 / 255, blue: 255 / 255, alpha: 1)
|
||||
static let buttonDisabled = UIColor(red: 192 / 255, green: 192 / 255, blue: 192 / 255, alpha: 1)
|
||||
// MARK: - Brand
|
||||
|
||||
static let primary = UIColor(hex: 0x0073FF)
|
||||
static let primaryBanner = UIColor(hex: 0x1677FF)
|
||||
static let primaryLight = UIColor(hex: 0xEFF6FF)
|
||||
|
||||
// MARK: - Background
|
||||
|
||||
static let pageBackground = UIColor(hex: 0xF5F5F5)
|
||||
static let pageBackgroundSoft = UIColor(hex: 0xF7FAFF)
|
||||
static let cardBackground = UIColor.white
|
||||
static let inputBackground = UIColor(hex: 0xF4F4F4)
|
||||
|
||||
// MARK: - Border
|
||||
|
||||
static let border = UIColor(hex: 0xEEEEEE)
|
||||
static let cardOutline = UIColor(hex: 0xE9ECEF)
|
||||
|
||||
// MARK: - Text
|
||||
|
||||
static let textPrimary = UIColor(hex: 0x333333)
|
||||
static let textSecondary = UIColor(hex: 0x666666)
|
||||
static let textTertiary = UIColor(hex: 0x999999)
|
||||
static let textTabInactive = UIColor(hex: 0x7D8DA3)
|
||||
|
||||
// MARK: - Semantic
|
||||
|
||||
static let success = UIColor(hex: 0x10B981)
|
||||
static let successBackground = UIColor(hex: 0xF0FDF4)
|
||||
static let warning = UIColor(hex: 0xFF7B00)
|
||||
static let warningBackground = UIColor(hex: 0xFFF0E2)
|
||||
static let danger = UIColor(hex: 0xEF4444)
|
||||
static let dangerBackground = UIColor(hex: 0xFFE7E7)
|
||||
static let info = UIColor(hex: 0x0073FF)
|
||||
static let infoBackground = UIColor(hex: 0xE8F4FF)
|
||||
static let online = UIColor(hex: 0x22C55E)
|
||||
|
||||
// MARK: - Overlay
|
||||
|
||||
static let overlayScrim = UIColor.black.withAlphaComponent(0.2)
|
||||
|
||||
// MARK: - Legacy aliases(逐步迁移后移除)
|
||||
|
||||
static let text333 = textPrimary
|
||||
static let text666 = textSecondary
|
||||
static let agreementLink = UIColor(hex: 0x208BFF)
|
||||
static let secondaryButtonBackground = primaryLight
|
||||
static let buttonDisabled = UIColor(hex: 0xC0C0C0)
|
||||
static let placeholder = UIColor.gray
|
||||
}
|
||||
|
||||
54
suixinkan/Theme/AppFont.swift
Normal file
54
suixinkan/Theme/AppFont.swift
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// AppFont.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 应用字体层级,基于 8pt 网格与 SF Pro(System)。
|
||||
enum AppFont {
|
||||
|
||||
case caption
|
||||
case captionMedium
|
||||
case body
|
||||
case bodyMedium
|
||||
case subtitle
|
||||
case title
|
||||
case metric
|
||||
case display
|
||||
|
||||
/// 对应 UIFont。
|
||||
var uiFont: UIFont {
|
||||
switch self {
|
||||
case .caption:
|
||||
return .systemFont(ofSize: 12, weight: .regular)
|
||||
case .captionMedium:
|
||||
return .systemFont(ofSize: 12, weight: .medium)
|
||||
case .body:
|
||||
return .systemFont(ofSize: 14, weight: .regular)
|
||||
case .bodyMedium:
|
||||
return .systemFont(ofSize: 14, weight: .medium)
|
||||
case .subtitle:
|
||||
return .systemFont(ofSize: 16, weight: .medium)
|
||||
case .title:
|
||||
return .systemFont(ofSize: 16, weight: .bold)
|
||||
case .metric:
|
||||
return .systemFont(ofSize: 18, weight: .bold)
|
||||
case .display:
|
||||
return .systemFont(ofSize: 28, weight: .semibold)
|
||||
}
|
||||
}
|
||||
|
||||
/// 将字体应用到 UILabel。
|
||||
func apply(to label: UILabel) {
|
||||
label.font = uiFont
|
||||
}
|
||||
}
|
||||
|
||||
extension UIFont {
|
||||
|
||||
/// 通过 `AppFont` 获取系统字体。
|
||||
static func app(_ style: AppFont) -> UIFont {
|
||||
style.uiFont
|
||||
}
|
||||
}
|
||||
28
suixinkan/Theme/AppNavigationBarAppearance.swift
Normal file
28
suixinkan/Theme/AppNavigationBarAppearance.swift
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// AppNavigationBarAppearance.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 全局 UINavigationBar 外观配置。
|
||||
enum AppNavigationBarAppearance {
|
||||
|
||||
/// 应用标准导航栏样式(白底、无 shadow、主色标题)。
|
||||
static func applyGlobalAppearance() {
|
||||
let appearance = UINavigationBarAppearance()
|
||||
appearance.configureWithOpaqueBackground()
|
||||
appearance.backgroundColor = AppColor.cardBackground
|
||||
appearance.shadowColor = .clear
|
||||
appearance.titleTextAttributes = [
|
||||
.foregroundColor: AppColor.textPrimary,
|
||||
.font: UIFont.app(.title),
|
||||
]
|
||||
|
||||
let navigationBar = UINavigationBar.appearance()
|
||||
navigationBar.standardAppearance = appearance
|
||||
navigationBar.scrollEdgeAppearance = appearance
|
||||
navigationBar.compactAppearance = appearance
|
||||
navigationBar.tintColor = AppColor.primary
|
||||
}
|
||||
}
|
||||
20
suixinkan/Theme/AppRadius.swift
Normal file
20
suixinkan/Theme/AppRadius.swift
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// AppRadius.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import CoreGraphics
|
||||
|
||||
/// 应用圆角常量,与 Android ScenicQueueTokens 近似对齐。
|
||||
enum AppRadius {
|
||||
|
||||
static let xs: CGFloat = 4
|
||||
static let sm: CGFloat = 8
|
||||
static let md: CGFloat = 10
|
||||
static let lg: CGFloat = 12
|
||||
static let xl: CGFloat = 16
|
||||
static let sheetTop: CGFloat = 14
|
||||
|
||||
/// 周期筛选 pill(Statistics)。
|
||||
static let pill: CGFloat = 18
|
||||
}
|
||||
18
suixinkan/Theme/AppShadow.swift
Normal file
18
suixinkan/Theme/AppShadow.swift
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// AppShadow.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
/// 轻量阴影,仅用于登录表单等浮层卡片。
|
||||
enum AppShadow {
|
||||
|
||||
/// 为 layer 应用标准卡片阴影(登录表单等)。
|
||||
static func applyCardShadow(to layer: CALayer) {
|
||||
layer.shadowColor = UIColor.black.cgColor
|
||||
layer.shadowOpacity = 0.08
|
||||
layer.shadowOffset = CGSize(width: 0, height: 4)
|
||||
layer.shadowRadius = 12
|
||||
}
|
||||
}
|
||||
33
suixinkan/Theme/AppSpacing.swift
Normal file
33
suixinkan/Theme/AppSpacing.swift
Normal file
@ -0,0 +1,33 @@
|
||||
//
|
||||
// AppSpacing.swift
|
||||
// suixinkan
|
||||
//
|
||||
|
||||
import CoreGraphics
|
||||
|
||||
/// 应用间距常量,基于 8pt 网格。
|
||||
enum AppSpacing {
|
||||
|
||||
static let xxs: CGFloat = 4
|
||||
static let xs: CGFloat = 8
|
||||
static let sm: CGFloat = 12
|
||||
static let md: CGFloat = 16
|
||||
static let lg: CGFloat = 24
|
||||
static let xl: CGFloat = 32
|
||||
static let xxl: CGFloat = 48
|
||||
|
||||
/// 屏幕水平内边距。
|
||||
static let screenHorizontalInset: CGFloat = md
|
||||
|
||||
/// 最小可点击区域(Apple HIG)。
|
||||
static let minTouchTarget: CGFloat = 44
|
||||
|
||||
/// 首页自定义 Header 高度。
|
||||
static let homeHeaderHeight: CGFloat = 52
|
||||
|
||||
/// 主按钮默认高度。
|
||||
static let buttonHeight: CGFloat = 46
|
||||
|
||||
/// 表单行默认高度。
|
||||
static let formRowHeight: CGFloat = 52
|
||||
}
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -30,10 +30,10 @@ final class HomeViewController: BaseViewController {
|
||||
}
|
||||
|
||||
override func setupUI() {
|
||||
view.backgroundColor = UIColor(hex: 0xF5F5F5)
|
||||
view.backgroundColor = AppColor.pageBackground
|
||||
|
||||
contentStack.axis = .vertical
|
||||
contentStack.spacing = 12
|
||||
contentStack.spacing = AppSpacing.sm
|
||||
|
||||
scrollView.showsVerticalScrollIndicator = false
|
||||
view.addSubview(scenicHeaderView)
|
||||
@ -51,15 +51,15 @@ final class HomeViewController: BaseViewController {
|
||||
scenicHeaderView.snp.makeConstraints { make in
|
||||
make.top.equalTo(view.safeAreaLayoutGuide)
|
||||
make.leading.trailing.equalToSuperview()
|
||||
make.height.equalTo(52)
|
||||
make.height.equalTo(AppSpacing.homeHeaderHeight)
|
||||
}
|
||||
scrollView.snp.makeConstraints { make in
|
||||
make.top.equalTo(scenicHeaderView.snp.bottom)
|
||||
make.leading.trailing.bottom.equalToSuperview()
|
||||
}
|
||||
contentStack.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(16)
|
||||
make.width.equalTo(scrollView.snp.width).offset(-32)
|
||||
make.edges.equalToSuperview().inset(AppSpacing.screenHorizontalInset)
|
||||
make.width.equalTo(scrollView.snp.width).offset(-AppSpacing.screenHorizontalInset * 2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -47,8 +47,8 @@ final class HomeCommonAppsGridView: UIView {
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
titleLabel.text = "常用应用"
|
||||
titleLabel.font = .systemFont(ofSize: 16, weight: .bold)
|
||||
titleLabel.textColor = AppColor.text333
|
||||
titleLabel.font = .app(.title)
|
||||
titleLabel.textColor = AppColor.textPrimary
|
||||
|
||||
collectionView.backgroundColor = .clear
|
||||
collectionView.delegate = self
|
||||
@ -61,7 +61,7 @@ final class HomeCommonAppsGridView: UIView {
|
||||
make.top.leading.trailing.equalToSuperview()
|
||||
}
|
||||
collectionView.snp.makeConstraints { make in
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(12)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(AppSpacing.sm)
|
||||
make.leading.trailing.bottom.equalToSuperview()
|
||||
make.height.equalTo(88)
|
||||
}
|
||||
@ -101,8 +101,8 @@ final class HomeMenuCell: UICollectionViewCell {
|
||||
iconView.tintColor = AppColor.primary
|
||||
iconView.contentMode = .scaleAspectFit
|
||||
|
||||
titleLabel.font = .systemFont(ofSize: 12)
|
||||
titleLabel.textColor = AppColor.text333
|
||||
titleLabel.font = .app(.caption)
|
||||
titleLabel.textColor = AppColor.textPrimary
|
||||
titleLabel.textAlignment = .center
|
||||
titleLabel.numberOfLines = 2
|
||||
|
||||
@ -110,13 +110,13 @@ final class HomeMenuCell: UICollectionViewCell {
|
||||
contentView.addSubview(titleLabel)
|
||||
|
||||
iconView.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(8)
|
||||
make.top.equalToSuperview().offset(AppSpacing.xs)
|
||||
make.centerX.equalToSuperview()
|
||||
make.width.height.equalTo(28)
|
||||
}
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(iconView.snp.bottom).offset(8)
|
||||
make.leading.trailing.equalToSuperview().inset(4)
|
||||
make.top.equalTo(iconView.snp.bottom).offset(AppSpacing.xs)
|
||||
make.leading.trailing.equalToSuperview().inset(AppSpacing.xxs)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -17,23 +17,23 @@ final class HomeLocationReportCardView: UIView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
backgroundColor = .white
|
||||
layer.cornerRadius = 10
|
||||
backgroundColor = AppColor.cardBackground
|
||||
layer.cornerRadius = AppRadius.md
|
||||
|
||||
titleLabel.text = "位置上报"
|
||||
titleLabel.font = .systemFont(ofSize: 16, weight: .semibold)
|
||||
titleLabel.textColor = AppColor.text333
|
||||
titleLabel.font = .app(.title)
|
||||
titleLabel.textColor = AppColor.textPrimary
|
||||
|
||||
addressLabel.font = .systemFont(ofSize: 13)
|
||||
addressLabel.textColor = AppColor.text666
|
||||
addressLabel.font = .app(.body)
|
||||
addressLabel.textColor = AppColor.textSecondary
|
||||
addressLabel.numberOfLines = 2
|
||||
|
||||
reportButton.setTitle("立即上报", for: .normal)
|
||||
reportButton.setTitleColor(.white, for: .normal)
|
||||
reportButton.backgroundColor = AppColor.primary
|
||||
reportButton.layer.cornerRadius = 6
|
||||
reportButton.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium)
|
||||
reportButton.contentEdgeInsets = UIEdgeInsets(top: 8, left: 14, bottom: 8, right: 14)
|
||||
reportButton.layer.cornerRadius = AppRadius.sm
|
||||
reportButton.titleLabel?.font = .app(.bodyMedium)
|
||||
reportButton.contentEdgeInsets = UIEdgeInsets(top: AppSpacing.xs, left: 14, bottom: AppSpacing.xs, right: 14)
|
||||
reportButton.addTarget(self, action: #selector(reportTapped), for: .touchUpInside)
|
||||
|
||||
addSubview(titleLabel)
|
||||
@ -41,16 +41,16 @@ final class HomeLocationReportCardView: UIView {
|
||||
addSubview(reportButton)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.top.leading.equalToSuperview().offset(15)
|
||||
make.top.leading.equalToSuperview().offset(AppSpacing.screenHorizontalInset)
|
||||
}
|
||||
addressLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(8)
|
||||
make.leading.equalToSuperview().offset(15)
|
||||
make.bottom.equalToSuperview().offset(-15)
|
||||
make.trailing.lessThanOrEqualTo(reportButton.snp.leading).offset(-12)
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(AppSpacing.xs)
|
||||
make.leading.equalToSuperview().offset(AppSpacing.screenHorizontalInset)
|
||||
make.bottom.equalToSuperview().offset(-AppSpacing.screenHorizontalInset)
|
||||
make.trailing.lessThanOrEqualTo(reportButton.snp.leading).offset(-AppSpacing.sm)
|
||||
}
|
||||
reportButton.snp.makeConstraints { make in
|
||||
make.trailing.equalToSuperview().offset(-15)
|
||||
make.trailing.equalToSuperview().offset(-AppSpacing.screenHorizontalInset)
|
||||
make.centerY.equalToSuperview()
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ final class HomeQuickActionsView: UIView {
|
||||
super.init(frame: frame)
|
||||
stackView.axis = .horizontal
|
||||
stackView.distribution = .fillEqually
|
||||
stackView.spacing = 12
|
||||
stackView.spacing = AppSpacing.sm
|
||||
addSubview(stackView)
|
||||
stackView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
@ -45,8 +45,8 @@ final class HomeQuickActionsView: UIView {
|
||||
|
||||
private func makeActionButton(title: String, icon: String, action: Selector) -> UIView {
|
||||
let container = UIView()
|
||||
container.backgroundColor = .white
|
||||
container.layer.cornerRadius = 10
|
||||
container.backgroundColor = AppColor.cardBackground
|
||||
container.layer.cornerRadius = AppRadius.md
|
||||
|
||||
let button = UIButton(type: .system)
|
||||
button.addTarget(self, action: action, for: .touchUpInside)
|
||||
@ -61,8 +61,8 @@ final class HomeQuickActionsView: UIView {
|
||||
|
||||
let label = UILabel()
|
||||
label.text = title
|
||||
label.font = .systemFont(ofSize: 13, weight: .medium)
|
||||
label.textColor = AppColor.text333
|
||||
label.font = .app(.bodyMedium)
|
||||
label.textColor = AppColor.textPrimary
|
||||
label.textAlignment = .center
|
||||
|
||||
let column = UIStackView(arrangedSubviews: [imageView, label])
|
||||
|
||||
@ -16,22 +16,22 @@ final class HomeScenicHeaderView: UIView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
backgroundColor = .white
|
||||
titleLabel.font = .systemFont(ofSize: 16, weight: .medium)
|
||||
titleLabel.textColor = AppColor.text333
|
||||
arrowView.tintColor = AppColor.text666
|
||||
backgroundColor = AppColor.cardBackground
|
||||
titleLabel.font = .app(.subtitle)
|
||||
titleLabel.textColor = AppColor.textPrimary
|
||||
arrowView.tintColor = AppColor.textSecondary
|
||||
arrowView.contentMode = .scaleAspectFit
|
||||
|
||||
addSubview(titleLabel)
|
||||
addSubview(arrowView)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.leading.equalToSuperview().offset(16)
|
||||
make.leading.equalToSuperview().offset(AppSpacing.screenHorizontalInset)
|
||||
make.centerY.equalToSuperview()
|
||||
make.trailing.lessThanOrEqualTo(arrowView.snp.leading).offset(-8)
|
||||
make.trailing.lessThanOrEqualTo(arrowView.snp.leading).offset(-AppSpacing.xs)
|
||||
}
|
||||
arrowView.snp.makeConstraints { make in
|
||||
make.trailing.equalToSuperview().offset(-16)
|
||||
make.trailing.equalToSuperview().offset(-AppSpacing.screenHorizontalInset)
|
||||
make.centerY.equalToSuperview()
|
||||
make.width.height.equalTo(16)
|
||||
}
|
||||
|
||||
@ -15,17 +15,17 @@ final class HomeStoreCardView: UIView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
backgroundColor = .white
|
||||
layer.cornerRadius = 10
|
||||
backgroundColor = AppColor.cardBackground
|
||||
layer.cornerRadius = AppRadius.md
|
||||
|
||||
nameLabel.font = .systemFont(ofSize: 16, weight: .semibold)
|
||||
nameLabel.textColor = AppColor.text333
|
||||
nameLabel.font = .app(.title)
|
||||
nameLabel.textColor = AppColor.textPrimary
|
||||
|
||||
addressLabel.font = .systemFont(ofSize: 13)
|
||||
addressLabel.textColor = AppColor.text666
|
||||
addressLabel.font = .app(.body)
|
||||
addressLabel.textColor = AppColor.textSecondary
|
||||
addressLabel.numberOfLines = 2
|
||||
|
||||
statusLabel.font = .systemFont(ofSize: 12, weight: .medium)
|
||||
statusLabel.font = .app(.captionMedium)
|
||||
statusLabel.textColor = AppColor.primary
|
||||
|
||||
addSubview(nameLabel)
|
||||
@ -33,17 +33,17 @@ final class HomeStoreCardView: UIView {
|
||||
addSubview(statusLabel)
|
||||
|
||||
nameLabel.snp.makeConstraints { make in
|
||||
make.top.leading.equalToSuperview().offset(15)
|
||||
make.trailing.lessThanOrEqualTo(statusLabel.snp.leading).offset(-8)
|
||||
make.top.leading.equalToSuperview().offset(AppSpacing.screenHorizontalInset)
|
||||
make.trailing.lessThanOrEqualTo(statusLabel.snp.leading).offset(-AppSpacing.xs)
|
||||
}
|
||||
statusLabel.snp.makeConstraints { make in
|
||||
make.top.equalToSuperview().offset(15)
|
||||
make.trailing.equalToSuperview().offset(-15)
|
||||
make.top.equalToSuperview().offset(AppSpacing.screenHorizontalInset)
|
||||
make.trailing.equalToSuperview().offset(-AppSpacing.screenHorizontalInset)
|
||||
}
|
||||
addressLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(nameLabel.snp.bottom).offset(8)
|
||||
make.leading.trailing.equalToSuperview().inset(15)
|
||||
make.bottom.equalToSuperview().offset(-15)
|
||||
make.top.equalTo(nameLabel.snp.bottom).offset(AppSpacing.xs)
|
||||
make.leading.trailing.equalToSuperview().inset(AppSpacing.screenHorizontalInset)
|
||||
make.bottom.equalToSuperview().offset(-AppSpacing.screenHorizontalInset)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,18 +18,18 @@ final class HomeWorkStatusCardView: UIView {
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
backgroundColor = .white
|
||||
layer.cornerRadius = 10
|
||||
backgroundColor = AppColor.cardBackground
|
||||
layer.cornerRadius = AppRadius.md
|
||||
|
||||
onlineButton.titleLabel?.font = .systemFont(ofSize: 12, weight: .medium)
|
||||
onlineButton.layer.cornerRadius = 4
|
||||
onlineButton.titleLabel?.font = .app(.captionMedium)
|
||||
onlineButton.layer.cornerRadius = AppRadius.xs
|
||||
onlineButton.contentEdgeInsets = UIEdgeInsets(top: 6, left: 12, bottom: 6, right: 12)
|
||||
onlineButton.addTarget(self, action: #selector(onlineTapped), for: .touchUpInside)
|
||||
|
||||
countdownLabel.font = .systemFont(ofSize: 16, weight: .medium)
|
||||
countdownLabel.font = .app(.subtitle)
|
||||
countdownLabel.textColor = AppColor.primary
|
||||
|
||||
reminderButton.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
|
||||
reminderButton.titleLabel?.font = .app(.subtitle)
|
||||
reminderButton.setTitleColor(AppColor.primary, for: .normal)
|
||||
reminderButton.addTarget(self, action: #selector(reminderTapped), for: .touchUpInside)
|
||||
|
||||
@ -38,18 +38,18 @@ final class HomeWorkStatusCardView: UIView {
|
||||
addSubview(reminderButton)
|
||||
|
||||
onlineButton.snp.makeConstraints { make in
|
||||
make.leading.equalToSuperview().offset(15)
|
||||
make.leading.equalToSuperview().offset(AppSpacing.screenHorizontalInset)
|
||||
make.centerY.equalToSuperview()
|
||||
}
|
||||
countdownLabel.snp.makeConstraints { make in
|
||||
make.center.equalToSuperview()
|
||||
}
|
||||
reminderButton.snp.makeConstraints { make in
|
||||
make.trailing.equalToSuperview().offset(-15)
|
||||
make.trailing.equalToSuperview().offset(-AppSpacing.screenHorizontalInset)
|
||||
make.centerY.equalToSuperview()
|
||||
}
|
||||
snp.makeConstraints { make in
|
||||
make.height.equalTo(52)
|
||||
make.height.equalTo(AppSpacing.formRowHeight)
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,11 +61,11 @@ final class HomeWorkStatusCardView: UIView {
|
||||
func apply(isOnline: Bool, countdownText: String, reminderMinutes: Int) {
|
||||
onlineButton.setTitle(isOnline ? "在线" : "离线", for: .normal)
|
||||
if isOnline {
|
||||
onlineButton.backgroundColor = UIColor(hex: 0x22C55E)
|
||||
onlineButton.setTitleColor(UIColor(hex: 0xF0FDF4), for: .normal)
|
||||
onlineButton.backgroundColor = AppColor.online
|
||||
onlineButton.setTitleColor(AppColor.successBackground, for: .normal)
|
||||
} else {
|
||||
onlineButton.backgroundColor = UIColor(hex: 0xF4F4F4)
|
||||
onlineButton.setTitleColor(UIColor(hex: 0x7B8EAA), for: .normal)
|
||||
onlineButton.backgroundColor = AppColor.inputBackground
|
||||
onlineButton.setTitleColor(AppColor.textTabInactive, for: .normal)
|
||||
}
|
||||
countdownLabel.text = countdownText
|
||||
let reminderTitle = reminderMinutes == 0 ? "不提醒" : "提前\(reminderMinutes)分钟"
|
||||
|
||||
@ -67,21 +67,21 @@ final class MainTabBarController: UITabBarController {
|
||||
|
||||
private func configureTabBarAppearance() {
|
||||
tabBar.tintColor = AppColor.primary
|
||||
tabBar.backgroundColor = .white
|
||||
tabBar.backgroundColor = AppColor.cardBackground
|
||||
tabBar.shadowImage = UIImage()
|
||||
|
||||
let normalAttributes: [NSAttributedString.Key: Any] = [
|
||||
.foregroundColor: UIColor(hex: 0x7D8DA3),
|
||||
.font: UIFont.systemFont(ofSize: 12, weight: .regular),
|
||||
.foregroundColor: AppColor.textTabInactive,
|
||||
.font: UIFont.app(.caption),
|
||||
]
|
||||
let selectedAttributes: [NSAttributedString.Key: Any] = [
|
||||
.foregroundColor: AppColor.primary,
|
||||
.font: UIFont.systemFont(ofSize: 12, weight: .medium),
|
||||
.font: UIFont.app(.captionMedium),
|
||||
]
|
||||
|
||||
let appearance = UITabBarAppearance()
|
||||
appearance.configureWithOpaqueBackground()
|
||||
appearance.backgroundColor = .white
|
||||
appearance.backgroundColor = AppColor.cardBackground
|
||||
appearance.shadowColor = .clear
|
||||
appearance.stackedLayoutAppearance.normal.titleTextAttributes = normalAttributes
|
||||
appearance.stackedLayoutAppearance.selected.titleTextAttributes = selectedAttributes
|
||||
|
||||
@ -107,34 +107,34 @@ final class OrderCardCell: UITableViewCell {
|
||||
}
|
||||
|
||||
private func setupUI() {
|
||||
cardView.backgroundColor = .white
|
||||
cardView.layer.cornerRadius = 12
|
||||
cardView.backgroundColor = AppColor.cardBackground
|
||||
cardView.layer.cornerRadius = AppRadius.lg
|
||||
|
||||
orderNumberLabel.font = .systemFont(ofSize: 14)
|
||||
orderNumberLabel.textColor = .black
|
||||
createdAtLabel.font = .systemFont(ofSize: 12)
|
||||
createdAtLabel.textColor = UIColor(hex: 0x6B7280)
|
||||
typeChip.font = .systemFont(ofSize: 12)
|
||||
orderNumberLabel.font = .app(.body)
|
||||
orderNumberLabel.textColor = AppColor.textPrimary
|
||||
createdAtLabel.font = .app(.caption)
|
||||
createdAtLabel.textColor = AppColor.textSecondary
|
||||
typeChip.font = .app(.caption)
|
||||
typeChip.textColor = AppColor.primary
|
||||
typeChip.backgroundColor = UIColor(hex: 0xEFF6FF)
|
||||
typeChip.layer.cornerRadius = 4
|
||||
typeChip.backgroundColor = AppColor.primaryLight
|
||||
typeChip.layer.cornerRadius = AppRadius.xs
|
||||
typeChip.clipsToBounds = true
|
||||
typeChip.textAlignment = .center
|
||||
|
||||
configureActionButton(refundButton, title: "退款", color: UIColor(hex: 0xEF4444), bg: UIColor(hex: 0xFFE7E7))
|
||||
configureActionButton(verifyButton, title: "核销订单", color: .white, bg: UIColor(hex: 0x0073FF))
|
||||
configureActionButton(refundButton, title: "退款", color: AppColor.danger, bg: AppColor.dangerBackground)
|
||||
configureActionButton(verifyButton, title: "核销订单", color: .white, bg: AppColor.primary)
|
||||
refundButton.addTarget(self, action: #selector(refundTapped), for: .touchUpInside)
|
||||
verifyButton.addTarget(self, action: #selector(verifyTapped), for: .touchUpInside)
|
||||
|
||||
uploadTaskButton.setTitle("上传任务", for: .normal)
|
||||
uploadTaskButton.setTitleColor(AppColor.primary, for: .normal)
|
||||
uploadTaskButton.titleLabel?.font = .systemFont(ofSize: 16)
|
||||
uploadTaskButton.backgroundColor = UIColor(hex: 0xEFF6FF)
|
||||
uploadTaskButton.layer.cornerRadius = 12
|
||||
uploadTaskButton.titleLabel?.font = .app(.subtitle)
|
||||
uploadTaskButton.backgroundColor = AppColor.primaryLight
|
||||
uploadTaskButton.layer.cornerRadius = AppRadius.lg
|
||||
uploadTaskButton.addTarget(self, action: #selector(uploadTaskTapped), for: .touchUpInside)
|
||||
|
||||
actionStack.axis = .horizontal
|
||||
actionStack.spacing = 12
|
||||
actionStack.spacing = AppSpacing.sm
|
||||
actionStack.distribution = .fillEqually
|
||||
actionStack.addArrangedSubview(refundButton)
|
||||
actionStack.addArrangedSubview(verifyButton)
|
||||
@ -143,27 +143,27 @@ final class OrderCardCell: UITableViewCell {
|
||||
infoStack.spacing = 6
|
||||
|
||||
cancelButton.setTitle("取消订单", for: .normal)
|
||||
cancelButton.setTitleColor(UIColor(hex: 0xEF4444), for: .normal)
|
||||
cancelButton.titleLabel?.font = .systemFont(ofSize: 14)
|
||||
cancelButton.setTitleColor(AppColor.danger, for: .normal)
|
||||
cancelButton.titleLabel?.font = .app(.body)
|
||||
cancelButton.addTarget(self, action: #selector(cancelTapped), for: .touchUpInside)
|
||||
|
||||
orderSourceButton.setTitleColor(AppColor.primary, for: .normal)
|
||||
orderSourceButton.titleLabel?.font = .systemFont(ofSize: 14)
|
||||
orderSourceButton.titleLabel?.font = .app(.body)
|
||||
orderSourceButton.contentHorizontalAlignment = .leading
|
||||
orderSourceButton.addTarget(self, action: #selector(orderSourceTapped), for: .touchUpInside)
|
||||
|
||||
historicalButton.setTitle("历史拍摄", for: .normal)
|
||||
historicalButton.setTitleColor(AppColor.primary, for: .normal)
|
||||
historicalButton.titleLabel?.font = .systemFont(ofSize: 14)
|
||||
historicalButton.titleLabel?.font = .app(.body)
|
||||
historicalButton.addTarget(self, action: #selector(historicalTapped), for: .touchUpInside)
|
||||
|
||||
refinedStack.axis = .horizontal
|
||||
refinedStack.spacing = 8
|
||||
refinedStack.spacing = AppSpacing.xs
|
||||
refinedNeedButton.setTitle("需要精修", for: .normal)
|
||||
refinedNoButton.setTitle("无需精修", for: .normal)
|
||||
[refinedNeedButton, refinedNoButton].forEach {
|
||||
$0.titleLabel?.font = .systemFont(ofSize: 13)
|
||||
$0.layer.cornerRadius = 6
|
||||
$0.titleLabel?.font = .app(.body)
|
||||
$0.layer.cornerRadius = AppRadius.sm
|
||||
$0.layer.borderWidth = 1
|
||||
}
|
||||
refinedNeedButton.addTarget(self, action: #selector(refinedNeedTapped), for: .touchUpInside)
|
||||
@ -185,7 +185,7 @@ final class OrderCardCell: UITableViewCell {
|
||||
cardView.addSubview(cancelButton)
|
||||
|
||||
cardView.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 0, left: 16, bottom: 12, right: 16))
|
||||
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 0, left: AppSpacing.md, bottom: AppSpacing.sm, right: AppSpacing.md))
|
||||
}
|
||||
orderNumberLabel.snp.makeConstraints { make in
|
||||
make.top.leading.equalToSuperview().inset(16)
|
||||
@ -240,9 +240,9 @@ final class OrderCardCell: UITableViewCell {
|
||||
private func configureActionButton(_ button: UIButton, title: String, color: UIColor, bg: UIColor) {
|
||||
button.setTitle(title, for: .normal)
|
||||
button.setTitleColor(color, for: .normal)
|
||||
button.titleLabel?.font = .systemFont(ofSize: 16)
|
||||
button.titleLabel?.font = .app(.subtitle)
|
||||
button.backgroundColor = bg
|
||||
button.layer.cornerRadius = 8
|
||||
button.layer.cornerRadius = AppRadius.sm
|
||||
}
|
||||
|
||||
private func addInfoRow(title: String, value: String) {
|
||||
@ -251,12 +251,12 @@ final class OrderCardCell: UITableViewCell {
|
||||
row.distribution = .fillEqually
|
||||
let titleLabel = UILabel()
|
||||
titleLabel.text = title
|
||||
titleLabel.font = .systemFont(ofSize: 13)
|
||||
titleLabel.textColor = UIColor(hex: 0x6B7280)
|
||||
titleLabel.font = .app(.body)
|
||||
titleLabel.textColor = AppColor.textSecondary
|
||||
let valueLabel = UILabel()
|
||||
valueLabel.text = value
|
||||
valueLabel.font = .systemFont(ofSize: 13)
|
||||
valueLabel.textColor = AppColor.text333
|
||||
valueLabel.font = .app(.body)
|
||||
valueLabel.textColor = AppColor.textPrimary
|
||||
valueLabel.textAlignment = .right
|
||||
row.addArrangedSubview(titleLabel)
|
||||
row.addArrangedSubview(valueLabel)
|
||||
@ -269,12 +269,12 @@ final class OrderCardCell: UITableViewCell {
|
||||
row.distribution = .fillEqually
|
||||
let titleLabel = UILabel()
|
||||
titleLabel.text = "手机号"
|
||||
titleLabel.font = .systemFont(ofSize: 13)
|
||||
titleLabel.textColor = UIColor(hex: 0x6B7280)
|
||||
titleLabel.font = .app(.body)
|
||||
titleLabel.textColor = AppColor.textSecondary
|
||||
let valueButton = UIButton(type: .system)
|
||||
valueButton.setTitle(OrderPhoneMask.mask(phone), for: .normal)
|
||||
valueButton.setTitleColor(AppColor.primary, for: .normal)
|
||||
valueButton.titleLabel?.font = .systemFont(ofSize: 13)
|
||||
valueButton.titleLabel?.font = .app(.body)
|
||||
valueButton.contentHorizontalAlignment = .trailing
|
||||
valueButton.isHidden = hidden || phone.isEmpty
|
||||
valueButton.addTarget(self, action: #selector(callTapped), for: .touchUpInside)
|
||||
@ -285,7 +285,7 @@ final class OrderCardCell: UITableViewCell {
|
||||
|
||||
private func updateRefinedButtons(isRefined: Int, readOnly: Bool) {
|
||||
let selectedBorder = AppColor.primary.cgColor
|
||||
let normalBorder = UIColor(hex: 0xE5E7EB).cgColor
|
||||
let normalBorder = AppColor.border.cgColor
|
||||
refinedNeedButton.layer.borderColor = isRefined == 1 ? selectedBorder : normalBorder
|
||||
refinedNoButton.layer.borderColor = isRefined == 2 ? selectedBorder : normalBorder
|
||||
refinedNeedButton.isEnabled = !readOnly
|
||||
|
||||
@ -6,20 +6,17 @@
|
||||
import SnapKit
|
||||
import UIKit
|
||||
|
||||
/// 订单状态标签。
|
||||
/// 订单状态标签,内部委托 `AppStatusBadge`。
|
||||
final class OrderStatusBadgeView: UIView {
|
||||
private let label = UILabel()
|
||||
|
||||
private let badge = AppStatusBadge()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
label.font = .systemFont(ofSize: 14, weight: .medium)
|
||||
label.textAlignment = .center
|
||||
addSubview(label)
|
||||
label.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 2, left: 4, bottom: 2, right: 4))
|
||||
addSubview(badge)
|
||||
badge.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
layer.cornerRadius = 4
|
||||
clipsToBounds = true
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
@ -28,20 +25,6 @@ final class OrderStatusBadgeView: UIView {
|
||||
}
|
||||
|
||||
func apply(status: Int, text: String) {
|
||||
label.text = text
|
||||
switch status {
|
||||
case 18, 20:
|
||||
label.textColor = UIColor(hex: 0x0073FF)
|
||||
backgroundColor = UIColor(hex: 0xEFF6FF)
|
||||
case 30:
|
||||
label.textColor = UIColor(hex: 0x10B981)
|
||||
backgroundColor = UIColor(hex: 0xF0FDF4)
|
||||
case 50:
|
||||
label.textColor = UIColor(hex: 0xEF4444)
|
||||
backgroundColor = UIColor(hex: 0xFFE7E7)
|
||||
default:
|
||||
label.textColor = UIColor(hex: 0xFF7B00)
|
||||
backgroundColor = UIColor(hex: 0xFFF0E2)
|
||||
}
|
||||
badge.applyOrderStatus(status, text: text)
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,6 @@ final class OrdersViewController: BaseViewController, UITableViewDataSource, UIT
|
||||
}
|
||||
|
||||
override func setupUI() {
|
||||
view.backgroundColor = UIColor(hex: 0xF5F5F5)
|
||||
view.addSubview(filterBar)
|
||||
view.addSubview(listView)
|
||||
listView.tableView.dataSource = self
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
import SnapKit
|
||||
import UIKit
|
||||
|
||||
/// 个人信息页状态标签,用于账号状态、审核状态等展示。
|
||||
/// 个人信息页状态标签,内部委托 `AppStatusBadge`。
|
||||
final class ProfileStatusBadgeView: UIView {
|
||||
|
||||
enum Style {
|
||||
@ -20,18 +20,14 @@ final class ProfileStatusBadgeView: UIView {
|
||||
case bankRejected
|
||||
}
|
||||
|
||||
private let label = UILabel()
|
||||
private let badge = AppStatusBadge()
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
label.font = .systemFont(ofSize: 12, weight: .medium)
|
||||
label.textAlignment = .center
|
||||
addSubview(label)
|
||||
label.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(UIEdgeInsets(top: 3, left: 8, bottom: 3, right: 8))
|
||||
addSubview(badge)
|
||||
badge.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview()
|
||||
}
|
||||
layer.cornerRadius = 4
|
||||
clipsToBounds = true
|
||||
}
|
||||
|
||||
@available(*, unavailable)
|
||||
@ -40,23 +36,15 @@ final class ProfileStatusBadgeView: UIView {
|
||||
}
|
||||
|
||||
func apply(style: Style, text: String) {
|
||||
label.text = text
|
||||
switch style {
|
||||
case .accountActive:
|
||||
label.textColor = UIColor(hex: 0x22C55E)
|
||||
backgroundColor = UIColor(hex: 0xF0FDF4)
|
||||
case .scenic:
|
||||
label.textColor = AppColor.primary
|
||||
backgroundColor = UIColor(hex: 0xEFF6FF)
|
||||
badge.apply(tone: .success, text: text)
|
||||
case .scenic, .auditApproved, .bankApproved:
|
||||
badge.apply(tone: .info, text: text)
|
||||
case .auditPending, .bankPending:
|
||||
label.textColor = UIColor(hex: 0xFF7B00)
|
||||
backgroundColor = UIColor(hex: 0xFFF0E2)
|
||||
case .auditApproved, .bankApproved:
|
||||
label.textColor = AppColor.primary
|
||||
backgroundColor = UIColor(hex: 0xEFF6FF)
|
||||
badge.apply(tone: .warning, text: text)
|
||||
case .auditRejected, .bankRejected:
|
||||
label.textColor = UIColor(hex: 0xEF4444)
|
||||
backgroundColor = UIColor(hex: 0xFFE7E7)
|
||||
badge.apply(tone: .danger, text: text)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,27 +47,27 @@ final class StatisticsDailyListView: UIView {
|
||||
}
|
||||
|
||||
private func setupUI() {
|
||||
backgroundColor = .white
|
||||
layer.cornerRadius = 12
|
||||
backgroundColor = AppColor.cardBackground
|
||||
layer.cornerRadius = AppRadius.lg
|
||||
clipsToBounds = true
|
||||
|
||||
titleLabel.text = "时间范围"
|
||||
titleLabel.font = .systemFont(ofSize: 14, weight: .bold)
|
||||
titleLabel.textColor = .black
|
||||
titleLabel.font = .app(.bodyMedium)
|
||||
titleLabel.textColor = AppColor.textPrimary
|
||||
|
||||
rangeButton.backgroundColor = UIColor(hex: 0xF4F4F4)
|
||||
rangeButton.layer.cornerRadius = 4
|
||||
rangeButton.backgroundColor = AppColor.inputBackground
|
||||
rangeButton.layer.cornerRadius = AppRadius.xs
|
||||
rangeButton.addTarget(self, action: #selector(rangeTapped), for: .touchUpInside)
|
||||
|
||||
rangeLabel.font = .systemFont(ofSize: 14)
|
||||
rangeLabel.textColor = UIColor(hex: 0x4B5563)
|
||||
rangeLabel.font = .app(.body)
|
||||
rangeLabel.textColor = AppColor.textSecondary
|
||||
rangeLabel.text = "今日"
|
||||
|
||||
arrowView.image = UIImage(systemName: "chevron.down")
|
||||
arrowView.tintColor = UIColor(hex: 0x4B5563)
|
||||
arrowView.tintColor = AppColor.textSecondary
|
||||
arrowView.contentMode = .scaleAspectFit
|
||||
|
||||
divider.backgroundColor = UIColor(hex: 0xF4F4F4)
|
||||
divider.backgroundColor = AppColor.inputBackground
|
||||
|
||||
tableView.backgroundColor = .clear
|
||||
tableView.separatorStyle = .none
|
||||
|
||||
@ -28,16 +28,16 @@ final class StatisticsPeriodButton: UIButton {
|
||||
}
|
||||
|
||||
private func setupUI() {
|
||||
titleLabel?.font = .systemFont(ofSize: 14, weight: .medium)
|
||||
layer.cornerRadius = 18
|
||||
titleLabel?.font = .app(.bodyMedium)
|
||||
layer.cornerRadius = AppRadius.pill
|
||||
clipsToBounds = true
|
||||
contentEdgeInsets = UIEdgeInsets(top: 6, left: 20, bottom: 6, right: 20)
|
||||
updateAppearance()
|
||||
}
|
||||
|
||||
private func updateAppearance() {
|
||||
backgroundColor = isSelected ? UIColor(hex: 0x3B82F6) : UIColor(hex: 0xF3F4F6)
|
||||
setTitleColor(isSelected ? .white : UIColor(hex: 0x4B5563), for: .normal)
|
||||
backgroundColor = isSelected ? AppColor.primary : AppColor.inputBackground
|
||||
setTitleColor(isSelected ? .white : AppColor.textSecondary, for: .normal)
|
||||
titleLabel?.font = .systemFont(ofSize: 14, weight: isSelected ? .semibold : .medium)
|
||||
}
|
||||
}
|
||||
|
||||
@ -32,13 +32,13 @@ final class StatisticsStatCardView: UIView {
|
||||
}
|
||||
|
||||
private func setupUI() {
|
||||
layer.cornerRadius = 12
|
||||
layer.cornerRadius = AppRadius.lg
|
||||
clipsToBounds = true
|
||||
|
||||
titleLabel.font = .systemFont(ofSize: 14)
|
||||
titleLabel.textColor = UIColor.black.withAlphaComponent(0.6)
|
||||
titleLabel.font = .app(.body)
|
||||
titleLabel.textColor = AppColor.textPrimary.withAlphaComponent(0.6)
|
||||
|
||||
valueLabel.font = .systemFont(ofSize: 18, weight: .bold)
|
||||
valueLabel.font = .app(.metric)
|
||||
valueLabel.numberOfLines = 1
|
||||
valueLabel.adjustsFontSizeToFitWidth = true
|
||||
valueLabel.minimumScaleFactor = 0.8
|
||||
@ -50,16 +50,16 @@ final class StatisticsStatCardView: UIView {
|
||||
addSubview(iconView)
|
||||
|
||||
titleLabel.snp.makeConstraints { make in
|
||||
make.top.leading.equalToSuperview().inset(12)
|
||||
make.trailing.lessThanOrEqualTo(iconView.snp.leading).offset(-8)
|
||||
make.top.leading.equalToSuperview().inset(AppSpacing.sm)
|
||||
make.trailing.lessThanOrEqualTo(iconView.snp.leading).offset(-AppSpacing.xs)
|
||||
}
|
||||
valueLabel.snp.makeConstraints { make in
|
||||
make.top.equalTo(titleLabel.snp.bottom).offset(3)
|
||||
make.leading.bottom.equalToSuperview().inset(12)
|
||||
make.trailing.lessThanOrEqualTo(iconView.snp.leading).offset(-8)
|
||||
make.leading.bottom.equalToSuperview().inset(AppSpacing.sm)
|
||||
make.trailing.lessThanOrEqualTo(iconView.snp.leading).offset(-AppSpacing.xs)
|
||||
}
|
||||
iconView.snp.makeConstraints { make in
|
||||
make.trailing.equalToSuperview().inset(8)
|
||||
make.trailing.equalToSuperview().inset(AppSpacing.xs)
|
||||
make.centerY.equalToSuperview()
|
||||
make.size.equalTo(48)
|
||||
}
|
||||
|
||||
@ -18,8 +18,8 @@ final class StatisticsSummaryCardView: UIView {
|
||||
|
||||
private let totalAmountCard = StatisticsStatCardView(
|
||||
title: "订单总金额",
|
||||
valueColor: UIColor(hex: 0x22C55E),
|
||||
backgroundColor: UIColor(hex: 0xF0FDF4),
|
||||
valueColor: AppColor.online,
|
||||
backgroundColor: AppColor.successBackground,
|
||||
iconName: "icon_data_statistics_total_amount"
|
||||
)
|
||||
private let totalOrderCard = StatisticsStatCardView(
|
||||
@ -30,20 +30,20 @@ final class StatisticsSummaryCardView: UIView {
|
||||
)
|
||||
private let receivedCard = StatisticsStatCardView(
|
||||
title: "实收金额",
|
||||
valueColor: UIColor(hex: 0x22C55E),
|
||||
backgroundColor: UIColor(hex: 0xFFF0E2),
|
||||
valueColor: AppColor.online,
|
||||
backgroundColor: AppColor.warningBackground,
|
||||
iconName: "icon_data_statistics_get_amount"
|
||||
)
|
||||
private let averageCard = StatisticsStatCardView(
|
||||
title: "客单价",
|
||||
valueColor: UIColor(hex: 0x0073FF),
|
||||
backgroundColor: UIColor(hex: 0xEFF6FF),
|
||||
valueColor: AppColor.primary,
|
||||
backgroundColor: AppColor.primaryLight,
|
||||
iconName: "icon_data_statistics_average_amount"
|
||||
)
|
||||
private let refundCard = StatisticsStatCardView(
|
||||
title: "退款金额",
|
||||
valueColor: UIColor(hex: 0xEF4444),
|
||||
backgroundColor: UIColor(hex: 0xFFE7E7),
|
||||
valueColor: AppColor.danger,
|
||||
backgroundColor: AppColor.dangerBackground,
|
||||
iconName: "icon_data_statistics_refund_amount"
|
||||
)
|
||||
|
||||
@ -69,15 +69,15 @@ final class StatisticsSummaryCardView: UIView {
|
||||
}
|
||||
|
||||
private func setupUI() {
|
||||
backgroundColor = .white
|
||||
layer.cornerRadius = 12
|
||||
backgroundColor = AppColor.cardBackground
|
||||
layer.cornerRadius = AppRadius.lg
|
||||
clipsToBounds = true
|
||||
|
||||
datePrefixLabel.text = "已选日期:"
|
||||
datePrefixLabel.font = .systemFont(ofSize: 14)
|
||||
datePrefixLabel.textColor = AppColor.text333
|
||||
datePrefixLabel.font = .app(.body)
|
||||
datePrefixLabel.textColor = AppColor.textPrimary
|
||||
|
||||
dateValueLabel.font = .systemFont(ofSize: 14)
|
||||
dateValueLabel.font = .app(.body)
|
||||
dateValueLabel.textColor = AppColor.primary
|
||||
dateValueLabel.numberOfLines = 1
|
||||
|
||||
@ -95,17 +95,17 @@ final class StatisticsSummaryCardView: UIView {
|
||||
|
||||
let row1 = UIStackView(arrangedSubviews: [totalOrderCard, receivedCard])
|
||||
row1.axis = .horizontal
|
||||
row1.spacing = 12
|
||||
row1.spacing = AppSpacing.sm
|
||||
row1.distribution = .fillEqually
|
||||
|
||||
let row2 = UIStackView(arrangedSubviews: [averageCard, refundCard])
|
||||
row2.axis = .horizontal
|
||||
row2.spacing = 12
|
||||
row2.spacing = AppSpacing.sm
|
||||
row2.distribution = .fillEqually
|
||||
|
||||
let cardStack = UIStackView(arrangedSubviews: [totalAmountCard, row1, row2])
|
||||
cardStack.axis = .vertical
|
||||
cardStack.spacing = 12
|
||||
cardStack.spacing = AppSpacing.sm
|
||||
|
||||
let dateRow = UIStackView(arrangedSubviews: [datePrefixLabel, dateValueLabel, UIView()])
|
||||
dateRow.axis = .horizontal
|
||||
@ -114,11 +114,11 @@ final class StatisticsSummaryCardView: UIView {
|
||||
|
||||
let contentStack = UIStackView(arrangedSubviews: [dateRow, periodStack, cardStack])
|
||||
contentStack.axis = .vertical
|
||||
contentStack.spacing = 12
|
||||
contentStack.spacing = AppSpacing.sm
|
||||
|
||||
addSubview(contentStack)
|
||||
contentStack.snp.makeConstraints { make in
|
||||
make.edges.equalToSuperview().inset(16)
|
||||
make.edges.equalToSuperview().inset(AppSpacing.md)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ final class StatisticsViewController: BaseViewController {
|
||||
}
|
||||
|
||||
override func setupUI() {
|
||||
view.backgroundColor = UIColor(hex: 0xF7FAFF)
|
||||
view.backgroundColor = AppColor.pageBackgroundSoft
|
||||
|
||||
view.addSubview(summaryCardView)
|
||||
view.addSubview(dailyListView)
|
||||
@ -31,13 +31,13 @@ final class StatisticsViewController: BaseViewController {
|
||||
|
||||
override func setupConstraints() {
|
||||
summaryCardView.snp.makeConstraints { make in
|
||||
make.top.equalTo(view.safeAreaLayoutGuide).offset(16)
|
||||
make.leading.trailing.equalToSuperview().inset(16)
|
||||
make.top.equalTo(view.safeAreaLayoutGuide).offset(AppSpacing.md)
|
||||
make.leading.trailing.equalToSuperview().inset(AppSpacing.screenHorizontalInset)
|
||||
}
|
||||
dailyListView.snp.makeConstraints { make in
|
||||
make.top.equalTo(summaryCardView.snp.bottom).offset(16)
|
||||
make.leading.trailing.equalToSuperview().inset(16)
|
||||
make.bottom.equalTo(view.safeAreaLayoutGuide).inset(16)
|
||||
make.top.equalTo(summaryCardView.snp.bottom).offset(AppSpacing.md)
|
||||
make.leading.trailing.equalToSuperview().inset(AppSpacing.screenHorizontalInset)
|
||||
make.bottom.equalTo(view.safeAreaLayoutGuide).inset(AppSpacing.md)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user