feat(ui): UI 骨架基线 — 3 Tab + RecordSheet + Quick/Archive 流程占位
替换 Xcode 默认模板: - 删除 ContentView/Item/__App - 新增 App/TijiApp(SwiftData ModelContainer)、RootView(3 Tab + RecordSheet) - DesignSystem:Tokens(色板/字体/圆角)+ Components(卡片/按钮/Chip) - Models:Indicator / Report / DiaryEntry @Model 初版 - Features:Home / Quick(A1-A3)/ Archive(B1-B5)/ Record / Trends / Me 静态 UI W2 AI 基座工作将在此基线上叠加。 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
124
体己/Features/Quick/A3BatchView.swift
Normal file
124
体己/Features/Quick/A3BatchView.swift
Normal file
@@ -0,0 +1,124 @@
|
||||
import SwiftUI
|
||||
|
||||
struct A3BatchItem {
|
||||
let name: String
|
||||
let value: String
|
||||
let unit: String
|
||||
let range: String
|
||||
let status: IndicatorStatus
|
||||
}
|
||||
|
||||
struct A3BatchView: View {
|
||||
var onAddMore: () -> Void
|
||||
var onFinish: () -> Void
|
||||
var onBack: () -> Void
|
||||
|
||||
let items: [A3BatchItem] = [
|
||||
.init(name: "低密度脂蛋白胆固醇", value: "3.84", unit: "mmol/L", range: "< 3.40", status: .high),
|
||||
.init(name: "甘油三酯 TG", value: "1.78", unit: "mmol/L", range: "< 1.70", status: .high),
|
||||
.init(name: "空腹血糖 GLU", value: "5.4", unit: "mmol/L", range: "3.9–6.1", status: .normal),
|
||||
]
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 0) {
|
||||
header
|
||||
ScrollView(showsIndicators: false) {
|
||||
VStack(spacing: 10) {
|
||||
ForEach(Array(items.enumerated()), id: \.offset) { idx, it in
|
||||
BatchRow(index: idx + 1, item: it)
|
||||
}
|
||||
addRow
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.bottom, 16)
|
||||
}
|
||||
HStack(spacing: 10) {
|
||||
Button {
|
||||
onFinish()
|
||||
} label: {
|
||||
Text("全部保存(\(items.count))").frame(maxWidth: .infinity)
|
||||
}
|
||||
.buttonStyle(TjPrimaryButton())
|
||||
}
|
||||
.padding(.horizontal, 16)
|
||||
.padding(.bottom, 14)
|
||||
}
|
||||
.background(Tj.Palette.sand.ignoresSafeArea())
|
||||
}
|
||||
|
||||
private var header: some View {
|
||||
HStack(spacing: 6) {
|
||||
Button(action: onBack) {
|
||||
Image(systemName: "chevron.left")
|
||||
.font(.system(size: 18, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.text)
|
||||
.frame(width: 36, height: 36)
|
||||
}
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text("本次已记录 \(items.count) 项")
|
||||
.font(.system(size: 15, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.text)
|
||||
Text("核对后一次保存")
|
||||
.font(.system(size: 11))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
}
|
||||
Spacer()
|
||||
Text("· · ·")
|
||||
.font(.system(size: 14, design: .monospaced))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
.padding(.trailing, 12)
|
||||
}
|
||||
.padding(.horizontal, 12)
|
||||
.padding(.top, 4)
|
||||
.padding(.bottom, 12)
|
||||
}
|
||||
|
||||
private var addRow: some View {
|
||||
Button(action: onAddMore) {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "camera").font(.system(size: 14))
|
||||
Text("再拍一项")
|
||||
.font(.system(size: 13))
|
||||
}
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.vertical, 14)
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: Tj.Radius.md, style: .continuous)
|
||||
.strokeBorder(Tj.Palette.line, style: StrokeStyle(lineWidth: 1.5, dash: [4, 4]))
|
||||
)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
}
|
||||
|
||||
private struct BatchRow: View {
|
||||
let index: Int
|
||||
let item: A3BatchItem
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 12) {
|
||||
TjPlaceholder(label: "#\(index)")
|
||||
.frame(width: 60, height: 44)
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(item.name)
|
||||
.font(.system(size: 13, weight: .semibold))
|
||||
.foregroundStyle(Tj.Palette.text)
|
||||
.lineLimit(1)
|
||||
Text("范围 \(item.range) \(item.unit)")
|
||||
.font(.system(size: 11))
|
||||
.foregroundStyle(Tj.Palette.text3)
|
||||
}
|
||||
Spacer(minLength: 8)
|
||||
VStack(alignment: .trailing, spacing: 2) {
|
||||
Text(item.value)
|
||||
.font(.system(size: 17, weight: .semibold))
|
||||
.foregroundStyle(item.status == .high ? Tj.Palette.brick : Tj.Palette.text)
|
||||
TjBadge(text: item.status == .high ? "偏高" : "正常",
|
||||
style: item.status == .high ? .brick : .leaf)
|
||||
}
|
||||
}
|
||||
.padding(12)
|
||||
.tjCard()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user