处理简单的view逻辑
This commit is contained in:
parent
bfc88eac08
commit
a87978e89b
22
punchnet/Views/Login/LoginState.swift
Normal file
22
punchnet/Views/Login/LoginState.swift
Normal 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
|
||||||
|
}
|
||||||
@ -6,20 +6,11 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
import Observation
|
||||||
|
|
||||||
// 登陆页面
|
// 登陆页面
|
||||||
struct LoginView: View {
|
struct LoginView: View {
|
||||||
@State private var token: String = ""
|
@State private var state = LoginState()
|
||||||
|
|
||||||
@State private var account: String = ""
|
|
||||||
@State private var password: String = ""
|
|
||||||
|
|
||||||
@State private var loginMode: LoginMode = .account
|
|
||||||
|
|
||||||
enum LoginMode {
|
|
||||||
case token
|
|
||||||
case account
|
|
||||||
}
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
@ -33,11 +24,11 @@ struct LoginView: View {
|
|||||||
.frame(width: 25, height: 25)
|
.frame(width: 25, height: 25)
|
||||||
|
|
||||||
Text("密钥登陆")
|
Text("密钥登陆")
|
||||||
.foregroundColor(loginMode == .token ? .blue : .black)
|
.foregroundColor(state.loginMode == .token ? .blue : .black)
|
||||||
}
|
}
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
self.loginMode = .token
|
self.state.loginMode = .token
|
||||||
}
|
}
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
@ -46,19 +37,21 @@ struct LoginView: View {
|
|||||||
.clipped()
|
.clipped()
|
||||||
.frame(width: 25, height: 25)
|
.frame(width: 25, height: 25)
|
||||||
Text("账户登陆")
|
Text("账户登陆")
|
||||||
.foregroundColor(loginMode == .account ? .blue : .black)
|
.foregroundColor(state.loginMode == .account ? .blue : .black)
|
||||||
}
|
}
|
||||||
.contentShape(Rectangle())
|
.contentShape(Rectangle())
|
||||||
.onTapGesture {
|
.onTapGesture {
|
||||||
self.loginMode = .account
|
self.state.loginMode = .account
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch loginMode {
|
Group {
|
||||||
case .token:
|
switch state.loginMode {
|
||||||
LoginTokenView(token: self.$token)
|
case .token:
|
||||||
case .account:
|
LoginTokenView(state: self.state)
|
||||||
LoginAccountView(account: $account, password: $password)
|
case .account:
|
||||||
|
LoginAccountView(state: self.state)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -69,10 +62,10 @@ struct LoginView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct LoginTokenView: View {
|
struct LoginTokenView: View {
|
||||||
@Binding var token: String
|
@Bindable var state: LoginState
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TextField("认证密钥", text: $token)
|
TextField("认证密钥", text: self.$state.token)
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.leading)
|
||||||
.textFieldStyle(PlainTextFieldStyle())
|
.textFieldStyle(PlainTextFieldStyle())
|
||||||
.frame(width: 200, height: 25)
|
.frame(width: 200, height: 25)
|
||||||
@ -102,11 +95,10 @@ struct LoginTokenView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct LoginAccountView: View {
|
struct LoginAccountView: View {
|
||||||
@Binding var account: String
|
@Bindable var state: LoginState
|
||||||
@Binding var password: String
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
TextField("手机号/邮箱", text: $account)
|
TextField("手机号/邮箱", text: $state.account)
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.leading)
|
||||||
.textFieldStyle(PlainTextFieldStyle())
|
.textFieldStyle(PlainTextFieldStyle())
|
||||||
.frame(width: 200, height: 25)
|
.frame(width: 200, height: 25)
|
||||||
@ -119,7 +111,7 @@ struct LoginAccountView: View {
|
|||||||
.padding(.top, 25)
|
.padding(.top, 25)
|
||||||
, alignment: .topLeading)
|
, alignment: .topLeading)
|
||||||
|
|
||||||
TextField("密码", text: $account)
|
SecureField("密码", text: $state.password)
|
||||||
.multilineTextAlignment(.leading)
|
.multilineTextAlignment(.leading)
|
||||||
.textFieldStyle(PlainTextFieldStyle())
|
.textFieldStyle(PlainTextFieldStyle())
|
||||||
.frame(width: 200, height: 25)
|
.frame(width: 200, height: 25)
|
||||||
89
punchnet/Views/Network/NetworkState.swift
Normal file
89
punchnet/Views/Network/NetworkState.swift
Normal 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),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
241
punchnet/Views/Network/NetworkView.swift
Normal file
241
punchnet/Views/Network/NetworkView.swift
Normal 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()
|
||||||
|
}
|
||||||
@ -44,7 +44,8 @@ struct punchnetApp: App {
|
|||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup(id: "mainWindow") {
|
WindowGroup(id: "mainWindow") {
|
||||||
IndexView(noticeServer: self.noticeServer)
|
//IndexView(noticeServer: self.noticeServer)
|
||||||
|
LoginView()
|
||||||
.onAppear {
|
.onAppear {
|
||||||
// 获取主屏幕的尺寸
|
// 获取主屏幕的尺寸
|
||||||
guard let screenFrame = NSScreen.main?.frame else { return }
|
guard let screenFrame = NSScreen.main?.frame else { return }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user