From 1397875a116c2e083c8e7f90441aac4d479f2c96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=8C=AF=E5=8D=87?= <359059686@qq.com> Date: Mon, 25 Aug 2025 11:03:48 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E7=A6=BB=E7=BA=BF?= =?UTF-8?q?=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 + lib/app/routes/app_pages.dart | 12 +- lib/app/routes/app_routes.dart | 1 + lib/data/providers/user_provider.dart | 38 ++++ lib/data/repositories/auth_repository.dart | 0 .../my/bingdings/change_password_binding.dart | 17 ++ .../change_password_controller.dart | 57 ++++++ lib/modules/my/views/change_password.dart | 166 ++++++++++++++++++ lib/modules/my/views/my_page.dart | 11 +- lib/modules/problem/views/problem_page.dart | 4 +- .../problem/views/problem_upload_page.dart | 2 +- .../problem/views}/widgets/custom_button.dart | 0 .../views}/widgets/date_picker_button.dart | 0 .../widgets}/problem_card.dart | 2 +- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 56 ++++++ pubspec.yaml | 1 + .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 19 files changed, 361 insertions(+), 14 deletions(-) create mode 100644 lib/data/providers/user_provider.dart create mode 100644 lib/data/repositories/auth_repository.dart create mode 100644 lib/modules/my/bingdings/change_password_binding.dart create mode 100644 lib/modules/my/controllers/change_password_controller.dart create mode 100644 lib/modules/my/views/change_password.dart rename lib/{shared => modules/problem/views}/widgets/custom_button.dart (100%) rename lib/{shared => modules/problem/views}/widgets/date_picker_button.dart (100%) rename lib/modules/problem/{components => views/widgets}/problem_card.dart (98%) diff --git a/README.md b/README.md index d458a7b..34c772c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # problem_check_system +系统架构为MVVM + 仓库模式 + 这个应用需要实现以下功能: 离线登录系统 diff --git a/lib/app/routes/app_pages.dart b/lib/app/routes/app_pages.dart index d2450c7..a882e55 100644 --- a/lib/app/routes/app_pages.dart +++ b/lib/app/routes/app_pages.dart @@ -3,6 +3,8 @@ import 'package:problem_check_system/modules/home/bindings/home_binding.dart'; import 'package:problem_check_system/modules/home/views/home_page.dart'; import 'package:problem_check_system/modules/auth/bindings/auth_binding.dart'; import 'package:problem_check_system/modules/auth/views/login_page.dart'; +import 'package:problem_check_system/modules/my/bingdings/change_password_binding.dart'; +import 'package:problem_check_system/modules/my/views/change_password.dart'; import 'app_routes.dart'; @@ -20,11 +22,11 @@ abstract class AppPages { page: () => const LoginPage(), binding: AuthBinding(), ), - // GetPage( - // name: AppRoutes.my, - // page: () => const MyPage(), - // binding: null, - // ), + GetPage( + name: AppRoutes.changePassword, + page: () => const ChangePasswordPage(), + binding: ChangePasswordBinding(), + ), // // 添加 Problem 模块的路由和绑定 // GetPage( // name: AppRoutes.problem, // 确保在 app_routes.dart 中定义了此常量 diff --git a/lib/app/routes/app_routes.dart b/lib/app/routes/app_routes.dart index 300f680..272fc7c 100644 --- a/lib/app/routes/app_routes.dart +++ b/lib/app/routes/app_routes.dart @@ -4,4 +4,5 @@ abstract class AppRoutes { static const login = '/login'; static const problem = '/problem'; static const my = '/my'; + static const changePassword = '/changePassword'; } diff --git a/lib/data/providers/user_provider.dart b/lib/data/providers/user_provider.dart new file mode 100644 index 0000000..a25d44c --- /dev/null +++ b/lib/data/providers/user_provider.dart @@ -0,0 +1,38 @@ +import 'package:dio/dio.dart'; + +class UserProvider { + final Dio _dio; + + // 通过构造函数注入 Dio 实例 + UserProvider({required Dio dio}) : _dio = dio; + + /// 调用 API 修改用户密码 + /// + /// @param newPassword 新密码 + Future changePassword(String newPassword) async { + try { + final response = await _dio.post( + '/api/change_password', // 替换为你的修改密码接口地址 + data: { + 'new_password': newPassword, + }, + ); + return response; + } on DioException catch (e) { + // 抛出 DioException 以便在控制器中处理 + throw e; + } + } + + /// 调用 API 获取用户信息 + /// + /// 这个方法可以用于获取用户的姓名、手机号等信息 + Future getUserInfo() async { + try { + final response = await _dio.get('/api/user_info'); // 替换为你的用户信息接口地址 + return response; + } on DioException catch (e) { + throw e; + } + } +} \ No newline at end of file diff --git a/lib/data/repositories/auth_repository.dart b/lib/data/repositories/auth_repository.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/modules/my/bingdings/change_password_binding.dart b/lib/modules/my/bingdings/change_password_binding.dart new file mode 100644 index 0000000..ff0f9f2 --- /dev/null +++ b/lib/modules/my/bingdings/change_password_binding.dart @@ -0,0 +1,17 @@ +import 'package:dio/dio.dart'; +import 'package:get/get.dart'; +import 'package:problem_check_system/modules/my/controllers/change_password_controller.dart'; +import 'package:problem_check_system/data/providers/user_provider.dart'; // 假设你有这个 Provider + +class ChangePasswordBinding implements Bindings { + @override + void dependencies() { + // 如果 ChangePasswordController 依赖于 UserProvider,则需要先注入它 + final dio = Get.find(); + Get.lazyPut(() => UserProvider(dio: dio)); + Get.lazyPut( + // 如果需要,可以在这里注入依赖 + () => ChangePasswordController(userProvider: Get.find()), + ); + } +} \ No newline at end of file diff --git a/lib/modules/my/controllers/change_password_controller.dart b/lib/modules/my/controllers/change_password_controller.dart new file mode 100644 index 0000000..96865f4 --- /dev/null +++ b/lib/modules/my/controllers/change_password_controller.dart @@ -0,0 +1,57 @@ +import 'package:get/get.dart'; +import 'package:problem_check_system/data/providers/user_provider.dart'; // 假设你有一个用户相关的 Provider + +class ChangePasswordController extends GetxController { + // 响应式变量,用于存储新密码和确认密码 + var newPassword = ''.obs; + var confirmPassword = ''.obs; + var isLoading = false.obs; + + // 假设你需要一个 UserProvider 来处理 API 请求 + final UserProvider _userProvider; + ChangePasswordController({required UserProvider userProvider}) + : _userProvider = userProvider; + + // 更新新密码 + void updateNewPassword(String value) { + newPassword.value = value; + } + + // 更新确认密码 + void updateConfirmPassword(String value) { + confirmPassword.value = value; + } + + // 修改密码逻辑 + Future changePassword() async { + // 简单验证 + if (newPassword.value.isEmpty || confirmPassword.value.isEmpty) { + Get.snackbar('错误', '密码不能为空'); + return; + } + if (newPassword.value != confirmPassword.value) { + Get.snackbar('错误', '两次输入的密码不一致'); + return; + } + + isLoading.value = true; + try { + // TODO: 调用 API 来修改密码 + // final response = await _userProvider.changePassword(newPassword.value); + // if (response.statusCode == 200) { + // Get.back(); + // Get.snackbar('成功', '密码修改成功'); + // } else { + // Get.snackbar('失败', '密码修改失败,请重试'); + // } + // 模拟网络请求 + await Future.delayed(const Duration(seconds: 2)); + Get.back(); + Get.snackbar('成功', '密码修改成功', snackbarStatus: (status) {}); + } catch (e) { + Get.snackbar('错误', '修改密码失败: ${e.toString()}'); + } finally { + isLoading.value = false; + } + } +} \ No newline at end of file diff --git a/lib/modules/my/views/change_password.dart b/lib/modules/my/views/change_password.dart new file mode 100644 index 0000000..36f4922 --- /dev/null +++ b/lib/modules/my/views/change_password.dart @@ -0,0 +1,166 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:problem_check_system/modules/my/controllers/change_password_controller.dart'; + +class ChangePasswordPage extends StatelessWidget { + const ChangePasswordPage({super.key}); + + @override + Widget build(BuildContext context) { + // 获取控制器实例 + final ChangePasswordController controller = Get.find(); + + return Scaffold( + appBar: _buildAppBar(), + body: Padding( + padding: EdgeInsets.symmetric(horizontal: 24.w), + child: Column( + children: [ + SizedBox(height: 16.h), + _buildInputField( + label: '新密码', + hintText: '请输入新密码', + onChanged: controller.updateNewPassword, + obscureText: true, + ), + SizedBox(height: 24.h), + _buildInputField( + label: '确认新密码', + hintText: '请再次输入新密码', + onChanged: controller.updateConfirmPassword, + obscureText: true, + ), + const Spacer(), // 占据剩余空间 + _buildButtons(controller), + SizedBox(height: 50.h), + ], + ), + ), + ); + } + + /// 自定义 AppBar + AppBar _buildAppBar() { + return AppBar( + backgroundColor: const Color(0xFFF1F7FF), + elevation: 0, + centerTitle: true, + title: const Text( + '修改密码', + style: TextStyle( + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + leading: IconButton( + icon: const Icon(Icons.arrow_back_ios, color: Colors.black), + onPressed: () => Get.back(), + ), + ); + } + + /// 输入框组件 + Widget _buildInputField({ + required String label, + required String hintText, + required Function(String) onChanged, + bool obscureText = false, + }) { + return Container( + padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12.r), + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.1), + spreadRadius: 2, + blurRadius: 5, + offset: const Offset(0, 3), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: TextStyle( + fontSize: 16.sp, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + ), + SizedBox(height: 8.h), + TextField( + onChanged: onChanged, + obscureText: obscureText, + decoration: InputDecoration( + hintText: hintText, + hintStyle: TextStyle( + color: Colors.grey, + fontSize: 14.sp, + ), + border: InputBorder.none, // 移除下划线 + isDense: true, + contentPadding: EdgeInsets.zero, + ), + ), + ], + ), + ); + } + + /// 底部按钮区域 + Widget _buildButtons(ChangePasswordController controller) { + return Row( + children: [ + // 取消按钮 + Expanded( + child: OutlinedButton( + onPressed: () => Get.back(), + style: OutlinedButton.styleFrom( + minimumSize: Size(160.w, 48.h), + side: const BorderSide(color: Color(0xFF5695FD)), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.r), + ), + ), + child: Text( + '取消', + style: TextStyle( + fontSize: 16.sp, + color: const Color(0xFF5695FD), + ), + ), + ), + ), + SizedBox(width: 16.w), + // 确定按钮 + Expanded( + child: ElevatedButton( + onPressed: () { + // 调用控制器中的修改密码方法 + controller.changePassword(); + }, + style: ElevatedButton.styleFrom( + minimumSize: Size(160.w, 48.h), + backgroundColor: const Color(0xFF5695FD), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8.r), + ), + ), + child: Text( + '确定', + style: TextStyle( + fontSize: 16.sp, + color: Colors.white, + ), + ), + ), + ), + ], + ); + } +} \ No newline at end of file diff --git a/lib/modules/my/views/my_page.dart b/lib/modules/my/views/my_page.dart index 0aa5d4e..202c272 100644 --- a/lib/modules/my/views/my_page.dart +++ b/lib/modules/my/views/my_page.dart @@ -4,6 +4,8 @@ import 'package:get/get.dart'; import 'package:problem_check_system/modules/my/controllers/my_controller.dart'; import 'package:problem_check_system/modules/auth/controllers/auth_controller.dart'; +import '../../../app/routes/app_routes.dart'; + class MyPage extends StatelessWidget { const MyPage({super.key}); @@ -40,7 +42,7 @@ class MyPage extends StatelessWidget { end: Alignment.bottomCenter, colors: [ const Color(0xFFE4F0FF), - const Color(0xFFF1F7FF).withOpacity(0.0), + const Color(0xFFF1F7FF).withValues(alpha: 25.5), ], ), ), @@ -77,7 +79,7 @@ class MyPage extends StatelessWidget { borderRadius: BorderRadius.circular(15.r), boxShadow: [ BoxShadow( - color: Colors.grey.withOpacity(0.1), + color: Colors.grey.withValues(alpha: 25.5), spreadRadius: 2, blurRadius: 5, offset: const Offset(0, 3), @@ -94,7 +96,7 @@ class MyPage extends StatelessWidget { color: Colors.grey[200], shape: BoxShape.circle, border: Border.all( - color: Colors.grey.withOpacity(0.4), + color: Colors.grey.withValues(alpha: 102), width: 1.w, ), ), @@ -136,8 +138,7 @@ class MyPage extends StatelessWidget { _buildActionButton( label: '修改密码', onTap: () { - // TODO: 跳转到修改密码页面 - // Get.toNamed(AppRoutes.changePassword); + Get.toNamed(AppRoutes.changePassword); }, ), SizedBox(height: 15.h), diff --git a/lib/modules/problem/views/problem_page.dart b/lib/modules/problem/views/problem_page.dart index 644acea..0b03d58 100644 --- a/lib/modules/problem/views/problem_page.dart +++ b/lib/modules/problem/views/problem_page.dart @@ -3,8 +3,8 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:problem_check_system/modules/problem/controllers/problem_controller.dart'; import 'package:problem_check_system/data/models/problem_model.dart'; -import 'package:problem_check_system/shared/widgets/date_picker_button.dart'; -import 'package:problem_check_system/modules/problem/components/problem_card.dart'; +import 'package:problem_check_system/modules/problem/views/widgets/date_picker_button.dart'; +import 'package:problem_check_system/modules/problem/views/widgets/problem_card.dart'; import 'package:problem_check_system/modules/problem/views/problem_form_page.dart'; class ProblemPage extends StatelessWidget { diff --git a/lib/modules/problem/views/problem_upload_page.dart b/lib/modules/problem/views/problem_upload_page.dart index 0bf78f7..95c7a24 100644 --- a/lib/modules/problem/views/problem_upload_page.dart +++ b/lib/modules/problem/views/problem_upload_page.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:problem_check_system/modules/problem/controllers/problem_upload_controller.dart'; -import 'package:problem_check_system/modules/problem/components/problem_card.dart'; +import 'package:problem_check_system/modules/problem/views/widgets/problem_card.dart'; class ProblemUploadPage extends StatelessWidget { ProblemUploadPage({super.key}); diff --git a/lib/shared/widgets/custom_button.dart b/lib/modules/problem/views/widgets/custom_button.dart similarity index 100% rename from lib/shared/widgets/custom_button.dart rename to lib/modules/problem/views/widgets/custom_button.dart diff --git a/lib/shared/widgets/date_picker_button.dart b/lib/modules/problem/views/widgets/date_picker_button.dart similarity index 100% rename from lib/shared/widgets/date_picker_button.dart rename to lib/modules/problem/views/widgets/date_picker_button.dart diff --git a/lib/modules/problem/components/problem_card.dart b/lib/modules/problem/views/widgets/problem_card.dart similarity index 98% rename from lib/modules/problem/components/problem_card.dart rename to lib/modules/problem/views/widgets/problem_card.dart index fdf7903..313fad3 100644 --- a/lib/modules/problem/components/problem_card.dart +++ b/lib/modules/problem/views/widgets/problem_card.dart @@ -3,7 +3,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:intl/intl.dart'; import 'package:problem_check_system/data/models/problem_model.dart'; -import 'package:problem_check_system/shared/widgets/custom_button.dart'; +import 'package:problem_check_system/modules/problem/views/widgets/custom_button.dart'; import 'package:problem_check_system/modules/problem/views/problem_form_page.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index f6d969f..84fbaae 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -5,12 +5,14 @@ import FlutterMacOS import Foundation +import connectivity_plus import file_selector_macos import path_provider_foundation import shared_preferences_foundation import sqflite_darwin func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 8f97f79..80703a6 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.7.0" async: dependency: transitive description: @@ -41,6 +49,22 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.19.1" + connectivity_plus: + dependency: "direct main" + description: + name: connectivity_plus + sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.1.5" + connectivity_plus_platform_interface: + dependency: transitive + description: + name: connectivity_plus_platform_interface + sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204" + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.1" cross_file: dependency: transitive description: @@ -57,6 +81,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "3.0.6" + dbus: + dependency: transitive + description: + name: dbus + sha256: "79e0c23480ff85dc68de79e2cd6334add97e48f7f4865d17686dd6ea81a47e8c" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.7.11" dio: dependency: "direct main" description: @@ -368,6 +400,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.0" + nm: + dependency: transitive + description: + name: nm + sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.5.0" path: dependency: "direct main" description: @@ -488,6 +528,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1" + url: "https://pub.flutter-io.cn" + source: hosted + version: "7.0.1" platform: dependency: transitive description: @@ -733,6 +781,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025" + url: "https://pub.flutter-io.cn" + source: hosted + version: "6.6.1" sdks: dart: ">=3.8.1 <4.0.0" flutter: ">=3.29.0" diff --git a/pubspec.yaml b/pubspec.yaml index 9190bbf..f285d04 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,6 +7,7 @@ environment: sdk: ^3.8.1 dependencies: + connectivity_plus: ^6.1.5 dio: ^5.9.0 flutter: sdk: flutter diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 2c256bd..84f9bcc 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -6,10 +6,13 @@ #include "generated_plugin_registrant.h" +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { + ConnectivityPlusWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin")); FileSelectorWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("FileSelectorWindows")); PermissionHandlerWindowsPluginRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 230eabf..bd04dca 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -3,6 +3,7 @@ # list(APPEND FLUTTER_PLUGIN_LIST + connectivity_plus file_selector_windows permission_handler_windows )