Browse Source

feat:登录流程修改,改为非必要登录

ythtc 1 month ago
parent
commit
fed8f2bd44

BIN
VenusKitto.xcodeproj/project.xcworkspace/xcuserdata/neoa.xcuserdatad/UserInterfaceState.xcuserstate


+ 21 - 0
VenusKitto/Assets.xcassets/emptydata.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "2x"
+    },
+    {
+      "filename" : "emptydata.png",
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}

BIN
VenusKitto/Assets.xcassets/emptydata.imageset/emptydata.png


+ 89 - 3
VenusKitto/BookkeepingViewController.swift

@@ -116,6 +116,51 @@ final class BookkeepingViewController: UIViewController, UITableViewDataSource,
     private let tableView = UITableView(frame: .zero, style: .grouped)
     // tableHeader 容器,用于在布局变化时重算高度
     private var headerContainer: UIView?
+    
+    // 空视图
+    private lazy var emptyView: UIView = {
+        let container = UIView()
+        container.backgroundColor = .clear
+        
+        let imageView = UIImageView()
+        imageView.image = UIImage(named: "emptydata") // 使用现有的图片资源
+        imageView.contentMode = .scaleAspectFit
+//        imageView.tintColor = UIColor(hex: "#CFCFCF")
+        
+        let titleLabel = UILabel()
+        titleLabel.text = "暂无记账记录"
+        titleLabel.font = .systemFont(ofSize: 18, weight: .medium)
+        titleLabel.textColor = UIColor(hex: "#CFCFCF")
+        titleLabel.textAlignment = .center
+        
+        let subtitleLabel = UILabel()
+        subtitleLabel.text = "快去添加第一条记账记录吧~"
+        subtitleLabel.font = .systemFont(ofSize: 14)
+        subtitleLabel.textColor = UIColor(hex: "#CFCFCF")
+        subtitleLabel.textAlignment = .center
+        
+        let stackView = UIStackView(arrangedSubviews: [imageView, titleLabel, subtitleLabel])
+        stackView.axis = .vertical
+        stackView.alignment = .center
+        stackView.spacing = 16
+        
+        container.addSubview(stackView)
+        stackView.translatesAutoresizingMaskIntoConstraints = false
+        imageView.translatesAutoresizingMaskIntoConstraints = false
+        
+        NSLayoutConstraint.activate([
+            imageView.widthAnchor.constraint(equalToConstant: 80),
+            imageView.heightAnchor.constraint(equalToConstant: 80),
+            
+            stackView.centerXAnchor.constraint(equalTo: container.centerXAnchor),
+            stackView.centerYAnchor.constraint(equalTo: container.centerYAnchor),
+            stackView.leadingAnchor.constraint(greaterThanOrEqualTo: container.leadingAnchor, constant: 40),
+            stackView.trailingAnchor.constraint(lessThanOrEqualTo: container.trailingAnchor, constant: -40)
+        ])
+        
+        container.isHidden = true
+        return container
+    }()
 
     // 数据(由外部注入,带 id)
     private var pets: [BKPet] = []
@@ -344,13 +389,23 @@ final class BookkeepingViewController: UIViewController, UITableViewDataSource,
         tableView.delegate = self
         tableView.register(ExpenseCell.self, forCellReuseIdentifier: "ExpenseCell")
         view.addSubview(tableView)
+        view.addSubview(emptyView)
+        
         tableView.translatesAutoresizingMaskIntoConstraints = false
+        emptyView.translatesAutoresizingMaskIntoConstraints = false
+        
         NSLayoutConstraint.activate([
             tableView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 8),
             tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
             tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
-            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
+            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
+            
+            emptyView.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 200),
+            emptyView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
+            emptyView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
+            emptyView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
         ])
+        
         tableView.estimatedRowHeight = 121
         tableView.rowHeight = UITableView.automaticDimension
     }
@@ -398,8 +453,8 @@ final class BookkeepingViewController: UIViewController, UITableViewDataSource,
     // MARK: - 触发刷新 & 网络请求
     private func refetch() {
         guard let pid = currentPetId() else {
-            // 无 petId(占位宠物),展示本地 demo
-            reloadDemoData()
+            // 无 petId(占位宠物),显示空视图
+            showEmptyView()
             return
         }
         fetchBillRecords(petId: pid, month: currentMonth)
@@ -484,6 +539,14 @@ final class BookkeepingViewController: UIViewController, UITableViewDataSource,
         }
         groups.sort { $0.date > $1.date }
         self.dayGroups = groups
+        
+        // 检查是否有数据,决定显示列表还是空视图
+        if dayGroups.isEmpty {
+            showEmptyView()
+        } else {
+            hideEmptyView()
+        }
+        
         self.tableView.reloadData()
     }
 
@@ -736,6 +799,29 @@ final class BookkeepingViewController: UIViewController, UITableViewDataSource,
         }
     }
     
+    // MARK: - 空视图管理
+    private func showEmptyView() {
+        dayGroups = []
+        // 设置汇总卡为 0
+        let petName = pets.isEmpty ? "宠物" : pets[selectedPetIndex].name
+        let suffix: String
+        let yF = DateFormatter(); yF.dateFormat = "yyyy"
+        let ymF = DateFormatter(); ymF.dateFormat = "yyyy.MM"
+        switch periodIndex {
+        case 0: suffix = "合计花费"
+        case 1: suffix = "\(yF.string(from: currentMonth))花费"
+        default: suffix = "\(ymF.string(from: currentMonth))花费"
+        }
+        summaryCard.configure(title: "\(petName)  \(suffix)", amount: 0)
+        
+        emptyView.isHidden = false
+        tableView.reloadData()
+    }
+    
+    private func hideEmptyView() {
+        emptyView.isHidden = true
+    }
+
     // MARK: - UIPopoverPresentationControllerDelegate fallback for iPad popover
     func prepareForPopoverPresentation(_ popoverPresentationController: UIPopoverPresentationController) {
         if popoverPresentationController.sourceView == nil && popoverPresentationController.barButtonItem == nil {

+ 134 - 19
VenusKitto/HomeViewController.swift

@@ -38,6 +38,51 @@ class HomeViewController: UIViewController, UIPopoverPresentationControllerDeleg
     private let tagScroll = UIScrollView()
     private let tagStack = UIStackView()
     private let recordStack = UIStackView()
+    
+    // 空视图组件
+    private lazy var emptyStateView: UIView = {
+        let container = UIView()
+        container.backgroundColor = .clear
+        
+        let imageView = UIImageView()
+        imageView.image = UIImage(named: "emptydata") // 使用现有的图片资源
+        imageView.contentMode = .scaleAspectFit
+//        imageView.tintColor = UIColor(hex: "#CFCFCF")
+        
+        let titleLabel = UILabel()
+        titleLabel.text = "暂无记录"
+        titleLabel.font = .systemFont(ofSize: 18, weight: .medium)
+        titleLabel.textColor = UIColor(hex: "#CFCFCF")
+        titleLabel.textAlignment = .center
+        
+        let subtitleLabel = UILabel()
+        subtitleLabel.text = "快去记录第一个美好时刻吧~"
+        subtitleLabel.font = .systemFont(ofSize: 14)
+        subtitleLabel.textColor = UIColor(hex: "#CFCFCF")
+        subtitleLabel.textAlignment = .center
+        
+        let stackView = UIStackView(arrangedSubviews: [imageView, titleLabel, subtitleLabel])
+        stackView.axis = .vertical
+        stackView.alignment = .center
+        stackView.spacing = 16
+        
+        container.addSubview(stackView)
+        stackView.translatesAutoresizingMaskIntoConstraints = false
+        imageView.translatesAutoresizingMaskIntoConstraints = false
+        
+        NSLayoutConstraint.activate([
+            imageView.widthAnchor.constraint(equalToConstant: 80),
+            imageView.heightAnchor.constraint(equalToConstant: 80),
+            
+            stackView.centerXAnchor.constraint(equalTo: container.centerXAnchor),
+            stackView.centerYAnchor.constraint(equalTo: container.centerYAnchor),
+            stackView.leadingAnchor.constraint(greaterThanOrEqualTo: container.leadingAnchor, constant: 40),
+            stackView.trailingAnchor.constraint(lessThanOrEqualTo: container.trailingAnchor, constant: -40)
+        ])
+        
+        container.isHidden = true
+        return container
+    }()
 
     private let addButton: UIButton = {
         let b = UIButton(type: .custom)
@@ -151,7 +196,7 @@ class HomeViewController: UIViewController, UIPopoverPresentationControllerDeleg
         scrollView.addSubview(contentView)
 
         // Header
-        [titleLabel, settingsButton, petCard, tagScroll, recordStack].forEach {
+        [titleLabel, settingsButton, petCard, tagScroll, recordStack, emptyStateView].forEach {
             $0.translatesAutoresizingMaskIntoConstraints = false
             contentView.addSubview($0)
         }
@@ -265,6 +310,12 @@ class HomeViewController: UIViewController, UIPopoverPresentationControllerDeleg
             recordStack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12),
             recordStack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -12),
             recordStack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -24),
+            
+            // Empty state view
+            emptyStateView.topAnchor.constraint(equalTo: tagScroll.bottomAnchor, constant: 50),
+            emptyStateView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12),
+            emptyStateView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -12),
+            emptyStateView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -100),
 
             // Bottom tab bar
             tabBarView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
@@ -417,9 +468,29 @@ class HomeViewController: UIViewController, UIPopoverPresentationControllerDeleg
     }
     
     @objc private func tapAddPet() {
+        
+        // 检查登录状态
+        let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogggedIn")
+        let userToken = UserDefaults.standard.string(forKey: "userToken")
+        
+        // 如果没有登录状态或者没有有效的token,弹出登录界面
+        if !isLoggedIn || userToken?.isEmpty != false {
+            showLoginViewController()
+            return
+        }
+
+        
         let vc = AddPetViewController()
         navigationController?.pushViewController(vc, animated: true)
     }
+    
+    private func showLoginViewController() {
+        let loginVC = LoginViewController()
+        let navController = UINavigationController(rootViewController: loginVC)
+        navController.modalPresentationStyle = .fullScreen
+        present(navController, animated: true)
+    }
+
 
 
     private func styleAddPetButton() {
@@ -436,6 +507,7 @@ class HomeViewController: UIViewController, UIPopoverPresentationControllerDeleg
 //        addPetButton.isHidden = value
         tagScroll.isHidden = !value
         recordStack.isHidden = !value
+        emptyStateView.isHidden = value // 没有宠物时显示空视图
         emptyTipLabel.isHidden = value
         emptyBanner.isHidden = value
         if !value {
@@ -536,12 +608,35 @@ class HomeViewController: UIViewController, UIPopoverPresentationControllerDeleg
     }
 
     @objc private func tapQuickEvent() {
+        print("快速进入 随手小记")
+
+        // 检查登录状态
+        let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogggedIn")
+        let userToken = UserDefaults.standard.string(forKey: "userToken")
+        
+        // 如果没有登录状态或者没有有效的token,弹出登录界面
+        if !isLoggedIn || userToken?.isEmpty != false {
+            showLoginViewController()
+            return
+        }
+
         hideActionMenu()
         showCreateRecordSheet()
     }
 
     @objc private func tapQuickNote() {
         print("快速进入 记账")
+        
+        // 检查登录状态
+        let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogggedIn")
+        let userToken = UserDefaults.standard.string(forKey: "userToken")
+        
+        // 如果没有登录状态或者没有有效的token,弹出登录界面
+        if !isLoggedIn || userToken?.isEmpty != false {
+            showLoginViewController()
+            return
+        }
+
         hideActionMenu()
         showBookkeepingQuickSheet()
     }
@@ -915,24 +1010,26 @@ class HomeViewController: UIViewController, UIPopoverPresentationControllerDeleg
         UserDefaults.standard.set(false, forKey: "isLogggedIn")
         UserDefaults.standard.removeObject(forKey: "userToken")
 
-        // 创建登录界面
+//        // 创建登录界面
         let loginVC = LoginViewController()
         let navController = UINavigationController(rootViewController: loginVC)
-        
-        // 获取当前窗口
-        guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else {
-            return
-        }
-        
-        // 设置根视图控制器为登录界面
-        window.rootViewController = navController
-        
-        // 添加切换动画
-        UIView.transition(with: window,
-                          duration: 0.4,
-                          options: .transitionCrossDissolve,
-                          animations: nil,
-                          completion: nil)
+        navController.modalPresentationStyle = .fullScreen
+        self.present(navController, animated: true)
+//
+//        // 获取当前窗口
+//        guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else {
+//            return
+//        }
+//        
+//        // 设置根视图控制器为登录界面
+//        window.rootViewController = navController
+//        
+//        // 添加切换动画
+//        UIView.transition(with: window,
+//                          duration: 0.4,
+//                          options: .transitionCrossDissolve,
+//                          animations: nil,
+//                          completion: nil)
     }
 
 
@@ -1159,8 +1256,15 @@ class HomeViewController: UIViewController, UIPopoverPresentationControllerDeleg
             recordStack.removeArrangedSubview(v)
             v.removeFromSuperview()
         }
-        guard !list.isEmpty else { return }
-
+        
+        // 检查是否有数据,决定显示列表还是空视图
+        if list.isEmpty {
+            showEmptyState()
+            return
+        }
+        
+        hideEmptyState()
+        
         let placeholder = UIImage(named: "peihead") ?? UIImage(systemName: "pawprint.circle")!
 
         for rec in list {
@@ -1192,6 +1296,17 @@ class HomeViewController: UIViewController, UIPopoverPresentationControllerDeleg
         }
     }
 
+    // MARK: - 空视图管理
+    private func showEmptyState() {
+        emptyStateView.isHidden = false
+        recordStack.isHidden = true
+    }
+    
+    private func hideEmptyState() {
+        emptyStateView.isHidden = true
+        recordStack.isHidden = false
+    }
+    
     private func formatAPIDate(_ s: String?) -> String {
         guard let s = s, !s.isEmpty else { return "" }
         let inFmt = DateFormatter()

+ 27 - 2
VenusKitto/LoginViewController.swift

@@ -37,6 +37,12 @@ class LoginViewController: UIViewController {
         // Set up the view background color
         view.backgroundColor = .white
         
+        if let backImage = UIImage(named: "AddPet385") {
+            let backButton = UIBarButtonItem(image: backImage.withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(tapCancel))
+            navigationItem.leftBarButtonItem = backButton
+        }
+
+        
         let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
         view.addGestureRecognizer(tapGesture)
         
@@ -183,6 +189,10 @@ class LoginViewController: UIViewController {
         ])
     }
     
+    @objc private func tapCancel() {
+        self.dismiss(animated: true)
+    }
+    
     @objc func dismissKeyboard() {
         // Dismiss the keyboard when tapping outside the text fields
         view.endEditing(true)
@@ -376,8 +386,23 @@ class LoginViewController: UIViewController {
                                 UserDefaults.standard.set(token, forKey: "userToken") // Store the token
                                 
                                 // Navigate to the main interface
-                                let mainVC = HomeViewController() // Replace with your actual main screen controller
-                                self.navigationController?.setViewControllers([mainVC], animated: true)
+                                let mainVC = HomeViewController()
+                                let navController = UINavigationController(rootViewController: mainVC)
+// Replace with your actual main screen controller
+//                                self.navigationController?.setViewControllers([mainVC], animated: true)
+                                // 获取当前窗口
+                                guard let window = UIApplication.shared.windows.first(where: { $0.isKeyWindow }) else {
+                                    return
+                                }
+                                // 设置根视图控制器为登录界面
+                                window.rootViewController = navController
+                                // 添加切换动画
+                                UIView.transition(with: window,
+                                                  duration: 0.4,
+                                                  options: .transitionCrossDissolve,
+                                                  animations: nil,
+                                                  completion: nil)
+
                             } else {
                                 // Handle missing token error
                                 self.showAlert(title: "错误", message: "Token 不存在")

+ 8 - 8
VenusKitto/SceneDelegate.swift

@@ -27,17 +27,17 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
 //        let startVC = HomeViewController()
 //        self.window?.rootViewController = UINavigationController(rootViewController: startVC)
         
-        UIView.transition(with: window!, duration: 0.2, options: .transitionCrossDissolve, animations: {
-            if isLogggedIn {
+//        UIView.transition(with: window!, duration: 0.2, options: .transitionCrossDissolve, animations: {
+//            if isLogggedIn {
                 // 用户已登录,显示主界面
                 let mainVC = HomeViewController()
                 self.window?.rootViewController = UINavigationController(rootViewController: mainVC)
-            } else {
-                // 用户未登录,显示登录界面
-                let loginVC = LoginViewController()
-                self.window?.rootViewController = UINavigationController(rootViewController: loginVC)
-            }
-        }, completion: nil)
+//            } else {
+//                // 用户未登录,显示登录界面
+//                let loginVC = LoginViewController()
+//                self.window?.rootViewController = UINavigationController(rootViewController: loginVC)
+//            }
+//        }, completion: nil)
 
         
         window?.makeKeyAndVisible()

+ 30 - 5
VenusKitto/SettingsViewController.swift

@@ -211,7 +211,7 @@ final class SettingsViewController: UIViewController {
 
     private func fillUserInfo() {
         // 显示手机号(打码)与 ID
-        let phone = UserDefaults.standard.string(forKey: "memberPhone") ?? "18000000000"
+        let phone = UserDefaults.standard.string(forKey: "memberPhone") ?? "登录"
         let uid = UserDefaults.standard.string(forKey: "userId") ?? "--"
         phoneLabel.text = maskedPhone(phone)
         idLabel.text = "ID:\(uid)"
@@ -246,14 +246,28 @@ final class SettingsViewController: UIViewController {
 
     // MARK: - Actions
     @objc private func tapProfile() {
-        // 这里可跳个人信息页;先展示提示
-//        let ac = UIAlertController(title: "个人信息", message: "点击了头像卡片", preferredStyle: .alert)
-//        ac.addAction(UIAlertAction(title: "好的", style: .default))
-//        present(ac, animated: true)
+        // 检查登录状态
+        let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogggedIn")
+        let userToken = UserDefaults.standard.string(forKey: "userToken")
+        
+        // 如果没有登录状态或者没有有效的token,弹出登录界面
+        if !isLoggedIn || userToken?.isEmpty != false {
+            showLoginViewController()
+            return
+        }
+        
+        // 已登录,跳转到个人信息页
         let userSettingsVC = UserSettingsViewController()
         userSettingsVC.hidesBottomBarWhenPushed = true
         navigationController?.pushViewController(userSettingsVC, animated: true)
     }
+    
+    private func showLoginViewController() {
+        let loginVC = LoginViewController()
+        let navController = UINavigationController(rootViewController: loginVC)
+        navController.modalPresentationStyle = .fullScreen
+        present(navController, animated: true)
+    }
 
     @objc private func tapRate() {
         // 跳 App Store 评分(占位)
@@ -262,6 +276,17 @@ final class SettingsViewController: UIViewController {
     }
     
     @objc private func tapPet() {
+        
+        // 检查登录状态
+        let isLoggedIn = UserDefaults.standard.bool(forKey: "isLogggedIn")
+        let userToken = UserDefaults.standard.string(forKey: "userToken")
+        
+        // 如果没有登录状态或者没有有效的token,弹出登录界面
+        if !isLoggedIn || userToken?.isEmpty != false {
+            showLoginViewController()
+            return
+        }
+
         //进入我的宠物界面
         let vc = MyPetsViewController()
         vc.hidesBottomBarWhenPushed = true