'update'
This commit is contained in:
52
ipad_app/Sources/Views/Components/BubbleMetricsView.swift
Normal file
52
ipad_app/Sources/Views/Components/BubbleMetricsView.swift
Normal file
@@ -0,0 +1,52 @@
|
||||
#if os(iOS)
|
||||
import SwiftUI
|
||||
|
||||
@available(macOS 10.15, iOS 13.0, *)
|
||||
struct BubbleMetric: Identifiable {
|
||||
let id = UUID()
|
||||
let label: String
|
||||
let display: String
|
||||
let valueMinutes: Double // 用于相对半径
|
||||
let color: Color
|
||||
}
|
||||
|
||||
@available(macOS 10.15, iOS 13.0, *)
|
||||
struct BubbleMetricsView: View {
|
||||
let metrics: [BubbleMetric]
|
||||
|
||||
private func radius(for v: Double, maxV: Double) -> CGFloat {
|
||||
guard maxV > 0 else { return 20 }
|
||||
let norm = sqrt(v / maxV)
|
||||
return 30 + norm * 70
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geo in
|
||||
let maxV = metrics.map { $0.valueMinutes }.max() ?? 1
|
||||
ZStack {
|
||||
ForEach(Array(metrics.enumerated()), id: \.[1].id) { idx, m in
|
||||
// 简单环形布局
|
||||
let angle = Double(idx) / Double(metrics.count) * Double.pi * 2
|
||||
let R = min(geo.size.width, geo.size.height) / 2 - 80
|
||||
let x = geo.size.width/2 + CGFloat(cos(angle)) * R
|
||||
let y = geo.size.height/2 + CGFloat(sin(angle)) * R
|
||||
let r = radius(for: m.valueMinutes, maxV: maxV)
|
||||
Circle()
|
||||
.fill(m.color.opacity(0.75))
|
||||
.frame(width: r, height: r)
|
||||
.overlay(
|
||||
VStack(spacing:4){
|
||||
Text(m.display).font(.system(size: min(18, r*0.28))).bold().foregroundColor(.white)
|
||||
Text(m.label).font(.system(size: min(14, r*0.22))).foregroundColor(.white)
|
||||
}.padding(4)
|
||||
)
|
||||
.position(x: x, y: y)
|
||||
.shadow(radius: 4, y: 2)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
}
|
||||
.frame(height: 340)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
19
ipad_app/Sources/Views/Components/EmptyStateView.swift
Normal file
19
ipad_app/Sources/Views/Components/EmptyStateView.swift
Normal file
@@ -0,0 +1,19 @@
|
||||
#if os(iOS)
|
||||
import SwiftUI
|
||||
|
||||
struct EmptyStateView: View {
|
||||
let message: String
|
||||
let actionTitle: String
|
||||
let action: () -> Void
|
||||
var body: some View {
|
||||
VStack(spacing: 16) {
|
||||
Image(systemName: "tray")
|
||||
.font(.system(size: 48))
|
||||
.foregroundColor(.secondary)
|
||||
Text(message).foregroundColor(.secondary)
|
||||
Button(actionTitle, action: action)
|
||||
}
|
||||
.padding(40)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user