feat: 接口服务、主页页面开发
This commit is contained in:
parent
422e6a0291
commit
4e8e860810
@ -1,29 +1,55 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
<application android:label="@string/app_name" android:name="${applicationName}" android:icon="@mipmap/ic_launcher">
|
xmlns:tools="http://schemas.android.com/tools">
|
||||||
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
|
|
||||||
<!-- Specifies an Android theme to apply to this Activity as soon as
|
|
||||||
the Android process has started. This theme is visible to the user
|
|
||||||
while the Flutter UI initializes. After that, this theme continues
|
|
||||||
to determine the Window background behind the Flutter UI. -->
|
|
||||||
<meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme"/>
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<!-- Don't delete the meta-data below.
|
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
|
||||||
<meta-data android:name="flutterEmbedding" android:value="2"/>
|
|
||||||
</application>
|
|
||||||
<!-- Required to query activities that can process text, see:
|
|
||||||
https://developer.android.com/training/package-visibility?hl=en and
|
|
||||||
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
|
||||||
|
|
||||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
|
||||||
<queries>
|
|
||||||
<intent>
|
<!--允许访问网络,必选权限-->
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
<data android:mimeType="text/plain"/>
|
<!-- 写权限 -->
|
||||||
</intent>
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
</queries>
|
<!-- 读权限 -->
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
|
||||||
|
|
||||||
|
<application
|
||||||
|
android:name="${applicationName}"
|
||||||
|
android:icon="@mipmap/ic_launcher"
|
||||||
|
android:label="@string/app_name">
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||||
|
android:exported="true"
|
||||||
|
android:hardwareAccelerated="true"
|
||||||
|
android:launchMode="singleTop"
|
||||||
|
android:theme="@style/LaunchTheme"
|
||||||
|
android:windowSoftInputMode="adjustResize">
|
||||||
|
<!-- Specifies an Android theme to apply to this Activity as soon as
|
||||||
|
the Android process has started. This theme is visible to the user
|
||||||
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
|
to determine the Window background behind the Flutter UI. -->
|
||||||
|
<meta-data
|
||||||
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
|
android:resource="@style/NormalTheme" />
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<!-- Don't delete the meta-data below.
|
||||||
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
|
<meta-data
|
||||||
|
android:name="flutterEmbedding"
|
||||||
|
android:value="2" />
|
||||||
|
</application>
|
||||||
|
<!-- Required to query activities that can process text, see:
|
||||||
|
https://developer.android.com/training/package-visibility?hl=en and
|
||||||
|
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
|
||||||
|
|
||||||
|
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||||
|
<queries>
|
||||||
|
<intent>
|
||||||
|
<action android:name="android.intent.action.PROCESS_TEXT" />
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
|
</intent>
|
||||||
|
</queries>
|
||||||
</manifest>
|
</manifest>
|
||||||
3
lib/api/api_path.dart
Normal file
3
lib/api/api_path.dart
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
class ApiPath {
|
||||||
|
static const String login = "/auth/login";
|
||||||
|
}
|
||||||
51
lib/api/api_response.dart
Normal file
51
lib/api/api_response.dart
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
class ApiResponse<T> {
|
||||||
|
final bool success;
|
||||||
|
final T? data;
|
||||||
|
final String? message;
|
||||||
|
final int? statusCode;
|
||||||
|
|
||||||
|
// 构造函数
|
||||||
|
const ApiResponse({
|
||||||
|
required this.success,
|
||||||
|
this.data,
|
||||||
|
this.message,
|
||||||
|
this.statusCode,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 成功响应
|
||||||
|
factory ApiResponse.success(T data,
|
||||||
|
{String message = 'Success', int? statusCode}) {
|
||||||
|
return ApiResponse<T>(
|
||||||
|
success: true,
|
||||||
|
data: data,
|
||||||
|
message: message,
|
||||||
|
statusCode: statusCode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 失败响应
|
||||||
|
factory ApiResponse.error(String message, {int? statusCode, T? data}) {
|
||||||
|
return ApiResponse<T>(
|
||||||
|
success: false,
|
||||||
|
message: message,
|
||||||
|
statusCode: statusCode,
|
||||||
|
data: data, // 可选:返回部分数据(如错误时的缓存数据)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载中(可选)
|
||||||
|
factory ApiResponse.loading() {
|
||||||
|
return ApiResponse<T>(
|
||||||
|
success: false,
|
||||||
|
message: 'Loading...',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [success, data, message, statusCode];
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ApiResponse(success: $success, message: $message, data: $data, statusCode: $statusCode)';
|
||||||
|
}
|
||||||
|
}
|
||||||
85
lib/api/base_api_service.dart
Normal file
85
lib/api/base_api_service.dart
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// api/service/user_api_service.dart
|
||||||
|
import 'package:dio/dio.dart' as dioAlias;
|
||||||
|
import 'package:starwork_flutter/api/api_response.dart';
|
||||||
|
import 'package:starwork_flutter/flavors.dart';
|
||||||
|
|
||||||
|
class BaseApiService {
|
||||||
|
final dioAlias.Dio dio = dioAlias.Dio();
|
||||||
|
|
||||||
|
BaseApiService() {
|
||||||
|
dio.options.baseUrl = F.apiHost;
|
||||||
|
dio.options.connectTimeout = const Duration(seconds: 30);
|
||||||
|
dio.options.receiveTimeout = const Duration(seconds: 30);
|
||||||
|
// 可添加拦截器、token 等
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 统一请求方法(私有,但子类可用)
|
||||||
|
Future<ApiResponse<T>> makeRequest<T>({
|
||||||
|
required String path,
|
||||||
|
String method = 'GET',
|
||||||
|
dynamic data,
|
||||||
|
Map<String, dynamic>? queryParameters,
|
||||||
|
required T Function(dynamic) fromJson,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
dioAlias.Response response;
|
||||||
|
|
||||||
|
switch (method.toUpperCase()) {
|
||||||
|
case 'GET':
|
||||||
|
response = await dio.get(path, queryParameters: queryParameters);
|
||||||
|
break;
|
||||||
|
case 'POST':
|
||||||
|
response = await dio.post(path,
|
||||||
|
data: data, queryParameters: queryParameters);
|
||||||
|
break;
|
||||||
|
case 'PUT':
|
||||||
|
response =
|
||||||
|
await dio.put(path, data: data, queryParameters: queryParameters);
|
||||||
|
break;
|
||||||
|
case 'DELETE':
|
||||||
|
response = await dio.delete(path,
|
||||||
|
data: data, queryParameters: queryParameters);
|
||||||
|
break;
|
||||||
|
case 'PATCH':
|
||||||
|
response = await dio.patch(path,
|
||||||
|
data: data, queryParameters: queryParameters);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return ApiResponse.error('Unsupported method: $method');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.statusCode! >= 200 && response.statusCode! < 300) {
|
||||||
|
final parsedData = fromJson(response.data);
|
||||||
|
return ApiResponse.success(
|
||||||
|
parsedData,
|
||||||
|
statusCode: response.statusCode,
|
||||||
|
message: 'Success',
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return ApiResponse.error(
|
||||||
|
response.statusMessage ?? 'Request failed',
|
||||||
|
statusCode: response.statusCode,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} on dioAlias.DioException catch (e) {
|
||||||
|
String message = 'Unknown error';
|
||||||
|
int? statusCode = e.response?.statusCode;
|
||||||
|
|
||||||
|
if (e.type == dioAlias.DioExceptionType.connectionTimeout) {
|
||||||
|
message = 'Connection timeout';
|
||||||
|
} else if (e.type == dioAlias.DioExceptionType.receiveTimeout) {
|
||||||
|
message = 'Server timeout';
|
||||||
|
} else if (e.type == dioAlias.DioExceptionType.badResponse) {
|
||||||
|
message = e.response?.statusMessage ?? 'Bad response';
|
||||||
|
} else if (e.type == dioAlias.DioExceptionType.connectionError) {
|
||||||
|
message = 'Network not available';
|
||||||
|
} else {
|
||||||
|
message = e.message ?? 'Something went wrong';
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApiResponse.error(message, statusCode: statusCode);
|
||||||
|
} catch (e) {
|
||||||
|
return ApiResponse.error('Unexpected error: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
lib/api/model/user/user_model.dart
Normal file
24
lib/api/model/user/user_model.dart
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
class UserModel {
|
||||||
|
final int id;
|
||||||
|
final String name;
|
||||||
|
final String email;
|
||||||
|
|
||||||
|
UserModel({required this.id, required this.name, required this.email});
|
||||||
|
|
||||||
|
factory UserModel.fromJson(Map<String, dynamic> json) {
|
||||||
|
return UserModel(
|
||||||
|
id: json['id'],
|
||||||
|
name: json['name'],
|
||||||
|
email: json['email'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return {
|
||||||
|
'id': id,
|
||||||
|
'name': name,
|
||||||
|
'email': email,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
18
lib/api/service/user_api_service.dart
Normal file
18
lib/api/service/user_api_service.dart
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:starwork_flutter/api/api_response.dart';
|
||||||
|
import 'package:starwork_flutter/api/base_api_service.dart';
|
||||||
|
import 'package:starwork_flutter/api/model/user/user_model.dart';
|
||||||
|
|
||||||
|
class UserApiService {
|
||||||
|
final BaseApiService _api = BaseApiService();
|
||||||
|
|
||||||
|
Future<ApiResponse<UserModel>> login(Map<String, dynamic> userData) {
|
||||||
|
return _api.makeRequest(
|
||||||
|
// 通过实例调用
|
||||||
|
path: '/login',
|
||||||
|
method: 'POST',
|
||||||
|
data: userData,
|
||||||
|
fromJson: (data) => UserModel.fromJson(data),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -42,7 +42,7 @@ class App extends StatelessWidget {
|
|||||||
fallbackLocale: const Locale('zh', 'CN'),
|
fallbackLocale: const Locale('zh', 'CN'),
|
||||||
// 必须设置 fallback 没有该语言时使用
|
// 必须设置 fallback 没有该语言时使用
|
||||||
getPages: AppPages.pages,
|
getPages: AppPages.pages,
|
||||||
initialRoute: AppRoutes.login,
|
initialRoute: AppRoutes.main,
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
import 'package:starwork_flutter/api/base_api_service.dart';
|
||||||
|
import 'package:starwork_flutter/api/service/user_api_service.dart';
|
||||||
import 'package:starwork_flutter/common/utils/shared_preferences_utils.dart';
|
import 'package:starwork_flutter/common/utils/shared_preferences_utils.dart';
|
||||||
import 'package:starwork_flutter/i18n/app_i18n.dart';
|
import 'package:starwork_flutter/i18n/app_i18n.dart';
|
||||||
|
|
||||||
@ -15,6 +17,8 @@ class AppInitialization {
|
|||||||
setSystemStatusBar();
|
setSystemStatusBar();
|
||||||
// 初始化 SharedPreferences
|
// 初始化 SharedPreferences
|
||||||
await SharedPreferencesUtils.init();
|
await SharedPreferencesUtils.init();
|
||||||
|
// 初始化api服务(单例)
|
||||||
|
Get.put(BaseApiService(),permanent: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setSystemStatusBar() {
|
static void setSystemStatusBar() {
|
||||||
|
|||||||
23
lib/base/app_permission.dart
Normal file
23
lib/base/app_permission.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
|
class AppPermission {
|
||||||
|
// 检查权限
|
||||||
|
static Future<bool> checkPermission({required Permission permission}) async {
|
||||||
|
var status = await permission.status;
|
||||||
|
return status == PermissionStatus.granted;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量检查权限
|
||||||
|
static Future<bool> checkPermissions({
|
||||||
|
required List<Permission> permissions,
|
||||||
|
}) async {
|
||||||
|
if (permissions.isEmpty) return false;
|
||||||
|
Map<Permission, PermissionStatus> statuses = await permissions.request();
|
||||||
|
for (var status in statuses.values) {
|
||||||
|
if (status != PermissionStatus.granted) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,16 @@
|
|||||||
|
import 'package:get/get.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
import 'package:starwork_flutter/base/app_permission.dart';
|
||||||
import 'package:starwork_flutter/base/base_controller.dart';
|
import 'package:starwork_flutter/base/base_controller.dart';
|
||||||
|
|
||||||
class HomeController extends BaseController {
|
class HomeController extends BaseController {
|
||||||
|
final isOpenNotificationPermission = false.obs;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onInit() async {
|
||||||
|
super.onInit();
|
||||||
|
isOpenNotificationPermission.value = await AppPermission.checkPermission(
|
||||||
|
permission: Permission.notification,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
import 'package:starwork_flutter/base/app_permission.dart';
|
||||||
|
|
||||||
import 'home_controller.dart';
|
import 'home_controller.dart';
|
||||||
|
|
||||||
@ -9,20 +12,76 @@ class HomeView extends GetView<HomeController> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
body: SafeArea(
|
||||||
title: const Text('HomeView'),
|
child: Container(
|
||||||
centerTitle: true,
|
width: 1.sw,
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 15.w),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_buildPageHead(),
|
||||||
|
_buildSystemNotificationPermissionRow(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
body: Center(
|
);
|
||||||
child: ElevatedButton(
|
}
|
||||||
onPressed: () {
|
|
||||||
if (Get.locale?.languageCode == 'zh') {
|
_buildPageHead() {
|
||||||
Get.updateLocale(const Locale('en', 'US'));
|
return Row(
|
||||||
} else {
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
Get.updateLocale(const Locale('zh', 'CN'));
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
}
|
children: [
|
||||||
},
|
Row(
|
||||||
child: Text('切换成英语${'路由'.tr}')),
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'19104656的互联',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18.sp,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.arrow_right_rounded,
|
||||||
|
size: 24.sp,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Icon(
|
||||||
|
Icons.add_circle_outline_rounded,
|
||||||
|
size: 24.sp,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildSystemNotificationPermissionRow() {
|
||||||
|
return Visibility(
|
||||||
|
visible: !controller.isOpenNotificationPermission.value,
|
||||||
|
child: Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: Color(0xFFfdefdf),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'系统通知未开启,报警消息无法通知'.tr,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Color(0xFFea8720),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
child: Text(
|
||||||
|
'去开启'.tr,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,16 @@
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:starwork_flutter/views/home/home_controller.dart';
|
||||||
import 'package:starwork_flutter/views/login/login_controller.dart';
|
import 'package:starwork_flutter/views/login/login_controller.dart';
|
||||||
import 'package:starwork_flutter/views/main/main_controller.dart';
|
import 'package:starwork_flutter/views/main/main_controller.dart';
|
||||||
|
import 'package:starwork_flutter/views/messages/messages_controller.dart';
|
||||||
|
import 'package:starwork_flutter/views/mine/mine_controller.dart';
|
||||||
|
|
||||||
class MainBinding extends Bindings {
|
class MainBinding extends Bindings {
|
||||||
@override
|
@override
|
||||||
void dependencies() {
|
void dependencies() {
|
||||||
Get.lazyPut<MainController>(() => MainController());
|
Get.lazyPut<MainController>(() => MainController());
|
||||||
|
Get.lazyPut<HomeController>(() => HomeController());
|
||||||
|
Get.lazyPut<MessagesController>(() => MessagesController());
|
||||||
|
Get.lazyPut<MineController>(() => MineController());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
pubspec.lock
32
pubspec.lock
@ -81,6 +81,22 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.8"
|
version: "1.0.8"
|
||||||
|
dio:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: dio
|
||||||
|
sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "5.9.0"
|
||||||
|
dio_web_adapter:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: dio_web_adapter
|
||||||
|
sha256: "7586e476d70caecaf1686d21eee7247ea43ef5c345eab9e0cc3583ff13378d78"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -165,6 +181,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.7.2"
|
version: "4.7.2"
|
||||||
|
http_parser:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: http_parser
|
||||||
|
sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "4.0.2"
|
||||||
image:
|
image:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -253,6 +277,14 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.11.0"
|
version: "1.11.0"
|
||||||
|
mime:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: mime
|
||||||
|
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.0"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -29,6 +29,8 @@ dependencies:
|
|||||||
fluttertoast: ^8.2.8
|
fluttertoast: ^8.2.8
|
||||||
# 验证码输入框
|
# 验证码输入框
|
||||||
pinput: ^5.0.1
|
pinput: ^5.0.1
|
||||||
|
# 网络请求库
|
||||||
|
dio: ^5.9.0
|
||||||
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user