Files
kangkang/康康/Features/Quick/A3BatchView.swift
link2026 d2c77d5c51 feat: 国际化(i18n) en/ja/ko + App 内语言切换
主体:多语言支持(简体中文源 + 英/日/韩)
- 基础设施:Localizable.xcstrings(String Catalog,sourceLanguage=zh-Hans)
  + pbxproj developmentRegion/knownRegions 注册 en/ja/ko
- 全部硬编码 Locale("zh_CN") → Locale.current;中文 dateFormat → Date.FormatStyle(跟随系统)
- UI 中文字面量统一为 String(appLoc:)(显式绑定所选语言 bundle+locale,即时切换)
  Text 字面量走环境 \.locale + Bundle 重定向
- 549 个 catalog key 全部 en/ja/ko 翻译完成(0 未翻译)
- App 内语言切换:我的 → 语言(LanguageManager + 即时生效,无需重启)
- 双用预设(症状/监测指标/慢病)本地化:static→computed 避免缓存

注:本提交为 WIP,一并打包了并行进行的功能模块
(HealthExport 健康导出、Security/Face ID 锁、DiaryAssist 日记 AI 辅助)
及 App 图标、CLAUDE.md、docs/scripts。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:28:24 +08:00

125 lines
4.3 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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: String(appLoc: "低密度脂蛋白胆固醇"), value: "3.84", unit: "mmol/L", range: "< 3.40", status: .high),
.init(name: String(appLoc: "甘油三酯 TG"), value: "1.78", unit: "mmol/L", range: "< 1.70", status: .high),
.init(name: String(appLoc: "空腹血糖 GLU"), value: "5.4", unit: "mmol/L", range: "3.96.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 ? String(appLoc: "偏高") : String(appLoc: "正常"),
style: item.status == .high ? .brick : .leaf)
}
}
.padding(12)
.tjCard()
}
}