Files
flutter_wisetronic/lib/main.dart
peima 901e42a41b fix(runtime): onGenerateRoute pathElements 越界 RangeError
- buy-service/renew-minioffice 加长度检查 (pathElements.length >= 4/3)
- 根因: Flutter web 深链接渐进式路径解析, onGenerateRoute 被调用多次,
  pathElements 递增 ([,buy-service] -> [,buy-service,1] -> 完整),
  前几次路径短但 pathElements[1]已匹配 -> int.parse([2])/[3] 越界
- 直接访问/刷新 /buy-service/x/y, /renew-minioffice/x 时崩溃
- 恢复 buy_service 实验代码 (data 校验 + mounted 保留)
2026-08-02 00:13:33 +08:00

210 lines
7.0 KiB
Dart

import 'dart:async';
import 'package:catcher/catcher.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:flutter_wisetronic/pages/buy_service.dart';
import 'package:geolocator/geolocator.dart' as geolocator;
import 'package:url_strategy/url_strategy.dart';
import 'models/located_address.dart';
import 'pages/create_online_store_1.dart';
import 'pages/download.dart';
import 'pages/me.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
// import 'package:uni_links/uni_links.dart';
import 'constants.dart';
import 'events/eventbus.dart';
import 'events/events.dart';
import 'generated/l10n.dart';
import 'pages/home.dart';
import 'pages/plain_page.dart';
import 'pages/renew_minioffice.dart';
import 'routes.dart';
import 'store/actions.dart';
import 'store/store.dart';
import 'utils/configure_nonweb.dart' if (dart.library.html) 'utils/configure_web.dart';
import 'utils/http_util.dart';
import 'utils/util_io.dart' if (dart.library.html) 'utils/util_web.dart';
import 'utils/utils.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
FlutterError.onError = (details) {
FlutterError.presentError(details);
print('CK_ERROR: ${details.exceptionAsString()}');
print('CK_CTX: ${details.context}');
print('CK_STACK: ${details.stack}');
};
// Enable configureApp will cause route problem.
// configureApp();
setPathUrlStrategy();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
MyApp() {
Routes.configure();
Utils().init();
Util().init();
// getCurrentPosition();
}
static getCurrentPosition() async {
bool serviceEnabled;
geolocator.LocationPermission permission;
serviceEnabled = await geolocator.Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
print('Location services are disabled');
return;
}
permission = await geolocator.Geolocator.checkPermission();
if (permission == geolocator.LocationPermission.deniedForever) {
print(
'Location permissions are permantly denied, we cannot request permissions.');
return;
}
if (permission == geolocator.LocationPermission.denied) {
permission = await geolocator.Geolocator.requestPermission();
if (permission != geolocator.LocationPermission.whileInUse &&
permission != geolocator.LocationPermission.always) {
print(
'Location permissions are denied (actual value: $permission).');
return;
}
geolocator.Position geoPosition = await geolocator.Geolocator.getCurrentPosition(
desiredAccuracy: geolocator.LocationAccuracy.high);
HttpUtil.httpGet('v1/getposition',
queryParameters: {
'latitude': geoPosition.latitude.toString(),
'longitude': geoPosition.longitude.toString(),
},
).then((value) {
print('value: $value');
store.dispatch(UpdateLocatedAddress(LocatedAddress.fromJson(value)));
}).catchError((error) {
print('error get address: $error');
});
}
}
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: Constants.DEBUG,
navigatorKey: kIsWeb ? null : Catcher.navigatorKey,
localizationsDelegates: [
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
RefreshLocalizations.delegate,
S.delegate,
],
supportedLocales: S.delegate.supportedLocales,
localeResolutionCallback: (Locale? locale, Iterable<Locale> supportedLocales) {
if (locale == null) {
store.dispatch(UpdateLocale(supportedLocales.first));
return supportedLocales.first;
}
print('Language code: ${locale.languageCode}, Country code: ${locale.countryCode}');
for (final supportedLocale in supportedLocales) {
if (supportedLocale.languageCode == locale.languageCode) {
store.dispatch(UpdateLocale(locale));
return supportedLocale;
}
}
store.dispatch(UpdateLocale(supportedLocales.first));
return supportedLocales.first;
},
onGenerateRoute: (RouteSettings settings) {
final List<String> pathElements = settings.name?.split('/') ?? [];
print('path elements: $pathElements');
if (pathElements.isEmpty || pathElements[0] != '') {
return null;
}
if (pathElements[1] == 'me') {
return MaterialPageRoute(
builder: (BuildContext context) => Me()
);
}
if (pathElements[1] == 'service-policy') {
return MaterialPageRoute(
builder: (BuildContext context) =>
PlainPage(
'service-policy',
businessId: 310,
),
);
}
if (pathElements[1] == 'privacy-policy') {
return MaterialPageRoute(
builder: (BuildContext context) =>
PlainPage(
'privacy-policy',
businessId: 310,
),
);
}
if (pathElements[1] == 'return-policy') {
return MaterialPageRoute(
builder: (BuildContext context) =>
PlainPage(
'return-policy',
businessId: 310,
),
);
}
if (pathElements[1] == 'end-user-license-agreement') {
return MaterialPageRoute(
builder: (BuildContext context) =>
PlainPage(
'end-user-license-agreement',
businessId: 310,
),
);
}
if (pathElements[1] == 'renew-minioffice' && pathElements.length >= 3) {
return MaterialPageRoute(builder: (BuildContext context) =>
RenewMiniOffice(int.parse(pathElements[2]))
);
}
if (pathElements[1] == 'buy-service' && pathElements.length >= 4) {
return MaterialPageRoute(builder: (BuildContext context) =>
BuyService(int.parse(pathElements[2]), pathElements[3])
);
}
if (pathElements[1] == 'contact-stores') {
return MaterialPageRoute(builder: (BuildContext context) =>
CreateOnlineStore1()
);
}
if (pathElements[1] == 'download') {
return MaterialPageRoute(builder: (BuildContext context) =>
Download()
);
}
return MaterialPageRoute(
builder: (BuildContext context) =>
Home(title: Constants.APP_TITLE,),
);
},
title: 'Wisetronic Inc.',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: StoreProvider(
store: store,
child: Home(title: Constants.APP_TITLE,),
),
);
}
}