Browse Source

增加网络请求框架

ios
Jolie 4 months ago
parent
commit
ba8f306dbb
18 changed files with 1579 additions and 112 deletions
  1. BIN
      assets/images/login_logo.png
  2. 1
      ios/Flutter/Debug.xcconfig
  3. 1
      ios/Flutter/Release.xcconfig
  4. 49
      lib/config/env_config.dart
  5. 7
      lib/generated/assets.dart
  6. 165
      lib/main.dart
  7. 20
      lib/network/api_service.dart
  8. 96
      lib/network/api_service.g.dart
  9. 4
      lib/network/index.dart
  10. 169
      lib/network/network_config.dart
  11. 189
      lib/network/network_service.dart
  12. 92
      lib/network/response_model.dart
  13. 17
      lib/network/user_api.dart
  14. 97
      lib/network/user_api.g.dart
  15. 15
      lib/pages/main_page.dart
  16. 15
      lib/pages/mine/login_page.dart
  17. 732
      pubspec.lock
  18. 22
      pubspec.yaml

BIN
assets/images/login_logo.png

Before After
Width: 572  |  Height: 256  |  Size: 30 KiB

1
ios/Flutter/Debug.xcconfig

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"

1
ios/Flutter/Release.xcconfig

@ -1 +1,2 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"

49
lib/config/env_config.dart

@ -0,0 +1,49 @@
import 'package:flutter/foundation.dart';
///
enum Environment { dev, release }
///
class EnvConfig {
//
static Environment current = Environment.dev; //
//
static const Map<String, String> _devConfig = {
'mainBaseUrl': 'https://dating-agency-api-test.qniao.cn',
'fileBaseUrl': 'https://dating-agency-api-test.qniao.cn',
};
//
static const Map<String, String> _releaseConfig = {
'mainBaseUrl': 'https://dating-agency-api-test.qniao.cn',
'fileBaseUrl': 'https://dating-agency-api-test.qniao.cn',
};
///
static String get(String key) {
return (current == Environment.dev
? _devConfig[key]
: _releaseConfig[key]) ??
'';
}
/// API的baseUrl
static String get mainBaseUrl {
return current == Environment.dev
? _devConfig['mainBaseUrl']!
: _releaseConfig['mainBaseUrl']!;
}
/// API的baseUrl
static String get fileBaseUrl {
return current == Environment.dev
? _devConfig['fileBaseUrl']!
: _releaseConfig['fileBaseUrl']!;
}
///
static void setEnvironment(Environment env) {
current = env;
}
}

7
lib/generated/assets.dart

@ -0,0 +1,7 @@
///This file is automatically generated. DO NOT EDIT, all your changes would be lost.
class Assets {
Assets._();
static const String imagesLoginLogo = 'assets/images/login_logo.png';
}

165
lib/main.dart

@ -1,122 +1,71 @@
import 'dart:io';
import 'package:dating_touchme_app/config/env_config.dart';
import 'package:dating_touchme_app/pages/main_page.dart';
import 'package:dating_touchme_app/pages/mine/login_page.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
void main() {
runApp(const MyApp());
}
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// GetStorage
await GetStorage.init();
class MyApp extends StatelessWidget {
const MyApp({super.key});
// - release模式
EnvConfig.setEnvironment(Environment.dev);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// TRY THIS: Try running your application with "flutter run". You'll see
// the application has a purple toolbar. Then, without quitting the app,
// try changing the seedColor in the colorScheme below to Colors.green
// and then invoke "hot reload" (save your changes or press the "hot
// reload" button in a Flutter-supported IDE, or press "r" if you used
// the command line to start the app).
//
// Notice that the counter didn't reset back to zero; the application
// state is not lost during the reload. To reset the state, use hot
// restart instead.
//
// This works for code too, not just values: Most code changes can be
// tested with just a hot reload.
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.light,
systemNavigationBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.dark,
),
);
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
if (Platform.isIOS) {
SystemChrome.setEnabledSystemUIMode(
SystemUiMode.manual,
overlays: [SystemUiOverlay.top],
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
runApp(
GetMaterialApp(
locale: Get.locale, // 使GetX的locale
supportedLocales: const [Locale('zh', 'CN')],
// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.
// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
///
localizationsDelegates: const [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate, // iOS
],
builder: FlutterSmartDialog.init(),
home: MyApp(),
),
);
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// TRY THIS: Try changing the color here to a specific color (to
// Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
// change color while the other colors stay the same.
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also a layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
//
// TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
// action in the IDE, or press "p" in the console), to see the
// wireframe for each widget.
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
ScreenUtil.init(context, designSize: const Size(375, 812));
// token是否为空
final storage = GetStorage();
final token = storage.read<String>('token');
// token为空
return token == null || token.isEmpty ? const LoginPage() : MainPage();
}
}

20
lib/network/api_service.dart

@ -0,0 +1,20 @@
import 'package:retrofit/retrofit.dart';
import 'package:dio/dio.dart';
part 'api_service.g.dart';
@RestApi(baseUrl: 'https://api.example.com/')
abstract class ApiService {
factory ApiService(Dio dio) = _ApiService;
@GET("{path}")
Future<HttpResponse<dynamic>> get(
@Path("path") String path,
);
@POST("{path}")
Future<HttpResponse<dynamic>> post(
@Path("path") String path,
@Body() dynamic data,
);
}

96
lib/network/api_service.g.dart

@ -0,0 +1,96 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'api_service.dart';
// dart format off
// **************************************************************************
// RetrofitGenerator
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations,unused_element_parameter,avoid_unused_constructor_parameters,unreachable_from_main
class _ApiService implements ApiService {
_ApiService(this._dio, {this.baseUrl, this.errorLogger}) {
baseUrl ??= 'https://api.example.com/';
}
final Dio _dio;
String? baseUrl;
final ParseErrorLogger? errorLogger;
@override
Future<HttpResponse<dynamic>> get(String path) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<HttpResponse<dynamic>>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'${path}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch(_options);
final _value = _result.data;
final httpResponse = HttpResponse(_value, _result);
return httpResponse;
}
@override
Future<HttpResponse<dynamic>> post(String path, dynamic data) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = data;
final _options = _setStreamType<HttpResponse<dynamic>>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'${path}',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch(_options);
final _value = _result.data;
final httpResponse = HttpResponse(_value, _result);
return httpResponse;
}
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
if (T != dynamic &&
!(requestOptions.responseType == ResponseType.bytes ||
requestOptions.responseType == ResponseType.stream)) {
if (T == String) {
requestOptions.responseType = ResponseType.plain;
} else {
requestOptions.responseType = ResponseType.json;
}
}
return requestOptions;
}
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}
final url = Uri.parse(baseUrl);
if (url.isAbsolute) {
return url.toString();
}
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
}
}
// dart format on

4
lib/network/index.dart

@ -0,0 +1,4 @@
export 'api_service.dart';
export 'network_config.dart';
export 'network_service.dart';
export 'response_model.dart';

169
lib/network/network_config.dart

@ -0,0 +1,169 @@
import 'package:dio/dio.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart' hide Response;
import 'package:get_storage/get_storage.dart';
import '../config/env_config.dart';
import '../pages/mine/login_page.dart';
/// API类型枚举baseUrl
enum ApiType {
main, // API
file, // API
}
///
class NetworkConfig {
static const int connectTimeout = 30000;
static const int receiveTimeout = 30000;
/// API类型创建不同的Dio实例
static Dio createDio({ApiType type = ApiType.main}) {
// baseUrl
String currentBaseUrl;
switch (type) {
case ApiType.main:
currentBaseUrl = EnvConfig.mainBaseUrl;
break;
case ApiType.file:
currentBaseUrl = EnvConfig.fileBaseUrl;
break;
}
final dio = Dio(
BaseOptions(
baseUrl: currentBaseUrl,
connectTimeout: Duration(milliseconds: connectTimeout),
receiveTimeout: Duration(milliseconds: receiveTimeout),
contentType: 'application/json',
responseType: ResponseType.json,
),
);
//
dio.interceptors.add(AuthInterceptor());
//
dio.interceptors.add(ResponseInterceptor());
//
dio.interceptors.add(LogInterceptor(
requestBody: true,
responseBody: true,
error: true,
));
return dio;
}
}
///
class AuthInterceptor extends Interceptor {
@override
void onRequest(
RequestOptions options,
RequestInterceptorHandler handler,
) async {
// token等认证信息
final token = _getToken();
if (token != null && token.isNotEmpty) {
options.headers['Authorization'] = 'Bearer $token';
}
//
options.headers['X-APP-ID'] = '';
handler.next(options);
}
String? _getToken() {
// token
// 使get_storage或其他存储方式
return GetStorage().read('token');
}
}
///
class ResponseInterceptor extends Interceptor {
@override
void onResponse(
Response response,
ResponseInterceptorHandler handler,
) {
//
final data = response.data;
//
if (response.statusCode == 200) {
// {"code": 0, "message": "success", "data": {...}}
if (data is Map<String, dynamic>) {
final code = data['code'] ?? 0;
if (code == 0) {
//
handler.next(response);
} else {
//
final message = data['message'] ?? '请求失败';
_showError(message);
handler.reject(DioException(
requestOptions: response.requestOptions,
error: message,
type: DioExceptionType.badResponse,
));
}
} else {
handler.next(response);
}
} else {
handler.next(response);
}
}
@override
void onError(DioException err, ErrorInterceptorHandler handler) {
//
String errorMessage = '网络请求失败';
switch (err.type) {
case DioExceptionType.connectionTimeout:
case DioExceptionType.sendTimeout:
case DioExceptionType.receiveTimeout:
errorMessage = '网络连接超时,请检查网络';
break;
case DioExceptionType.badResponse:
if (err.response?.statusCode == 401) {
errorMessage = '登录已过期,请重新登录';
_handleTokenExpired();
} else if (err.response?.statusCode == 403) {
errorMessage = '没有权限访问该资源';
} else if (err.response?.statusCode == 404) {
errorMessage = '请求的资源不存在';
} else if (err.response?.statusCode == 500) {
errorMessage = '服务器内部错误';
} else {
errorMessage = '请求失败,状态码:${err.response?.statusCode}';
}
break;
case DioExceptionType.cancel:
errorMessage = '请求已取消';
break;
default:
errorMessage = err.message ?? '未知错误';
}
_showError(errorMessage);
handler.reject(err);
}
void _showError(String message) {
// 使FlutterSmartDialog显示错误信息
SmartDialog.showToast(message, displayTime: const Duration(seconds: 2));
}
void _handleTokenExpired() {
// token过期逻辑
// 使Get.offAllNamed('/login')
GetStorage().remove('token');
Get.offAll(() => LoginPage());
}
}

189
lib/network/network_service.dart

@ -0,0 +1,189 @@
import 'package:dio/dio.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:retrofit/retrofit.dart';
import 'api_service.dart';
import 'network_config.dart';
import 'user_api.dart';
///
class NetworkService {
static final NetworkService _instance = NetworkService._internal();
// API服务实例
late final ApiService _apiService; // API服务
late final ApiService _fileApiService; // API服务
late final UserApi _userApi;
///
factory NetworkService() {
return _instance;
}
NetworkService._internal() {
// API服务 - 使API
final dio = NetworkConfig.createDio();
_apiService = ApiService(dio);
_userApi = UserApi(dio);
// API服务
final fileDio = NetworkConfig.createDio(type: ApiType.file);
_fileApiService = ApiService(fileDio);
}
/// GET请求
Future<dynamic> get(
String path,
{Map<String, dynamic>? queryParameters,
bool showLoading = false,
bool showError = true,
ApiType apiType = ApiType.main}) async {
try {
if (showLoading) {
_showLoading();
}
// queryParameterspath
String finalPath = path;
if (queryParameters != null && queryParameters.isNotEmpty) {
final queryString = queryParameters.entries
.map((e) => '${e.key}=${e.value}')
.join('&');
finalPath = '$path?$queryString';
}
// API类型选择对应的服务
final apiService = _getApiServiceByType(apiType);
final response = await apiService.get(finalPath);
return response.data;
} catch (e) {
if (showError) {
_handleError(e);
}
return null;
} finally {
if (showLoading) {
_hideLoading();
}
}
}
/// POST请求
Future<dynamic> post(
String path,
dynamic data,
{bool showLoading = false,
bool showError = true,
ApiType apiType = ApiType.main}) async {
try {
if (showLoading) {
_showLoading();
}
// API类型选择对应的服务
final apiService = _getApiServiceByType(apiType);
final response = await apiService.post(
path,
data,
);
return response.data;
} catch (e) {
if (showError) {
_handleError(e);
}
return null;
} finally {
if (showLoading) {
_hideLoading();
}
}
}
/// PUT请求POST模拟
Future<dynamic> put(
String path,
dynamic data,
{bool showLoading = false,
bool showError = true,
ApiType apiType = ApiType.main}) async {
// 使PUT方法
try {
if (showLoading) {
_showLoading();
}
// 使PUT方法的API服务
// 使POST作为替代
final apiService = _getApiServiceByType(apiType);
final response = await apiService.post(
path,
data,
);
return response.data;
} catch (e) {
if (showError) {
_handleError(e);
}
return null;
} finally {
if (showLoading) {
_hideLoading();
}
}
}
/// DELETE请求GET模拟
Future<dynamic> delete(
String path,
{bool showLoading = false,
bool showError = true,
ApiType apiType = ApiType.main}) async {
// 使DELETE方法
return get(path, showLoading: showLoading, showError: showError, apiType: apiType);
}
/// PATCH请求POST模拟
Future<dynamic> patch(
String path,
dynamic data,
{bool showLoading = false,
bool showError = true,
ApiType apiType = ApiType.main}) async {
// 使PATCH方法
return post(path, data, showLoading: showLoading, showError: showError, apiType: apiType);
}
/// API类型获取对应的API服务实例
ApiService _getApiServiceByType(ApiType type) {
switch (type) {
case ApiType.main:
return _apiService;
case ApiType.file:
return _fileApiService;
}
}
/// API
UserApi get userApi => _userApi;
void _showLoading() {
// 使FlutterSmartDialog显示加载指示器
SmartDialog.showLoading();
}
void _hideLoading() {
//
SmartDialog.dismiss();
}
void _handleError(dynamic error) {
//
print('网络错误: $error');
//
}
}

92
lib/network/response_model.dart

@ -0,0 +1,92 @@
/// API响应模型基类
class BaseResponse<T> {
final int code;
final String message;
final T? data;
BaseResponse({
required this.code,
required this.message,
this.data,
});
factory BaseResponse.fromJson(Map<String, dynamic> json, T Function(dynamic)? fromJsonT) {
return BaseResponse(
code: json['code'] ?? 0,
message: json['message'] ?? '',
data: fromJsonT != null && json.containsKey('data') && json['data'] != null
? fromJsonT(json['data'])
: null,
);
}
Map<String, dynamic> toJson(Object? Function(T?)? toJsonT) {
final Map<String, dynamic> data = <String, dynamic>{};
data['code'] = code;
data['message'] = message;
if (this.data != null && toJsonT != null) {
data['data'] = toJsonT(this.data);
}
return data;
}
///
bool get isSuccess => code == 0;
@override
String toString() {
return 'BaseResponse{code: $code, message: $message, data: $data}';
}
}
///
class PaginatedResponse<T> {
final List<T> list;
final int total;
final int page;
final int pageSize;
final bool hasMore;
PaginatedResponse({
required this.list,
required this.total,
required this.page,
required this.pageSize,
this.hasMore = false,
});
factory PaginatedResponse.fromJson(
Map<String, dynamic> json,
T Function(dynamic) fromJsonT,
) {
final list = <T>[];
if (json['list'] != null && json['list'] is List) {
for (final item in json['list']) {
list.add(fromJsonT(item));
}
}
return PaginatedResponse(
list: list,
total: json['total'] ?? 0,
page: json['page'] ?? 1,
pageSize: json['pageSize'] ?? 10,
hasMore: json['hasMore'] ?? false,
);
}
Map<String, dynamic> toJson(Object Function(T) toJsonT) {
return {
'list': list.map((e) => toJsonT(e)).toList(),
'total': total,
'page': page,
'pageSize': pageSize,
'hasMore': hasMore,
};
}
@override
String toString() {
return 'PaginatedResponse{list: $list, total: $total, page: $page, pageSize: $pageSize, hasMore: $hasMore}';
}
}

17
lib/network/user_api.dart

@ -0,0 +1,17 @@
import 'package:retrofit/retrofit.dart';
import 'package:dio/dio.dart';
part 'user_api.g.dart';
@RestApi(baseUrl: 'https://api.example.com/')
abstract class UserApi {
factory UserApi(Dio dio) = _UserApi;
@POST("auth/login")
Future<HttpResponse<dynamic>> login(
@Body() Map<String, dynamic> data,
);
@GET("user/info")
Future<HttpResponse<dynamic>> getUserInfo();
}

97
lib/network/user_api.g.dart

@ -0,0 +1,97 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'user_api.dart';
// dart format off
// **************************************************************************
// RetrofitGenerator
// **************************************************************************
// ignore_for_file: unnecessary_brace_in_string_interps,no_leading_underscores_for_local_identifiers,unused_element,unnecessary_string_interpolations,unused_element_parameter,avoid_unused_constructor_parameters,unreachable_from_main
class _UserApi implements UserApi {
_UserApi(this._dio, {this.baseUrl, this.errorLogger}) {
baseUrl ??= 'https://api.example.com/';
}
final Dio _dio;
String? baseUrl;
final ParseErrorLogger? errorLogger;
@override
Future<HttpResponse<dynamic>> login(Map<String, dynamic> data) async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
final _data = <String, dynamic>{};
_data.addAll(data);
final _options = _setStreamType<HttpResponse<dynamic>>(
Options(method: 'POST', headers: _headers, extra: _extra)
.compose(
_dio.options,
'auth/login',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch(_options);
final _value = _result.data;
final httpResponse = HttpResponse(_value, _result);
return httpResponse;
}
@override
Future<HttpResponse<dynamic>> getUserInfo() async {
final _extra = <String, dynamic>{};
final queryParameters = <String, dynamic>{};
final _headers = <String, dynamic>{};
const Map<String, dynamic>? _data = null;
final _options = _setStreamType<HttpResponse<dynamic>>(
Options(method: 'GET', headers: _headers, extra: _extra)
.compose(
_dio.options,
'user/info',
queryParameters: queryParameters,
data: _data,
)
.copyWith(baseUrl: _combineBaseUrls(_dio.options.baseUrl, baseUrl)),
);
final _result = await _dio.fetch(_options);
final _value = _result.data;
final httpResponse = HttpResponse(_value, _result);
return httpResponse;
}
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
if (T != dynamic &&
!(requestOptions.responseType == ResponseType.bytes ||
requestOptions.responseType == ResponseType.stream)) {
if (T == String) {
requestOptions.responseType = ResponseType.plain;
} else {
requestOptions.responseType = ResponseType.json;
}
}
return requestOptions;
}
String _combineBaseUrls(String dioBaseUrl, String? baseUrl) {
if (baseUrl == null || baseUrl.trim().isEmpty) {
return dioBaseUrl;
}
final url = Uri.parse(baseUrl);
if (url.isAbsolute) {
return url.toString();
}
return Uri.parse(dioBaseUrl).resolveUri(url).toString();
}
}
// dart format on

15
lib/pages/main_page.dart

@ -0,0 +1,15 @@
import 'package:flutter/material.dart';
class MainPage extends StatefulWidget {
const MainPage({super.key});
@override
State<MainPage> createState() => _MainPageState();
}
class _MainPageState extends State<MainPage> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}

15
lib/pages/mine/login_page.dart

@ -0,0 +1,15 @@
import 'package:flutter/material.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}

732
pubspec.lock

@ -1,6 +1,46 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: f0bb5d1648339c8308cc0b9838d8456b3cfe5c91f9dc1a735b4d003269e5da9a
url: "https://pub.flutter-io.cn"
source: hosted
version: "88.0.0"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: "0b7b9c329d2879f8f05d6c05b32ee9ec025f39b077864bdb5ac9a7b63418a98f"
url: "https://pub.flutter-io.cn"
source: hosted
version: "8.1.1"
ansicolor:
dependency: transitive
description:
name: ansicolor
sha256: "50e982d500bc863e1d703448afdbf9e5a72eb48840a4f766fa361ffd6877055f"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.3"
archive:
dependency: transitive
description:
name: archive
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.7"
args:
dependency: transitive
description:
name: args
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.7.0"
async:
dependency: transitive
description:
@ -17,6 +57,54 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
build:
dependency: transitive
description:
name: build
sha256: dfb67ccc9a78c642193e0c2d94cb9e48c2c818b3178a86097d644acdcde6a8d9
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.2"
build_config:
dependency: transitive
description:
name: build_config
sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
build_daemon:
dependency: transitive
description:
name: build_daemon
sha256: "409002f1adeea601018715d613115cfaf0e31f512cb80ae4534c79867ae2363d"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.1.0"
build_runner:
dependency: "direct dev"
description:
name: build_runner
sha256: a9461b8e586bf018dd4afd2e13b49b08c6a844a4b226c8d1d10f3a723cdd78c3
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.10.1"
built_collection:
dependency: transitive
description:
name: built_collection
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
sha256: a30f0a0e38671e89a492c44d005b5545b830a961575bbd8336d42869ff71066d
url: "https://pub.flutter-io.cn"
source: hosted
version: "8.12.0"
characters:
dependency: transitive
description:
@ -25,6 +113,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.0"
checked_yaml:
dependency: transitive
description:
name: checked_yaml
sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.4"
clock:
dependency: transitive
description:
@ -33,6 +129,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.2"
code_builder:
dependency: transitive
description:
name: code_builder
sha256: "11654819532ba94c34de52ff5feb52bd81cba1de00ef2ed622fd50295f9d4243"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.11.0"
collection:
dependency: transitive
description:
@ -41,6 +145,38 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.19.1"
convert:
dependency: transitive
description:
name: convert
sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.2"
cross_file:
dependency: transitive
description:
name: cross_file
sha256: "942a4791cd385a68ccb3b32c71c427aba508a1bb949b86dff2adbe4049f16239"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.5"
crypto:
dependency: transitive
description:
name: crypto
sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.6"
csslib:
dependency: transitive
description:
name: csslib
sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.2"
cupertino_icons:
dependency: "direct main"
description:
@ -49,6 +185,38 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.8"
dart_style:
dependency: transitive
description:
name: dart_style
sha256: c87dfe3d56f183ffe9106a18aebc6db431fc7c98c31a54b952a77f3d54a85697
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.2"
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"
event_bus:
dependency: "direct main"
description:
name: event_bus
sha256: "1a55e97923769c286d295240048fc180e7b0768902c3c2e869fe059aafa15304"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.1"
fake_async:
dependency: transitive
description:
@ -57,6 +225,62 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.3"
ffi:
dependency: transitive
description:
name: ffi
sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
file:
dependency: transitive
description:
name: file
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.0.1"
file_selector_linux:
dependency: transitive
description:
name: file_selector_linux
sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.3+2"
file_selector_macos:
dependency: transitive
description:
name: file_selector_macos
sha256: "88707a3bec4b988aaed3b4df5d7441ee4e987f20b286cddca5d6a8270cab23f2"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.4+5"
file_selector_platform_interface:
dependency: transitive
description:
name: file_selector_platform_interface
sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.6.2"
file_selector_windows:
dependency: transitive
description:
name: file_selector_windows
sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.9.3+4"
fixnum:
dependency: transitive
description:
name: fixnum
sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
flutter:
dependency: "direct main"
description: flutter
@ -70,11 +294,237 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.0.0"
flutter_localizations:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_native_splash:
dependency: "direct main"
description:
name: flutter_native_splash
sha256: "4fb9f4113350d3a80841ce05ebf1976a36de622af7d19aca0ca9a9911c7ff002"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.7"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
sha256: "306f0596590e077338312f38837f595c04f28d6cdeeac392d3d74df2f0003687"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.32"
flutter_screenutil:
dependency: "direct main"
description:
name: flutter_screenutil
sha256: "8239210dd68bee6b0577aa4a090890342d04a136ce1c81f98ee513fc0ce891de"
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.9.3"
flutter_smart_dialog:
dependency: "direct main"
description:
name: flutter_smart_dialog
sha256: "0852df132cb03fd8fc5144eb404c31eb7eb50c22aecb1cc2504f2f598090d756"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.9.8+9"
flutter_test:
dependency: "direct dev"
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
frontend_server_client:
dependency: transitive
description:
name: frontend_server_client
sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.0"
get:
dependency: "direct main"
description:
name: get
sha256: c79eeb4339f1f3deffd9ec912f8a923834bec55f7b49c9e882b8fef2c139d425
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.7.2"
get_storage:
dependency: "direct main"
description:
name: get_storage
sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
glob:
dependency: transitive
description:
name: glob
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.3"
graphs:
dependency: transitive
description:
name: graphs
sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.2"
hotreloader:
dependency: transitive
description:
name: hotreloader
sha256: bc167a1163807b03bada490bfe2df25b0d744df359227880220a5cbd04e5734b
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.3.0"
html:
dependency: transitive
description:
name: html
sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.15.6"
http:
dependency: transitive
description:
name: http
sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.5.0"
http_multi_server:
dependency: transitive
description:
name: http_multi_server
sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.2.2"
http_parser:
dependency: transitive
description:
name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.1.2"
image:
dependency: transitive
description:
name: image
sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.5.4"
image_picker:
dependency: "direct main"
description:
name: image_picker
sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: ca2a3b04d34e76157e9ae680ef16014fb4c2d20484e78417eaed6139330056f6
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.8.13+7"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.0"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: e675c22790bcc24e9abd455deead2b7a88de4b79f7327a281812f14de1a56f58
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.8.13+1"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.2"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.2+1"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.11.1"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.2.2"
intl:
dependency: "direct main"
description:
name: intl
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.20.2"
io:
dependency: transitive
description:
name: io
sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.5"
json_annotation:
dependency: transitive
description:
name: json_annotation
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.9.0"
json_serializable:
dependency: "direct dev"
description:
name: json_serializable
sha256: "33a040668b31b320aafa4822b7b1e177e163fc3c1e835c6750319d4ab23aa6fe"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.11.1"
leak_tracker:
dependency: transitive
description:
@ -99,6 +549,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.2"
lean_builder:
dependency: transitive
description:
name: lean_builder
sha256: ef5cd5f907157eb7aa87d1704504b5a6386d2cbff88a3c2b3344477bab323ee9
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.1.2"
lints:
dependency: transitive
description:
@ -107,6 +565,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.1.1"
logging:
dependency: transitive
description:
name: logging
sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.0"
matcher:
dependency: transitive
description:
@ -131,6 +597,22 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.16.0"
mime:
dependency: transitive
description:
name: mime
sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.0"
package_config:
dependency: transitive
description:
name: package_config
sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0"
path:
dependency: transitive
description:
@ -139,11 +621,171 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.9.1"
path_provider:
dependency: "direct main"
description:
name: path_provider
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.5"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: e122c5ea805bb6773bb12ce667611265980940145be920cd09a4b0ec0285cb16
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.20"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: efaec349ddfc181528345c56f8eda9d6cccd71c177511b132c6a0ddaefaa2738
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.4.3"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.1"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.2"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.3.0"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1"
url: "https://pub.flutter-io.cn"
source: hosted
version: "7.0.1"
platform:
dependency: transitive
description:
name: platform
sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.6"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.8"
pool:
dependency: transitive
description:
name: pool
sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.5.2"
posix:
dependency: transitive
description:
name: posix
sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61"
url: "https://pub.flutter-io.cn"
source: hosted
version: "6.0.3"
protobuf:
dependency: transitive
description:
name: protobuf
sha256: "826d6a306be26f29e5cd9faeb0c97aad5897270341dab6dbd7b8acd675937006"
url: "https://pub.flutter-io.cn"
source: hosted
version: "5.0.0"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.0"
pubspec_parse:
dependency: transitive
description:
name: pubspec_parse
sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.5.0"
retrofit:
dependency: "direct main"
description:
name: retrofit
sha256: "7d78824afa6eeeaf6ac58220910ee7a97597b39e93360d4bda230b7c6df45089"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.9.0"
retrofit_generator:
dependency: "direct dev"
description:
name: retrofit_generator
sha256: "47998fb9f214935e4eb00741aebc636ffcb62cb8ae73b474ac88127ce2744428"
url: "https://pub.flutter-io.cn"
source: hosted
version: "10.1.2"
shelf:
dependency: transitive
description:
name: shelf
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.2"
shelf_web_socket:
dependency: transitive
description:
name: shelf_web_socket
sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.0"
sky_engine:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
source_gen:
dependency: transitive
description:
name: source_gen
sha256: "9098ab86015c4f1d8af6486b547b11100e73b193e1899015033cb3e14ad20243"
url: "https://pub.flutter-io.cn"
source: hosted
version: "4.0.2"
source_helper:
dependency: transitive
description:
name: source_helper
sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.3.8"
source_span:
dependency: transitive
description:
@ -168,6 +810,14 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.4"
stream_transform:
dependency: transitive
description:
name: stream_transform
sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.1.1"
string_scanner:
dependency: transitive
description:
@ -192,6 +842,22 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.7.6"
typed_data:
dependency: transitive
description:
name: typed_data
sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.4.0"
universal_io:
dependency: transitive
description:
name: universal_io
sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.2"
vector_math:
dependency: transitive
description:
@ -208,6 +874,70 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "15.0.2"
watcher:
dependency: transitive
description:
name: watcher
sha256: "592ab6e2892f67760543fb712ff0177f4ec76c031f02f5b4ff8d3fc5eb9fb61a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.4"
web:
dependency: transitive
description:
name: web
sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.1.1"
web_socket:
dependency: transitive
description:
name: web_socket
sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
web_socket_channel:
dependency: transitive
description:
name: web_socket_channel
sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.0.3"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15"
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"
xxh3:
dependency: transitive
description:
name: xxh3
sha256: "399a0438f5d426785723c99da6b16e136f4953fb1e9db0bf270bd41dd4619916"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.2.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.3"
sdks:
dart: ">=3.9.0 <4.0.0"
flutter: ">=3.18.0-18.0.pre.54"
flutter: ">=3.35.0"

22
pubspec.yaml

@ -30,10 +30,23 @@ environment:
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.8
get: ^4.7.2
flutter_smart_dialog: ^4.9.7+8
flutter_screenutil: ^5.9.3
intl: ^0.20.2
get_storage: ^2.1.1
image_picker: ^1.1.1
path_provider: ^2.1.4
event_bus: ^2.0.1
dio: ^5.9.0
retrofit: ^4.9.0
flutter_native_splash: ^2.4.7
dev_dependencies:
flutter_test:
@ -45,6 +58,9 @@ dev_dependencies:
# package. See that file for information about deactivating specific lint
# rules and activating additional ones.
flutter_lints: ^5.0.0
build_runner: ^2.4.11
json_serializable: ^6.7.1
retrofit_generator: ^10.0.6
# For information on the generic Dart part of this file, see the
# following page: https://dart.dev/tools/pub/pubspec
@ -58,11 +74,11 @@ flutter:
uses-material-design: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
assets:
- assets/images/
# - images/a_dot_ham.jpeg
# An image asset can refer to one or more resolution-specific "variants", see
# An images asset can refer to one or more resolution-specific "variants", see
# https://flutter.dev/to/resolution-aware-images
# For details regarding adding assets from package dependencies, see

Loading…
Cancel
Save