diff --git a/lib/base/http/http.dart b/lib/base/http/http.dart new file mode 100644 index 0000000..5b55a59 --- /dev/null +++ b/lib/base/http/http.dart @@ -0,0 +1,109 @@ +import 'package:dio/dio.dart'; +import 'package:dio_log/dio_log.dart'; +import 'package:flutter/foundation.dart'; +import 'package:qinglong_app/base/http/token_interceptor.dart'; +import 'package:qinglong_app/base/userinfo_viewmodel.dart'; +import 'package:qinglong_app/main.dart'; + +import '../../json.jc.dart'; + +class Http { + static const int NOT_LOGIN = 1000; + static Dio? _dio; + + static void initDioConfig( + String host, + ) { + _dio = Dio( + BaseOptions( + baseUrl: host, + connectTimeout: 5000, + receiveTimeout: 5000, + sendTimeout: 5000, + contentType: "application/json", + ), + ); + _dio?.interceptors.add(DioLogInterceptor()); + _dio?.interceptors.add(TokenInterceptor()); + } + + static Future> post(String uri, Map json, {bool compute = true}) async { + if (userInfoViewModel.host == null || userInfoViewModel.host!.isEmpty) { + return HttpResponse(success: false, code: NOT_LOGIN, message: "未登录"); + } + + if (_dio == null) { + initDioConfig(UserInfoViewModel.getInstance().host!); + } + + var response = await _dio!.post(uri, data: json); + + return decodeResponse(response, compute); + } + + static HttpResponse decodeResponse( + Response response, + bool compute, + ) { + late HttpResponse result; + + int code = 0; + + if (response.statusCode == 200) { + if (compute) { + try { + if (response.data["code"] == 200) { + dynamic data = response.data["data"]; + T bean = DeserializeAction.invokeJson(DeserializeAction(data)); + result = HttpResponse(success: true, code: 200, bean: bean); + } else { + result = HttpResponse(success: false, code: -1000, message: "服务器返回数据异常"); + } + } catch (e) { + result = HttpResponse(success: false, code: -1000, message: "json解析失败"); + } + } + } else { + code = response.statusCode ?? 0; + result = HttpResponse(success: false, code: code, message: response.statusMessage); + } + + return result; + } +} + +class HttpResponse { + late bool success; + String? message; + late int code; + T? bean; + + HttpResponse({required this.success, this.message, required this.code, this.bean}); +} + +class DeserializeAction { + final dynamic json; + + DeserializeAction(this.json); + + T invoke() { + return JsonConversion$Json.fromJson(json); + } + + static dynamic invokeJson(DeserializeAction a) => a.invoke(); +} + +mixin BaseBean { + T fromJson(Map json); +} + +class CronBean with BaseBean { + @override + CronBean fromJson(Map json) { + return CronBean(); + } +} + +void decode() async { + compute(DeserializeAction.invokeJson, DeserializeAction({})); +} diff --git a/lib/base/http/token_interceptor.dart b/lib/base/http/token_interceptor.dart new file mode 100644 index 0000000..f384c98 --- /dev/null +++ b/lib/base/http/token_interceptor.dart @@ -0,0 +1,13 @@ +import 'package:dio/dio.dart'; +import 'package:qinglong_app/main.dart'; + +class TokenInterceptor extends Interceptor { + @override + void onRequest(RequestOptions options, RequestInterceptorHandler handler) { + if (userInfoViewModel.token != null) { + options.headers["Authorization"] = "Bearer " + userInfoViewModel.token!; + } + options.queryParameters["t"] = DateTime.now().millisecondsSinceEpoch; + return handler.next(options); + } +} diff --git a/lib/base/http/url.dart b/lib/base/http/url.dart new file mode 100644 index 0000000..abfb268 --- /dev/null +++ b/lib/base/http/url.dart @@ -0,0 +1,3 @@ +class Url { + static const LOGIN = "api/user/login"; +} diff --git a/lib/base/sp_const.dart b/lib/base/sp_const.dart index 87baf99..bdc6be9 100644 --- a/lib/base/sp_const.dart +++ b/lib/base/sp_const.dart @@ -1 +1,2 @@ -String sp_UserINfo = "userinfo"; \ No newline at end of file +String sp_UserINfo = "userinfo"; +String sp_Host = "host"; \ No newline at end of file diff --git a/lib/base/userinfo_viewmodel.dart b/lib/base/userinfo_viewmodel.dart index a1ba4ba..061d9f8 100644 --- a/lib/base/userinfo_viewmodel.dart +++ b/lib/base/userinfo_viewmodel.dart @@ -1,46 +1,37 @@ -import 'dart:convert'; - -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:qinglong_app/base/base_viewmodel.dart'; import 'package:qinglong_app/utils/sp_utils.dart'; import 'sp_const.dart'; -var userInfoProvider = ChangeNotifierProvider((ref) => UserInfoViewModel()); +class UserInfoViewModel { + String? _token; + String? _host = ""; -class UserInfoViewModel extends ViewModel { - UserInfoBean? _userInfoBean; + static UserInfoViewModel? _userInfoViewModel; - UserInfoViewModel() { + static UserInfoViewModel getInstance() { + _userInfoViewModel ??= UserInfoViewModel._(); + return _userInfoViewModel!; + } + + UserInfoViewModel._() { String userInfoJson = SpUtil.getString(sp_UserINfo); + _host = SpUtil.getString(sp_Host); if (userInfoJson.isNotEmpty) { - _userInfoBean = UserInfoBean.fromJson(jsonDecode(userInfoJson)); + _token = userInfoJson; } } - void updateUserInfoBean(UserInfoBean userInfoBean) { - _userInfoBean = userInfoBean; - SpUtil.putString(sp_UserINfo, jsonEncode(userInfoBean)); + void updateToken(String token) { + _token = token; + SpUtil.putString(sp_UserINfo, token); } - UserInfoBean? get userInfoBean => _userInfoBean; -} - -class UserInfoBean { - String? name; - int? age; - - UserInfoBean({this.name, this.age}); - - UserInfoBean.fromJson(Map json) { - name = json['name']; - age = json['age']; - } - - Map toJson() { - final Map data = new Map(); - data['name'] = this.name; - data['age'] = this.age; - return data; - } + void updateHost(String host) { + _host = host; + SpUtil.putString(sp_Host, host); + } + + String? get token => _token; + + String? get host => _host; } diff --git a/lib/json.dart b/lib/json.dart new file mode 100644 index 0000000..e7ac2f3 --- /dev/null +++ b/lib/json.dart @@ -0,0 +1,4 @@ +import 'package:json_conversion_annotation/json_conversion_annotation.dart'; + +@JsonConversionTarget() +class Json{} \ No newline at end of file diff --git a/lib/json.jc.dart b/lib/json.jc.dart new file mode 100644 index 0000000..55696da --- /dev/null +++ b/lib/json.jc.dart @@ -0,0 +1,43 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +import 'package:qinglong_app/module/login/login_bean.dart'; +import 'package:qinglong_app/module/task/task_bean.dart'; + + +class JsonConversion$Json { + + static M fromJson(dynamic json) { + if (json is List) { + return _getListChildType(json); + } else { + return _fromJsonSingle(json); + } + } + + static M _fromJsonSingle(dynamic json) { + + String type = M.toString(); + + if(type == (LoginBean).toString()){ + return LoginBean.jsonConversion(json) as M; + } + + if(type == (TaskBean).toString()){ + return TaskBean.jsonConversion(json) as M; + } + + throw Exception("not found"); + } + + static M _getListChildType(List data) { + if([] is M){ + return data.map((e) => LoginBean.jsonConversion(e)).toList() as M; + } + + if([] is M){ + return data.map((e) => TaskBean.jsonConversion(e)).toList() as M; + } + + throw Exception("not found"); + } +} diff --git a/lib/main.dart b/lib/main.dart index d072c4c..b978dc9 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:logger/logger.dart'; import 'package:qinglong_app/base/theme.dart'; import 'package:qinglong_app/module/login/login_page.dart'; @@ -10,12 +11,18 @@ import 'base/routes.dart'; import 'base/userinfo_viewmodel.dart'; import 'module/home/home_page.dart'; +late UserInfoViewModel userInfoViewModel; + +var logger = Logger(); + void main() { + + WidgetsFlutterBinding.ensureInitialized(); + userInfoViewModel = UserInfoViewModel.getInstance(); runApp( ProviderScope( overrides: [ themeProvider, - userInfoProvider, ], child: const MyApp(), ), @@ -42,7 +49,7 @@ class MyApp extends ConsumerWidget { return Routes.generateRoute(setting); }, // home: ref.read(userInfoProvider).userInfoBean != null ? const HomePage() : LoginPage(), - home: HomePage(), + home: LoginPage(), ), ); } diff --git a/lib/module/login/login_bean.dart b/lib/module/login/login_bean.dart new file mode 100644 index 0000000..9cb4ac4 --- /dev/null +++ b/lib/module/login/login_bean.dart @@ -0,0 +1,42 @@ +import 'package:json_conversion_annotation/json_conversion_annotation.dart'; + +@JsonConversion() +class LoginBean { + String? token; + String? lastip; + String? lastaddr; + int? lastlogon; + int? retries; + String? platform; + + LoginBean( + {this.token, + this.lastip, + this.lastaddr, + this.lastlogon, + this.retries, + this.platform}); + + LoginBean.fromJson(Map json) { + token = json['token']; + lastip = json['lastip']; + lastaddr = json['lastaddr']; + lastlogon = json['lastlogon']; + retries = json['retries']; + platform = json['platform']; + } + + Map toJson() { + final Map data = new Map(); + data['token'] = this.token; + data['lastip'] = this.lastip; + data['lastaddr'] = this.lastaddr; + data['lastlogon'] = this.lastlogon; + data['retries'] = this.retries; + data['platform'] = this.platform; + return data; + } + static LoginBean jsonConversion(Map json) { + return LoginBean.fromJson(json); + } +} diff --git a/lib/module/login/login_page.dart b/lib/module/login/login_page.dart index 082db33..e0be585 100644 --- a/lib/module/login/login_page.dart +++ b/lib/module/login/login_page.dart @@ -1,8 +1,9 @@ +import 'package:dio_log/dio_log.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:qinglong_app/base/common_dialog.dart'; import 'package:qinglong_app/base/routes.dart'; +import 'package:qinglong_app/main.dart'; import 'package:qinglong_app/module/login/login_viewmodel.dart'; import 'package:qinglong_app/utils/utils.dart'; @@ -14,9 +15,16 @@ class LoginPage extends StatefulWidget { } class _LoginPageState extends State { + final TextEditingController _hostController = TextEditingController(text: userInfoViewModel.host); final TextEditingController _userNameController = TextEditingController(); final TextEditingController _passwordController = TextEditingController(); + @override + void initState() { + super.initState(); + showDebugBtn(context, btnColor: Colors.blue); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -39,6 +47,41 @@ class _LoginPageState extends State { SizedBox( height: MediaQuery.of(context).size.height / 3, ), + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 15, + ), + child: Row( + children: [ + const SizedBox( + child: Text( + "域名:", + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + width: 60, + ), + const SizedBox( + width: 15, + ), + Expanded( + child: TextField( + onChanged: (_) { + setState(() {}); + }, + controller: _hostController, + decoration: const InputDecoration( + contentPadding: EdgeInsets.fromLTRB(0, 5, 0, 5), + hintText: "http://1.1.1.1:5700", + ), + autofocus: false, + ), + ), + ], + ), + ), Padding( padding: const EdgeInsets.symmetric( horizontal: 15, @@ -60,6 +103,7 @@ class _LoginPageState extends State { ), Expanded( child: TextField( + onChanged: (_) { setState(() {}); }, @@ -117,7 +161,7 @@ class _LoginPageState extends State { SizedBox( width: MediaQuery.of(context).size.width - 30, child: CupertinoButton( - color: (_userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty && !model.isLoading) + color: (_hostController.text.isNotEmpty && _userNameController.text.isNotEmpty && _passwordController.text.isNotEmpty && !model.isLoading) ? Theme.of(context).primaryColor : Theme.of(context).primaryColor.withOpacity(0.3), child: model.isLoading @@ -131,6 +175,7 @@ class _LoginPageState extends State { onPressed: () { if (model.isLoading) return; Utils.hideKeyBoard(context); + userInfoViewModel.updateHost(_hostController.text); model.login(_userNameController.text, _passwordController.text); }), ), diff --git a/lib/module/login/login_viewmodel.dart b/lib/module/login/login_viewmodel.dart index 72b98a7..062fefd 100644 --- a/lib/module/login/login_viewmodel.dart +++ b/lib/module/login/login_viewmodel.dart @@ -1,19 +1,41 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:qinglong_app/base/base_viewmodel.dart'; +import 'package:qinglong_app/base/http/http.dart'; +import 'package:qinglong_app/base/http/url.dart'; +import 'package:qinglong_app/main.dart'; + +import 'login_bean.dart'; var loginProvider = ChangeNotifierProvider((ref) => LoginViewModel()); class LoginViewModel extends ViewModel { bool loginSuccess = false; bool isLoading = false; + String msg = ""; - void login(String userName, String password) { + void login(String userName, String password) async { isLoading = true; + loginSuccess = false; + msg = ""; + notifyListeners(); - Future.delayed(Duration(seconds: 2), () { - isLoading = false; + HttpResponse response = await Http.post( + Url.LOGIN, + { + "username": userName, + "password": password, + }, + ); + + if (response.success) { + userInfoViewModel.updateToken(response.bean?.token ?? ""); loginSuccess = true; - notifyListeners(); - }); + isLoading = false; + } else { + isLoading = false; + loginSuccess = false; + msg = response.message ?? ""; + } + notifyListeners(); } } diff --git a/lib/module/task/task_bean.dart b/lib/module/task/task_bean.dart new file mode 100644 index 0000000..ba65f7b --- /dev/null +++ b/lib/module/task/task_bean.dart @@ -0,0 +1,79 @@ +import 'package:json_conversion_annotation/json_conversion_annotation.dart'; + +@JsonConversion() +class TaskBean { + String? name; + String? command; + String? schedule; + bool? saved; + String? sId; + int? created; + int? status; + String? timestamp; + int? isSystem; + int? isDisabled; + String? logPath; + int? isPinned; + int? lastExecutionTime; + int? lastRunningTime; + String? pid; + + TaskBean( + {this.name, + this.command, + this.schedule, + this.saved, + this.sId, + this.created, + this.status, + this.timestamp, + this.isSystem, + this.isDisabled, + this.logPath, + this.isPinned, + this.lastExecutionTime, + this.lastRunningTime, + this.pid}); + + TaskBean.fromJson(Map json) { + name = json['name']; + command = json['command']; + schedule = json['schedule']; + saved = json['saved']; + sId = json['_id']; + created = json['created']; + status = json['status']; + timestamp = json['timestamp']; + isSystem = json['isSystem']; + isDisabled = json['isDisabled']; + logPath = json['log_path']; + isPinned = json['isPinned']; + lastExecutionTime = json['last_execution_time']; + lastRunningTime = json['last_running_time']; + pid = json['pid']; + } + + Map toJson() { + final Map data = new Map(); + data['name'] = this.name; + data['command'] = this.command; + data['schedule'] = this.schedule; + data['saved'] = this.saved; + data['_id'] = this.sId; + data['created'] = this.created; + data['status'] = this.status; + data['timestamp'] = this.timestamp; + data['isSystem'] = this.isSystem; + data['isDisabled'] = this.isDisabled; + data['log_path'] = this.logPath; + data['isPinned'] = this.isPinned; + data['last_execution_time'] = this.lastExecutionTime; + data['last_running_time'] = this.lastRunningTime; + data['pid'] = this.pid; + return data; + } + + static TaskBean jsonConversion(Map json) { + return TaskBean.fromJson(json); + } +} diff --git a/pubspec.lock b/pubspec.lock index cda6fb8..d56219e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,27 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + url: "https://pub.flutter-io.cn" + source: hosted + version: "22.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.7.2" + args: + dependency: transitive + description: + name: args + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.3.0" async: dependency: transitive description: @@ -22,6 +43,62 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" + build: + dependency: transitive + description: + name: build + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.2.1" + build_config: + dependency: transitive + description: + name: build_config + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.4" + build_runner: + dependency: "direct dev" + description: + name: build_runner + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.7" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + url: "https://pub.flutter-io.cn" + source: hosted + version: "7.2.3" + built_collection: + dependency: transitive + description: + name: built_collection + url: "https://pub.flutter-io.cn" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + url: "https://pub.flutter-io.cn" + source: hosted + version: "8.1.3" characters: dependency: transitive description: @@ -36,6 +113,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.3.1" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.1" + cli_util: + dependency: transitive + description: + name: cli_util + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.5" clock: dependency: transitive description: @@ -43,6 +134,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.1.0" + code_builder: + dependency: transitive + description: + name: code_builder + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.1.0" collection: dependency: transitive description: @@ -50,6 +148,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.15.0" + convert: + dependency: transitive + description: + name: convert + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.1" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.1" cupertino_icons: dependency: "direct main" description: @@ -57,6 +169,27 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.4" + dart_style: + dependency: transitive + description: + name: dart_style + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.1" + dio: + dependency: "direct main" + description: + name: dio + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.0.4" + dio_log: + dependency: "direct main" + description: + name: dio_log + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.2" fake_async: dependency: transitive description: @@ -78,6 +211,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "6.1.2" + fixnum: + dependency: transitive + description: + name: fixnum + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.0" flutter: dependency: "direct main" description: flutter @@ -114,6 +254,48 @@ packages: description: flutter source: sdk version: "0.0.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.2" + glob: + dependency: transitive + description: + name: glob + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.2" + graphs: + dependency: transitive + description: + name: graphs + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.0.1" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.0.0" + io: + dependency: transitive + description: + name: io + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.3" js: dependency: transitive description: @@ -121,6 +303,27 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.6.3" + json_annotation: + dependency: transitive + description: + name: json_annotation + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.4.0" + json_conversion: + dependency: "direct dev" + description: + name: json_conversion + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.4" + json_conversion_annotation: + dependency: "direct main" + description: + name: json_conversion_annotation + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.0.4" lints: dependency: transitive description: @@ -128,6 +331,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.0.1" + logger: + dependency: "direct main" + description: + name: logger + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.1.0" + logging: + dependency: transitive + description: + name: logging + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.2" matcher: dependency: transitive description: @@ -142,6 +359,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.7.0" + mime: + dependency: transitive + description: + name: mime + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" + package_config: + dependency: transitive + description: + name: package_config + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.2" path: dependency: transitive description: @@ -170,6 +401,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.5" + pedantic: + dependency: transitive + description: + name: pedantic + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.11.1" platform: dependency: transitive description: @@ -184,6 +422,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.2" + pool: + dependency: transitive + description: + name: pool + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.5.0" process: dependency: transitive description: @@ -191,6 +436,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "4.2.4" + pub_semver: + dependency: transitive + description: + name: pub_semver + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" riverpod: dependency: transitive description: @@ -254,11 +513,32 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.0.4" + shelf: + dependency: transitive + description: + name: shelf + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.2.0" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" sky_engine: dependency: transitive description: flutter source: sdk version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.3" source_span: dependency: transitive description: @@ -287,6 +567,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.0" + stream_transform: + dependency: transitive + description: + name: stream_transform + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.0.0" string_scanner: dependency: transitive description: @@ -315,6 +602,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.4.3" + timing: + dependency: transitive + description: + name: timing + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.0" typed_data: dependency: transitive description: @@ -329,6 +623,20 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.1.1" + watcher: + dependency: transitive + description: + name: watcher + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + url: "https://pub.flutter-io.cn" + source: hosted + version: "2.1.0" win32: dependency: transitive description: @@ -343,6 +651,13 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.2.0" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.1.0" sdks: dart: ">=2.15.1 <3.0.0" flutter: ">=2.5.0" diff --git a/pubspec.yaml b/pubspec.yaml index 06027ad..46b993d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,8 +17,14 @@ dependencies: synchronized: ^3.0.0 back_button_interceptor: ^5.0.2 flutter_slidable: ^1.2.0 + dio: ^4.0.4 + dio_log: ^2.0.2 + json_conversion_annotation: ^0.0.4 + logger: ^1.1.0 dev_dependencies: + build_runner: ^2.0.0 + json_conversion: ^0.0.4 flutter_test: sdk: flutter diff --git a/test/widget_test.dart b/test/widget_test.dart index c274535..51f9fdc 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -7,24 +7,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:qinglong_app/base/http/http.dart'; +import 'package:qinglong_app/base/userinfo_viewmodel.dart'; import 'package:qinglong_app/main.dart'; +import 'package:qinglong_app/module/login/login_bean.dart'; +import 'package:qinglong_app/module/login/login_viewmodel.dart'; void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(const MyApp()); - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); }