处理简单的view逻辑

This commit is contained in:
anlicheng 2026-01-16 16:05:32 +08:00
parent bfc88eac08
commit a87978e89b
5 changed files with 372 additions and 27 deletions

View File

@ -0,0 +1,22 @@
//
// LoginState.swift
// punchnet
//
// Created by on 2026/1/16.
//
import Foundation
import Observation
@Observable
class LoginState {
enum LoginMode {
case token
case account
}
var token: String = ""
var account: String = ""
var password: String = ""
var loginMode: LoginMode = .account
}

View File

@ -6,20 +6,11 @@
//
import SwiftUI
import Observation
//
struct LoginView: View {
@State private var token: String = ""
@State private var account: String = ""
@State private var password: String = ""
@State private var loginMode: LoginMode = .account
enum LoginMode {
case token
case account
}
@State private var state = LoginState()
var body: some View {
VStack {
@ -33,11 +24,11 @@ struct LoginView: View {
.frame(width: 25, height: 25)
Text("密钥登陆")
.foregroundColor(loginMode == .token ? .blue : .black)
.foregroundColor(state.loginMode == .token ? .blue : .black)
}
.contentShape(Rectangle())
.onTapGesture {
self.loginMode = .token
self.state.loginMode = .token
}
HStack {
@ -46,19 +37,21 @@ struct LoginView: View {
.clipped()
.frame(width: 25, height: 25)
Text("账户登陆")
.foregroundColor(loginMode == .account ? .blue : .black)
.foregroundColor(state.loginMode == .account ? .blue : .black)
}
.contentShape(Rectangle())
.onTapGesture {
self.loginMode = .account
self.state.loginMode = .account
}
}
switch loginMode {
Group {
switch state.loginMode {
case .token:
LoginTokenView(token: self.$token)
LoginTokenView(state: self.state)
case .account:
LoginAccountView(account: $account, password: $password)
LoginAccountView(state: self.state)
}
}
Spacer()
@ -69,10 +62,10 @@ struct LoginView: View {
}
struct LoginTokenView: View {
@Binding var token: String
@Bindable var state: LoginState
var body: some View {
TextField("认证密钥", text: $token)
TextField("认证密钥", text: self.$state.token)
.multilineTextAlignment(.leading)
.textFieldStyle(PlainTextFieldStyle())
.frame(width: 200, height: 25)
@ -102,11 +95,10 @@ struct LoginTokenView: View {
}
struct LoginAccountView: View {
@Binding var account: String
@Binding var password: String
@Bindable var state: LoginState
var body: some View {
TextField("手机号/邮箱", text: $account)
TextField("手机号/邮箱", text: $state.account)
.multilineTextAlignment(.leading)
.textFieldStyle(PlainTextFieldStyle())
.frame(width: 200, height: 25)
@ -119,7 +111,7 @@ struct LoginAccountView: View {
.padding(.top, 25)
, alignment: .topLeading)
TextField("密码", text: $account)
SecureField("密码", text: $state.password)
.multilineTextAlignment(.leading)
.textFieldStyle(PlainTextFieldStyle())
.frame(width: 200, height: 25)

View File

@ -0,0 +1,89 @@
//
// NetworkState.swift
// punchnet
//
// Created by on 2026/1/16.
//
import Foundation
import Observation
@Observable
class NetworkState {
//
enum ConnectState {
case waitAuth
case connected
case disconnected
}
//
enum ShowMode {
case resource
case device
}
struct Resource {
var id: Int
var status: Int
var name: String
var schema: String
}
struct Device: Equatable, Hashable {
var id: Int
var status: Int
var name: String
var ipv4: String
var ipv6: String
var system: String
var resources: [Resource]
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.id == rhs.id
}
}
struct NetworkModel {
var name: String
}
var connectState: ConnectState = .connected
var model: NetworkModel = .init(name: "123@abc.com的网络")
var showModel: ShowMode = .device
var resources: [Resource] = [
.init(id: 1, status: 1, name: "OA", schema: "http://100.92.108.1:8080"),
.init(id: 2, status: 0, name: "数据资源", schema: "http://100.92.108.1:8080"),
.init(id: 3, status: 1, name: "OA", schema: "http://100.92.108.1:8080"),
.init(id: 4, status: 0, name: "TEST", schema: "http://100.92.108.1:8080"),
.init(id: 10, status: 1, name: "YES", schema: "http://100.92.108.1:8080"),
.init(id: 11, status: 0, name: "DEBUG", schema: "http://100.92.108.1:8080"),
]
var devices: [Device] = [
]
init() {
self.devices = [
.init(id: 1, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
.init(id: 2, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
.init(id: 3, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
.init(id: 4, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
.init(id: 5, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
.init(id: 15, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
.init(id: 25, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
.init(id: 35, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
.init(id: 45, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
.init(id: 55, status: 1, name: "阿里云1", ipv4: "192.168.1.1", ipv6: "fa9d.fa9d.fa9d.fa9d", system: "MacOS 12", resources: self.resources),
]
}
}

View File

@ -0,0 +1,241 @@
//
// NetworkView.swift
// punchnet
//
// Created by on 2026/1/16.
//
import SwiftUI
struct NetworkView: View {
@State private var state = NetworkState()
var body: some View {
VStack {
HStack(alignment: .center) {
Text(state.model.name)
Text(">")
Spacer()
Image("logo")
.resizable()
.frame(width: 25, height: 25)
}
Group {
switch state.connectState {
case .waitAuth:
NetworkWaitAuthView(state: self.state)
case .connected:
NetworkConnctedView(state: self.state)
case .disconnected:
NetworkDisconnctedView(state: self.state)
}
}
Spacer()
}
.frame(width: 400, height: 400)
.padding(.top, 10)
.padding(.leading, 10)
}
}
struct NetworkWaitAuthView: View {
@Bindable var state: NetworkState
var body: some View {
Color.clear
.overlay {
Text("等待确认中")
}
}
}
struct NetworkDisconnctedView: View {
@Bindable var state: NetworkState
@State var isOn: Bool = false
var body: some View {
VStack {
HStack {
Toggle("", isOn: $isOn)
.toggleStyle(SwitchToggleStyle(tint: .green))
Text("未连接")
Spacer()
}
ZStack {
Color.clear
Button {
print("call me here")
} label: {
Text("连接")
.font(.system(size: 14, weight: .regular))
.padding([.top, .bottom], 8)
.padding([.leading, .trailing], 30)
.foregroundColor(.white)
}
.background(Color(red: 74/255, green: 207/255, blue: 154/255))
.cornerRadius(5)
.frame(width: 120, height: 35)
}
}
}
}
struct NetworkConnctedView: View {
@Bindable var state: NetworkState
@State var isOn: Bool = true
var body: some View {
VStack {
HStack {
Toggle("", isOn: $isOn)
.toggleStyle(SwitchToggleStyle(tint: .green))
Text("已连接")
Spacer()
}
Group {
switch state.showModel {
case .resource:
NetworkResourceGroupView(resources: self.state.resources)
case .device:
NetworkDeviceGroupView(devices: self.state.devices, selection: self.state.devices[0])
}
}
}
}
}
//
struct NetworkResourceGroupView: View {
var resources: [NetworkState.Resource]
struct NetworkResourceView: View {
var resource: NetworkState.Resource
var body: some View {
VStack {
HStack {
Text(resource.status == 1 ? "yes" : "no")
Text(resource.name)
.font(.system(size: 14, weight: .regular))
}
Text(resource.schema)
.font(.system(size: 14, weight: .regular))
.padding(.leading, 30)
}
}
}
var body: some View {
LazyVGrid(columns: Array(repeating: GridItem(.flexible()), count: 3), spacing: 8) {
ForEach(resources, id: \.id) { resource in
NetworkResourceView(resource: resource)
}
}
}
}
//
struct NetworkDeviceGroupView: View {
var devices: [NetworkState.Device]
@State private var selection: NetworkState.Device
init(devices: [NetworkState.Device], selection: NetworkState.Device) {
self.devices = devices
self.selection = selection
}
var body: some View {
NavigationSplitView {
List(devices, id: \.id, selection: $selection) { device in
NetworkDeviceHeadView(device: device)
}
} detail: {
NetworkDeviceDetailView(device: $selection)
}
}
}
struct NetworkDeviceHeadView: View {
var device: NetworkState.Device
var body: some View {
VStack {
HStack {
Text(device.status == 1 ? "yes" : "no")
Text(device.name)
.font(.system(size: 14, weight: .regular))
}
Text(device.ipv4)
.font(.system(size: 14, weight: .regular))
.padding(.leading, 30)
}
}
}
struct NetworkDeviceDetailView: View {
@Binding var device: NetworkState.Device
var body: some View {
VStack {
HStack {
Text("连接状态")
Text("\(device.status)")
}
HStack {
Text("虚拟IPv4")
Text("\(device.ipv4)")
}
HStack {
Text("虚拟IPv6")
Text("\(device.ipv6)")
}
HStack {
Text("操作系统")
Text("\(device.system)")
}
VStack {
Text("服务列表")
List(device.resources, id: \.id) { resource in
HStack {
Text("\(resource.name)")
Text("\(resource.schema)")
}
}
}
}
}
}
#Preview {
NetworkView()
}

View File

@ -44,7 +44,8 @@ struct punchnetApp: App {
var body: some Scene {
WindowGroup(id: "mainWindow") {
IndexView(noticeServer: self.noticeServer)
//IndexView(noticeServer: self.noticeServer)
LoginView()
.onAppear {
//
guard let screenFrame = NSScreen.main?.frame else { return }