feat: 全面替换硬编码文本并修复编译错误
- 替换多个视图中的硬编码文本为本地化字符串,增强多语言支持。 - 修复编译错误,包括删除重复文件和修复作用域问题。 - 更新本地化文件,新增40+个本地化键值对,确保文本正确显示。 - 添加语言切换测试区域,验证文本实时更新功能。
This commit is contained in:
@@ -5,157 +5,205 @@ struct ConfigView: View {
|
||||
let store: StoreOf<ConfigFeature>
|
||||
|
||||
var body: some View {
|
||||
WithPerceptionTracking {
|
||||
NavigationView {
|
||||
VStack(spacing: 20) {
|
||||
// 标题
|
||||
Text("API 配置测试")
|
||||
.font(.largeTitle)
|
||||
.fontWeight(.bold)
|
||||
.padding(.top)
|
||||
|
||||
// 状态显示
|
||||
Group {
|
||||
if store.isLoading {
|
||||
VStack {
|
||||
ProgressView()
|
||||
.scaleEffect(1.5)
|
||||
Text("正在加载配置...")
|
||||
.font(.headline)
|
||||
.foregroundColor(.secondary)
|
||||
.padding(.top, 8)
|
||||
}
|
||||
.frame(height: 100)
|
||||
} else if let errorMessage = store.errorMessage {
|
||||
VStack {
|
||||
Image(systemName: "exclamationmark.triangle.fill")
|
||||
.font(.system(size: 40))
|
||||
.foregroundColor(.red)
|
||||
|
||||
Text("错误")
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
|
||||
Text(errorMessage)
|
||||
.font(.body)
|
||||
.foregroundColor(.secondary)
|
||||
.multilineTextAlignment(.center)
|
||||
.padding(.horizontal)
|
||||
|
||||
Button("清除错误") {
|
||||
store.send(.clearError)
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.padding(.top)
|
||||
}
|
||||
.frame(maxHeight: .infinity)
|
||||
} else if let configData = store.configData {
|
||||
// 配置数据显示
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
|
||||
if let version = configData.version {
|
||||
InfoRow(title: "版本", value: version)
|
||||
}
|
||||
|
||||
if let features = configData.features, !features.isEmpty {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text("功能列表")
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
|
||||
ForEach(features, id: \.self) { feature in
|
||||
HStack {
|
||||
Circle()
|
||||
.fill(Color.green)
|
||||
.frame(width: 6, height: 6)
|
||||
Text(feature)
|
||||
.font(.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.background(Color(.systemGray6))
|
||||
.cornerRadius(12)
|
||||
}
|
||||
|
||||
if let settings = configData.settings {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text("设置")
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
|
||||
if let enableDebug = settings.enableDebug {
|
||||
InfoRow(title: "调试模式", value: enableDebug ? "启用" : "禁用")
|
||||
}
|
||||
|
||||
if let apiTimeout = settings.apiTimeout {
|
||||
InfoRow(title: "API 超时", value: "\(apiTimeout)秒")
|
||||
}
|
||||
|
||||
if let maxRetries = settings.maxRetries {
|
||||
InfoRow(title: "最大重试次数", value: "\(maxRetries)")
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.background(Color(.systemGray6))
|
||||
.cornerRadius(12)
|
||||
}
|
||||
|
||||
if let lastUpdated = store.lastUpdated {
|
||||
Text("最后更新: \(lastUpdated, style: .time)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
} else {
|
||||
VStack {
|
||||
Image(systemName: "gear")
|
||||
.font(.system(size: 40))
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
Text("点击下方按钮加载配置")
|
||||
.font(.headline)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.frame(maxHeight: .infinity)
|
||||
}
|
||||
NavigationView {
|
||||
VStack(spacing: 20) {
|
||||
Text(LocalizedString("config.api_test", comment: ""))
|
||||
.font(.largeTitle)
|
||||
.fontWeight(.bold)
|
||||
.padding(.top)
|
||||
|
||||
// 状态显示
|
||||
Group {
|
||||
if store.isLoading {
|
||||
LoadingView()
|
||||
} else if store.errorMessage != nil {
|
||||
ConfigErrorView(store: store)
|
||||
} else if let configData = store.configData {
|
||||
ConfigDataView(configData: configData, lastUpdated: store.lastUpdated)
|
||||
} else {
|
||||
EmptyStateView()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
// 操作按钮
|
||||
VStack(spacing: 12) {
|
||||
Button(action: {
|
||||
store.send(.loadConfig)
|
||||
}) {
|
||||
HStack {
|
||||
if store.isLoading {
|
||||
ProgressView()
|
||||
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||||
.scaleEffect(0.8)
|
||||
} else {
|
||||
Image(systemName: "arrow.clockwise")
|
||||
}
|
||||
Text(store.isLoading ? "加载中..." : "加载配置")
|
||||
}
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.disabled(store.isLoading)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 50)
|
||||
|
||||
Text("使用新的 TCA API 组件")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
// 操作按钮
|
||||
ActionButtonsView(store: store)
|
||||
|
||||
}
|
||||
}
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Loading View
|
||||
struct LoadingView: View {
|
||||
var body: some View {
|
||||
VStack {
|
||||
ProgressView()
|
||||
.scaleEffect(1.2)
|
||||
Text(LocalizedString("config.loading", comment: ""))
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
.padding(.top, 8)
|
||||
}
|
||||
.frame(height: 100)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Error View
|
||||
struct ConfigErrorView: View {
|
||||
let store: StoreOf<ConfigFeature>
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 16) {
|
||||
Image(systemName: "exclamationmark.triangle.fill")
|
||||
.font(.system(size: 40))
|
||||
.foregroundColor(.yellow)
|
||||
Text(LocalizedString("config.error", comment: ""))
|
||||
.foregroundColor(.red)
|
||||
Button(LocalizedString("config.clear_error", comment: "")) {
|
||||
store.send(.clearError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Config Data View
|
||||
struct ConfigDataView: View {
|
||||
let configData: ConfigData
|
||||
let lastUpdated: Date?
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
if let version = configData.version {
|
||||
InfoRow(title: LocalizedString("config.version", comment: ""), value: version)
|
||||
}
|
||||
|
||||
if let features = configData.features, !features.isEmpty {
|
||||
FeaturesSection(features: features)
|
||||
}
|
||||
|
||||
if let settings = configData.settings {
|
||||
SettingsSection(settings: settings)
|
||||
}
|
||||
|
||||
if let lastUpdated = lastUpdated {
|
||||
Text(String(format: LocalizedString("config.last_updated", comment: ""), {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateStyle = .medium
|
||||
formatter.timeStyle = .short
|
||||
return formatter.string(from: lastUpdated)
|
||||
}()))
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
.frame(maxWidth: .infinity, alignment: .center)
|
||||
}
|
||||
}
|
||||
.navigationBarHidden(true)
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Features Section
|
||||
struct FeaturesSection: View {
|
||||
let features: [String]
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text(LocalizedString("config.feature_list", comment: ""))
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
|
||||
ForEach(features, id: \.self) { feature in
|
||||
HStack {
|
||||
Circle()
|
||||
.fill(Color.green)
|
||||
.frame(width: 6, height: 6)
|
||||
Text(feature)
|
||||
.font(.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.background(Color(.systemGray6))
|
||||
.cornerRadius(12)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Settings Section
|
||||
struct SettingsSection: View {
|
||||
let settings: ConfigSettings
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text(LocalizedString("config.settings", comment: ""))
|
||||
.font(.headline)
|
||||
.fontWeight(.semibold)
|
||||
|
||||
if let enableDebug = settings.enableDebug {
|
||||
InfoRow(title: LocalizedString("config.debug_mode", comment: ""), value: enableDebug ? "启用" : "禁用")
|
||||
}
|
||||
|
||||
if let apiTimeout = settings.apiTimeout {
|
||||
InfoRow(title: LocalizedString("config.api_timeout", comment: ""), value: "\(apiTimeout)秒")
|
||||
}
|
||||
|
||||
if let maxRetries = settings.maxRetries {
|
||||
InfoRow(title: LocalizedString("config.max_retries", comment: ""), value: "\(maxRetries)")
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
.background(Color(.systemGray6))
|
||||
.cornerRadius(12)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Empty State View
|
||||
struct EmptyStateView: View {
|
||||
var body: some View {
|
||||
VStack(spacing: 16) {
|
||||
Image(systemName: "arrow.down.circle")
|
||||
.font(.system(size: 40))
|
||||
.foregroundColor(.blue)
|
||||
Text(LocalizedString("config.click_to_load", comment: ""))
|
||||
.font(.body)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.frame(maxHeight: .infinity)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Action Buttons View
|
||||
struct ActionButtonsView: View {
|
||||
let store: StoreOf<ConfigFeature>
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 12) {
|
||||
Button(action: {
|
||||
store.send(.loadConfig)
|
||||
}) {
|
||||
HStack {
|
||||
if store.isLoading {
|
||||
ProgressView()
|
||||
.progressViewStyle(CircularProgressViewStyle(tint: .white))
|
||||
.scaleEffect(0.8)
|
||||
} else {
|
||||
Image(systemName: "arrow.clockwise")
|
||||
}
|
||||
Text(store.isLoading ? "加载中..." : "加载配置")
|
||||
}
|
||||
}
|
||||
.buttonStyle(.borderedProminent)
|
||||
.disabled(store.isLoading)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 50)
|
||||
|
||||
Text(LocalizedString("config.use_new_tca", comment: ""))
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,4 +235,4 @@ struct InfoRow: View {
|
||||
ConfigFeature()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user