Files
e-party-iOS/yana/ContentView.swift
edwinQQQ b35b6e1ce1 feat: 移除CreateFeedView-Analysis文档并新增用户协议组件以增强用户体验
- 删除CreateFeedView-Analysis.md文档以简化项目结构。
- 新增UserAgreementComponent以处理用户协议的显示和交互。
- 更新多个视图中的onChange逻辑以兼容iOS 17的新API用法,确保代码一致性和可维护性。
- 在Localizable.strings中新增用户协议相关的本地化文本,提升多语言支持。
2025-08-01 14:34:53 +08:00

216 lines
8.1 KiB
Swift

//
// ContentView.swift
// yana
//
// Created by P on 2025/4/21.
//
import SwiftUI
import ComposableArchitecture
// MARK: - API Response Models
struct InitResponse: Codable, Equatable {
let status: String
let message: String?
let data: InitData?
}
struct InitData: Codable, Equatable {
let version: String?
let timestamp: Int?
let config: [String: String]?
}
// MARK: - Local UI Log Level Enum
enum UILogLevel: String, CaseIterable {
case none = "无日志"
case basic = "基础日志"
case detailed = "详细日志"
}
struct LoginTabView: View {
let store: StoreOf<LoginFeature>
let initStore: StoreOf<InitFeature>
@Binding var selectedLogLevel: APILogger.LogLevel
var body: some View {
VStack {
//
VStack(alignment: .leading, spacing: 8) {
Text("日志级别:")
.font(.headline)
.foregroundColor(.primary)
Picker("日志级别", selection: $selectedLogLevel) {
Text("无日志").tag(APILogger.LogLevel.none)
Text("基础日志").tag(APILogger.LogLevel.basic)
Text("详细日志").tag(APILogger.LogLevel.detailed)
}
.pickerStyle(SegmentedPickerStyle())
}
.padding()
.background(Color.gray.opacity(0.1))
.cornerRadius(10)
Spacer()
VStack(spacing: 20) {
Text("eparty")
.font(.largeTitle)
.fontWeight(.bold)
VStack(spacing: 15) {
TextField("账号", text: Binding(
get: { store.account },
set: { store.send(.updateAccount($0)) }
))
.textFieldStyle(RoundedBorderTextFieldStyle())
.autocorrectionDisabled(true)
SecureField("密码", text: Binding(
get: { store.password },
set: { store.send(.updatePassword($0)) }
))
.textFieldStyle(RoundedBorderTextFieldStyle())
}
.padding(.horizontal)
if let error = store.error {
Text(error)
.foregroundColor(.red)
.font(.caption)
.multilineTextAlignment(.center)
.padding(.horizontal)
}
VStack(spacing: 10) {
Button(action: {
store.send(.login)
}) {
HStack {
if store.isLoading {
ProgressView()
.scaleEffect(0.8)
.progressViewStyle(CircularProgressViewStyle(tint: .white))
}
Text(store.isLoading ? "登录中..." : "登录")
}
.frame(maxWidth: .infinity)
.padding()
.background(store.isLoading ? Color.gray : Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
.disabled(store.isLoading || store.account.isEmpty || store.password.isEmpty)
Button(action: {
initStore.send(.initialize)
}) {
HStack {
if initStore.isLoading {
ProgressView()
.scaleEffect(0.8)
.progressViewStyle(CircularProgressViewStyle(tint: .white))
}
Text(initStore.isLoading ? "测试中..." : "测试初始化")
}
.frame(maxWidth: .infinity)
.padding()
.background(initStore.isLoading ? Color.gray : Color.green)
.foregroundColor(.white)
.cornerRadius(10)
}
.disabled(initStore.isLoading)
if let response = initStore.response {
VStack(alignment: .leading, spacing: 8) {
HStack {
Text("API 测试结果:")
.font(.headline)
.foregroundColor(.primary)
}
ScrollView {
VStack(alignment: .leading, spacing: 4) {
Text("状态: \(response.status)")
if let message = response.message {
Text("消息: \(message)")
}
if let data = response.data {
Text("版本: \(data.version ?? "未知")")
Text("时间戳: \(data.timestamp ?? 0)")
if let config = data.config {
Text("配置:")
ForEach(Array(config.keys), id: \.self) { key in
Text(" \(key): \(config[key] ?? "")")
}
}
}
}
.font(.system(.caption, design: .monospaced))
.foregroundColor(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(8)
.background(Color.gray.opacity(0.1))
.cornerRadius(8)
}
.frame(maxHeight: 200)
}
.padding()
.background(Color.gray.opacity(0.05))
.cornerRadius(10)
}
if let error = initStore.error {
Text(error)
.foregroundColor(.red)
.font(.caption)
.multilineTextAlignment(.center)
.padding()
}
}
.padding(.horizontal)
}
Spacer()
}
.padding()
}
}
struct ContentView: View {
let store: StoreOf<LoginFeature>
let initStore: StoreOf<InitFeature>
let configStore: StoreOf<ConfigFeature>
@State private var selectedLogLevel: APILogger.LogLevel = APILogger.logLevel
@State private var selectedTab = 0
var body: some View {
WithPerceptionTracking {
TabView(selection: $selectedTab) {
LoginTabView(store: store, initStore: initStore, selectedLogLevel: $selectedLogLevel)
.tabItem {
Label("登录", systemImage: "person.circle")
}
.tag(0)
ConfigView(store: configStore)
.tabItem {
Label("API 测试", systemImage: "network")
}
.tag(1)
}
.onChange(of: selectedLogLevel) { _, selectedLogLevel in
APILogger.logLevel = selectedLogLevel
}
}
}
}
#Preview {
ContentView(
store: Store(
initialState: LoginFeature.State()
) {
LoginFeature()
},
initStore: Store(
initialState: InitFeature.State()
) {
InitFeature()
},
configStore: Store(
initialState: ConfigFeature.State()
) {
ConfigFeature()
}
)
}