Browse Source

feat(flutter): support navigations

pull/856/head
colin 2 years ago
parent
commit
e488ddec48
  1. 3
      apps/flutter/components/lib/widgets/index.dart
  2. 90
      apps/flutter/components/lib/widgets/menu/index.dart
  3. 3
      apps/flutter/components/lib/widgets/menu/state.dart
  4. 23
      apps/flutter/core/lib/models/common.dart
  5. 16
      apps/flutter/core/lib/utils/color.utils.dart
  6. 1
      apps/flutter/core/lib/utils/index.dart
  7. 7
      apps/flutter/dev_app/lib/main.dart
  8. 3
      apps/flutter/dev_app/lib/main.module.dart
  9. 6
      apps/flutter/dev_app/lib/pages/public/center/controller.dart
  10. 1
      apps/flutter/dev_app/lib/pages/public/error/index.dart
  11. 1
      apps/flutter/dev_app/lib/pages/public/error/not_found/index.dart
  12. 23
      apps/flutter/dev_app/lib/pages/public/error/not_found/view.dart
  13. 35
      apps/flutter/dev_app/lib/pages/public/home/controller.dart
  14. 25
      apps/flutter/dev_app/lib/pages/public/home/state.dart
  15. 168
      apps/flutter/dev_app/lib/pages/public/home/view.dart
  16. 23
      apps/flutter/dev_app/lib/pages/public/home/widget/search.dart
  17. 3
      apps/flutter/dev_app/lib/pages/public/index.dart
  18. 2
      apps/flutter/dev_app/lib/pages/public/route.name.dart
  19. 6
      apps/flutter/dev_app/lib/pages/public/route.public.dart
  20. 56
      apps/flutter/dev_app/pubspec.lock
  21. 1
      apps/flutter/dev_app/pubspec.yaml
  22. BIN
      apps/flutter/dev_app/res/images/no_data.png
  23. BIN
      apps/flutter/dev_app/res/images/profile.png
  24. BIN
      apps/flutter/dev_app/res/images/setting.png
  25. 7
      apps/flutter/dev_app/res/translations/en.json
  26. 9
      apps/flutter/dev_app/res/translations/zh-Hans.json
  27. 14
      apps/flutter/platform/lib/services/favorite.menu.state.service.dart
  28. 14
      apps/flutter/platform/lib/services/menu.state.service.dart

3
apps/flutter/components/lib/widgets/index.dart

@ -2,4 +2,5 @@ export 'avatar/index.dart';
export 'action-button/index.dart'; export 'action-button/index.dart';
export 'back-to-top/index.dart'; export 'back-to-top/index.dart';
export 'bottom-button/index.dart'; export 'bottom-button/index.dart';
export 'empty/index.dart'; export 'empty/index.dart';
export 'menu/index.dart';

90
apps/flutter/components/lib/widgets/menu/index.dart

@ -0,0 +1,90 @@
import 'package:core/models/common.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class Navigation extends StatefulWidget {
const Navigation({
super.key,
this.activedMenu,
this.menus = const [],
this.onMenuExpanded,
});
final List<Menu> menus;
final String? activedMenu;
final void Function(Menu menu)? onMenuExpanded;
@override
State<Navigation> createState() => _NavigationState();
}
class _NavigationState extends State<Navigation> {
@override
Widget build(BuildContext context) {
return SingleChildScrollView(
child: Container(
child: _renderNavigations(widget.menus),
),
);
}
Widget _renderNavigations(List<Menu> menus) {
var mainMenus = menus.where((menu) => menu.children?.isNotEmpty == false);
var subMenus = menus.where((menu) => menu.children?.isNotEmpty == true);
return Column(
children: [
_renderMenus(subMenus.toList()),
...mainMenus.map((menu) => _buildMenuItem(menu)),
],
);
}
Widget _renderMenus(List<Menu> menus) {
return ExpansionPanelList.radio(
initialOpenPanelValue: widget.activedMenu,
expandedHeaderPadding: const EdgeInsets.all(0),
expansionCallback: (panelIndex, isExpanded) {
if (widget.onMenuExpanded != null) {
widget.onMenuExpanded!(menus[panelIndex]);
}
},
children: menus.map<ExpansionPanelRadio>((Menu menu) {
var body = menu.children?.isNotEmpty == true
? _renderNavigations(menu.children!)
: _buildMenuItem(menu);
return ExpansionPanelRadio(
canTapOnHeader: true,
headerBuilder: (BuildContext context, bool isExpanded) {
return SizedBox(
height: 30,
child: ListTile(
title: Text(menu.displayName.padLeft(menu.level * 4)),
),
);
},
body: body,
value: menu.name,
);
}).toList(),
);
}
Widget _buildMenuItem(Menu menu) {
return InkWell(
onTap: () {
Get.toNamed(menu.path);
},
child: FractionallySizedBox(
widthFactor: 1,
child: Container(
height: 30,
margin: const EdgeInsets.only(top: 10),
child: Text(
menu.displayName.padLeft(menu.level * 8),
),
),
),
);
}
}

3
apps/flutter/components/lib/widgets/menu/state.dart

@ -0,0 +1,3 @@
class MenuState {
}

23
apps/flutter/core/lib/models/common.dart

@ -42,3 +42,26 @@ class SignalrMessage {
String method; String method;
List<Object?> data; List<Object?> data;
} }
class Menu {
Menu({
required this.path,
required this.name,
required this.displayName,
this.id = 0,
this.level = 0,
this.description,
this.redirect,
this.meta,
this.children,
});
String path;
String name;
String displayName;
String? description;
String? redirect;
int level;
int id;
Map<String, dynamic>? meta;
List<Menu>? children;
}

16
apps/flutter/core/lib/utils/color.utils.dart

@ -0,0 +1,16 @@
import 'dart:ui';
class ColorUtils {
static Color fromHex(String hexString) {
final buffer = StringBuffer();
if (hexString.length == 6 || hexString.length == 7) buffer.write('ff');
buffer.write(hexString.replaceFirst('#', ''));
return Color(int.parse(buffer.toString(), radix: 16));
}
}
extension HexStringToColor on String {
Color toColor() {
return ColorUtils.fromHex(this);
}
}

1
apps/flutter/core/lib/utils/index.dart

@ -1,3 +1,4 @@
export 'color.utils.dart';
export 'environment.utils.dart'; export 'environment.utils.dart';
export 'internal.store.dart'; export 'internal.store.dart';
export 'localization.utils.dart'; export 'localization.utils.dart';

7
apps/flutter/dev_app/lib/main.dart

@ -2,10 +2,12 @@ import 'package:core/dependency/index.dart';
import 'package:core/utils/theme.utils.dart'; import 'package:core/utils/theme.utils.dart';
import 'package:core/utils/logging.dart'; import 'package:core/utils/logging.dart';
import 'package:dev_app/main.module.dart'; import 'package:dev_app/main.module.dart';
import 'package:dev_app/pages/index.dart';
import 'package:dev_app/pages/public/route.name.dart';
import 'package:dev_app/utils/localization.dart'; import 'package:dev_app/utils/localization.dart';
import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
Future main() async { Future main() async {
@ -25,8 +27,9 @@ class MyApp extends StatelessWidget {
theme: ThemeUtils.lightTheme, theme: ThemeUtils.lightTheme,
darkTheme: ThemeUtils.darkTheme, darkTheme: ThemeUtils.darkTheme,
themeMode: ThemeMode.system, themeMode: ThemeMode.system,
initialRoute: '/', initialRoute: PublicRoutes.main,
getPages: module.getRoutes(), getPages: module.getRoutes(),
unknownRoute: PublicRoute.notFound,
debugShowMaterialGrid: false, debugShowMaterialGrid: false,
enableLog: true, enableLog: true,
builder: EasyLoading.init(), builder: EasyLoading.init(),

3
apps/flutter/dev_app/lib/main.module.dart

@ -1,5 +1,6 @@
import 'package:components/index.dart'; import 'package:components/index.dart';
import 'package:dev_app/pages/index.dart'; import 'package:dev_app/pages/index.dart';
import 'package:dev_app/pages/public/route.name.dart';
import 'package:dev_app/services/index.dart'; import 'package:dev_app/services/index.dart';
import 'package:dev_app/utils/initial.utils.dart'; import 'package:dev_app/utils/initial.utils.dart';
import 'package:dev_app/utils/loading.dart'; import 'package:dev_app/utils/loading.dart';
@ -30,7 +31,7 @@ class MainModule extends Module {
@override @override
List<GetPage> get routes => [ List<GetPage> get routes => [
GetPage( GetPage(
name: '/', name: PublicRoutes.main,
page: () => const MainPage(), page: () => const MainPage(),
bindings: [ bindings: [
MainBinding(), MainBinding(),

6
apps/flutter/dev_app/lib/pages/public/center/controller.dart

@ -44,15 +44,15 @@ class CenterController extends GetxController {
} }
void onClickFeedback() { void onClickFeedback() {
redirectToRoute('/feedback');
} }
void onClickHelp() { void onClickHelp() {
redirectToRoute('/help');
} }
void onClickInfo() { void onClickInfo() {
redirectToRoute('/info');
} }
void onClickMessage() { void onClickMessage() {

1
apps/flutter/dev_app/lib/pages/public/error/index.dart

@ -0,0 +1 @@
export './not_found/index.dart';

1
apps/flutter/dev_app/lib/pages/public/error/not_found/index.dart

@ -0,0 +1 @@
export 'view.dart';

23
apps/flutter/dev_app/lib/pages/public/error/not_found/view.dart

@ -0,0 +1,23 @@
import 'package:bruno/bruno.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class PageNotFound extends StatelessWidget {
const PageNotFound({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("404Message".tr)
),
body: BrnAbnormalStateWidget(
img: Image.asset(
'res/images/no_data.png',
scale: 3.0,
),
content: "404MessageDetail".tr,
),
);
}
}

35
apps/flutter/dev_app/lib/pages/public/home/controller.dart

@ -1,3 +1,4 @@
import 'package:core/models/common.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:core/dependency/index.dart'; import 'package:core/dependency/index.dart';
import 'package:platforms/services/index.dart'; import 'package:platforms/services/index.dart';
@ -14,17 +15,27 @@ class HomeController extends GetxController {
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
// _menuStateService.getMyMenus$() _menuStateService.getMyMenus$()
// .listen((menus) { .listen((menus) {
// _state.update((val) { _state.update((val) {
// val?.menus = menus; val?.menus = menus;
// }); });
// }); });
// _favoriteMenuStateService.getFavoriteMenus$() _favoriteMenuStateService.getFavoriteMenus$()
// .listen((menus) { .listen((menus) {
// _state.update((val) { _state.update((val) {
// val?.favoriteMenus = menus; val?.favoriteMenus = menus;
// }); });
// }); });
}
void redirectToRoute(String route) {
Get.toNamed(route);
}
void onMenuExpanded(Menu menu) {
_state.update((val) {
val?.activedMenu = menu.name;
});
} }
} }

25
apps/flutter/dev_app/lib/pages/public/home/state.dart

@ -1,10 +1,35 @@
import 'package:core/models/common.dart';
import 'package:platforms/modes/menu.dto.dart'; import 'package:platforms/modes/menu.dto.dart';
class HomeState { class HomeState {
HomeState({ HomeState({
this.activedMenu,
this.menus = const [], this.menus = const [],
this.favoriteMenus = const [], this.favoriteMenus = const [],
}); });
String? activedMenu;
List<MenuDto> menus; List<MenuDto> menus;
List<UserFavoriteMenuDto> favoriteMenus; List<UserFavoriteMenuDto> favoriteMenus;
List<Menu> getMenus() => _buildTreeRecursive(menus, null, 0);
List<Menu> _buildTreeRecursive(List<MenuDto> treeMenus, String? parentId, int level) {
List<Menu> results = [];
var tempList = treeMenus.where((menu) => menu.parentId == parentId).toList();
for (int i = 0; i < tempList.length; i++) {
var menu = Menu(
id: tempList[i].id.hashCode,
path: tempList[i].path,
name: tempList[i].name,
displayName: tempList[i].displayName,
description: tempList[i].description,
redirect: tempList[i].redirect,
meta: tempList[i].meta,
level: level + 1
);
menu.children = _buildTreeRecursive(treeMenus, tempList[i].id, menu.level);
results.add(menu);
}
return results;
}
} }

168
apps/flutter/dev_app/lib/pages/public/home/view.dart

@ -1,6 +1,11 @@
import 'package:account/pages/route.name.dart';
import 'package:components/index.dart'; import 'package:components/index.dart';
import 'package:core/utils/index.dart';
import 'package:dev_app/pages/public/home/widget/search.dart'; import 'package:dev_app/pages/public/home/widget/search.dart';
import 'package:dev_app/pages/system/route.name.dart';
import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'controller.dart'; import 'controller.dart';
@ -20,26 +25,165 @@ class HomePage extends BasePage<HomeController> {
onPressed: () { onPressed: () {
showSearch(context: context, delegate: SearchBarDelegate(menus: bloc.state.menus)); showSearch(context: context, delegate: SearchBarDelegate(menus: bloc.state.menus));
}, },
child: const Row( child: Row(
children: <Widget>[ children: <Widget>[
Icon(Icons.search), const Icon(Icons.search),
Expanded(child: Text('搜索功能')) Expanded(child: Text('Label:SearchFeatures'.tr))
], ],
), ),
), ),
), ),
body: Column( body: ListView(
children: [ children: [
Expanded( ExpansionTile(
child: ListView.builder( initiallyExpanded: true,
itemCount: bloc.state.favoriteMenus.length, title: Text('Label:QuickNavigation'.tr,
itemBuilder: (context, index) { style: Theme.of(context).textTheme.titleMedium,
var favoriteMenu = bloc.state.favoriteMenus[index]; ),
return Text(favoriteMenu.displayName ?? favoriteMenu.name); children: [
}, SizedBox(
height: 120,
child: GridView.count(
shrinkWrap: true,
crossAxisCount: 4,
crossAxisSpacing: 5,
physics: const NeverScrollableScrollPhysics(),
children: [
_buildMenu(
SystemRoutes.settings,
SystemRoutes.settings,
icon: 'res/images/setting.png',
displayName: "Label:SystemSettings".tr,
color: Colors.red.hex),
_buildMenu(
AccountRoutes.profile,
AccountRoutes.profile,
icon: 'res/images/profile.png',
displayName: "Page:UserProfile".tr,
color: const Color.fromARGB(255, 68, 160, 206).hex),
],
),
),
],
), ),
ExpansionTile(
initiallyExpanded: true,
title: Text('Label:MyFavorite'.tr,
style: Theme.of(context).textTheme.titleMedium,
),
children: [
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemCount: bloc.state.favoriteMenus.length,
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
crossAxisSpacing: 5,
),
itemBuilder: (BuildContext context, int index) {
if (index >= bloc.state.favoriteMenus.length) {
return Empty.none;
}
var favoriteMenu = bloc.state.favoriteMenus[index];
return _buildMenu(
favoriteMenu.name,
favoriteMenu.path,
aliasName: favoriteMenu.aliasName,
//icon: favoriteMenu.icon,
// TODO:
icon: 'res/images/setting.png',
color: favoriteMenu.color,
displayName: favoriteMenu.displayName,
);
},
),
],
),
],
),
drawer: SafeArea(
child: Container(
width: 260,
color: const Color.fromARGB(255, 44, 115, 141),
child: Column(
children: [
Container(
height: 24,
margin: const EdgeInsets.all(10),
child: Row(
children: [
Padding(
padding: const EdgeInsets.only(left: 10),
child: Image.asset(
'res/images/logo.png',
height: 20,
width: 20,
),
),
const Padding(
padding: EdgeInsets.only(left: 10),
child: Text(
'abp flutter',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w400,
),
),
),
],
),
),
Expanded(
child: Obx(() => Navigation(
activedMenu: bloc.state.activedMenu,
menus: bloc.state.getMenus(),
onMenuExpanded: bloc.onMenuExpanded,
)),
),
],
), ),
], )
),
);
}
Widget _buildMenu(
String name,
String path,
{
String? aliasName,
String? icon,
String? color,
String? displayName,
}
) {
return InkWell(
onTap: () {
bloc.redirectToRoute(path);
},
child: SizedBox(
height: 20,
width: 30,
child: Column(
children: [
const SizedBox(height: 10),
icon != null
? Image.asset(
icon,
height: 40,
width: 40,
color: color.isNullOrWhiteSpace() ? null : ColorUtils.fromHex(color!),
)
: Empty.none,
Text(
displayName ?? aliasName ?? name,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 14
),
)
],
),
), ),
); );
} }

23
apps/flutter/dev_app/lib/pages/public/home/widget/search.dart

@ -13,8 +13,7 @@ class SearchBarDelegate extends SearchDelegate<String> {
List<Widget>? buildActions(BuildContext context) { List<Widget>? buildActions(BuildContext context) {
Widget button = IconButton( Widget button = IconButton(
onPressed: () { onPressed: () {
query = ""; close(context, "error");
showSuggestions(context);
}, },
icon: const Icon(Icons.clear), icon: const Icon(Icons.clear),
); );
@ -24,15 +23,17 @@ class SearchBarDelegate extends SearchDelegate<String> {
@override @override
Widget? buildLeading(BuildContext context) { Widget? buildLeading(BuildContext context) {
return IconButton( // return IconButton(
onPressed: () { // onPressed: () {
close(context, "error"); // query = "";
}, // showSuggestions(context);
icon: AnimatedIcon( // },
icon: AnimatedIcons.menu_arrow, // icon: AnimatedIcon(
progress: transitionAnimation, // icon: AnimatedIcons.menu_arrow,
), // progress: transitionAnimation,
); // ),
// );
return null;
} }
@override @override

3
apps/flutter/dev_app/lib/pages/public/index.dart

@ -1,3 +1,4 @@
export './center/index.dart'; export './center/index.dart';
export './home/index.dart'; export './home/index.dart';
export './work/index.dart'; export './work/index.dart';
export './error/index.dart';

2
apps/flutter/dev_app/lib/pages/public/route.name.dart

@ -1,5 +1,7 @@
class PublicRoutes { class PublicRoutes {
static String main = '/main';
static String home = '/home'; static String home = '/home';
static String work = '/work'; static String work = '/work';
static String center = '/center'; static String center = '/center';
static String notFound = '/error/not_found';
} }

6
apps/flutter/dev_app/lib/pages/public/route.public.dart

@ -4,7 +4,13 @@ import 'index.dart';
import 'route.name.dart'; import 'route.name.dart';
class PublicRoute { class PublicRoute {
static GetPage notFound = GetPage(
name: PublicRoutes.notFound,
page: () => const PageNotFound(),
);
static List<GetPage> routes = [ static List<GetPage> routes = [
notFound,
GetPage( GetPage(
name: PublicRoutes.home, name: PublicRoutes.home,
page: () => const HomePage(), page: () => const HomePage(),

56
apps/flutter/dev_app/pubspec.lock

@ -40,6 +40,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.11.0" version: "2.11.0"
bindings_compatible:
dependency: transitive
description:
name: bindings_compatible
sha256: "5dd5189f7512aff8ec180a8a11bd59230aa34a2d743e65e427192b7292a78d87"
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:
@ -48,6 +56,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "2.1.1" version: "2.1.1"
bruno:
dependency: "direct main"
description:
name: bruno
sha256: "8bd461a658996000eab1111a93fb4826ade878103f5a9afa29a414046805448b"
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.4.1"
build: build:
dependency: transitive dependency: transitive
description: description:
@ -307,6 +323,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "3.0.5" version: "3.0.5"
flutter_easyrefresh:
dependency: transitive
description:
name: flutter_easyrefresh
sha256: "5d161ee5dcac34da9065116568147d742dd25fb9bff3b10024d9054b195087ad"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.2.2"
flutter_highlight: flutter_highlight:
dependency: transitive dependency: transitive
description: description:
@ -514,6 +538,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
lpinyin:
dependency: transitive
description:
name: lpinyin
sha256: "0bb843363f1f65170efd09fbdfc760c7ec34fc6354f9fcb2f89e74866a0d814a"
url: "https://pub.flutter-io.cn"
source: hosted
version: "2.0.3"
markdown: markdown:
dependency: transitive dependency: transitive
description: description:
@ -608,6 +640,22 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "1.8.3" version: "1.8.3"
path_drawing:
dependency: transitive
description:
name: path_drawing
sha256: bbb1934c0cbb03091af082a6389ca2080345291ef07a5fa6d6e078ba8682f977
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
url: "https://pub.flutter-io.cn"
source: hosted
version: "1.0.1"
path_provider: path_provider:
dependency: transitive dependency: transitive
description: description:
@ -664,6 +712,14 @@ packages:
url: "https://pub.flutter-io.cn" url: "https://pub.flutter-io.cn"
source: hosted source: hosted
version: "5.4.0" version: "5.4.0"
photo_view:
dependency: transitive
description:
name: photo_view
sha256: "8036802a00bae2a78fc197af8a158e3e2f7b500561ed23b4c458107685e645bb"
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.14.0"
platform: platform:
dependency: transitive dependency: transitive
description: description:

1
apps/flutter/dev_app/pubspec.yaml

@ -49,6 +49,7 @@ dependencies:
platforms: platforms:
path: '../platform' path: '../platform'
bruno: ^3.3.0
dio: ^5.2.0+1 dio: ^5.2.0+1
flutter_easyloading: ^3.0.5 flutter_easyloading: ^3.0.5
flutter_picker: ^2.1.0 flutter_picker: ^2.1.0

BIN
apps/flutter/dev_app/res/images/no_data.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
apps/flutter/dev_app/res/images/profile.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
apps/flutter/dev_app/res/images/setting.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

7
apps/flutter/dev_app/res/translations/en.json

@ -5,6 +5,7 @@
"404Message": "Page not found", "404Message": "Page not found",
"404MessageDetail": "Sorry, there's nothing at this address.", "404MessageDetail": "Sorry, there's nothing at this address.",
"500Message": "Internal Server Error", "500Message": "Internal Server Error",
"Avatar": "Avatar",
"Center:Feedback": "Feedback", "Center:Feedback": "Feedback",
"Center:Help": "Help", "Center:Help": "Help",
"Center:Info": "Info", "Center:Info": "Info",
@ -12,6 +13,9 @@
"Center:Settings": "Settings", "Center:Settings": "Settings",
"DisplayName:Abp.Localization.DefaultLanguage": "Default language", "DisplayName:Abp.Localization.DefaultLanguage": "Default language",
"Description:Abp.Localization.DefaultLanguage": "The default language of the application.", "Description:Abp.Localization.DefaultLanguage": "The default language of the application.",
"DisplayName:UserName": "User Name",
"DisplayName:Email": "Email",
"DisplayName:PhoneNumber": "Phone Number",
"DefaultErrorMessage": "An error has occurred!", "DefaultErrorMessage": "An error has occurred!",
"DefaultErrorMessageDetail": "Error detail not sent by server.", "DefaultErrorMessageDetail": "Error detail not sent by server.",
"DefaultErrorMessage401": "You are not authenticated!", "DefaultErrorMessage401": "You are not authenticated!",
@ -37,6 +41,7 @@
"Label:NotifierSettings": "Notifier Settings", "Label:NotifierSettings": "Notifier Settings",
"Label:PasswordRequired": "Please enter password", "Label:PasswordRequired": "Please enter password",
"Label:PhoneNumberNotBound": "PhoneNumber Not Bound", "Label:PhoneNumberNotBound": "PhoneNumber Not Bound",
"Label:SearchFeatures": "Search Features",
"Label:Submit": "Submit", "Label:Submit": "Submit",
"Label:SwitchTheme": "Switch Theme", "Label:SwitchTheme": "Switch Theme",
"Label:SystemSettings": "System Settings", "Label:SystemSettings": "System Settings",
@ -45,6 +50,8 @@
"Label:Cancel": "Cancel", "Label:Cancel": "Cancel",
"Label:Confirm": "Confirm", "Label:Confirm": "Confirm",
"Label:LoginToPortal": "Login To Portal", "Label:LoginToPortal": "Login To Portal",
"Label:QuickNavigation": "Quick navigation",
"Label:MyFavorite": "My favorites",
"Languages": "Languages", "Languages": "Languages",
"Page:Center": "Center", "Page:Center": "Center",
"Page:Home": "Home", "Page:Home": "Home",

9
apps/flutter/dev_app/res/translations/zh-Hans.json

@ -2,9 +2,10 @@
"401Message": "未授权", "401Message": "未授权",
"403Message": "禁止访问", "403Message": "禁止访问",
"403MessageDetail": "您没有权限执行此操作!", "403MessageDetail": "您没有权限执行此操作!",
"404Message": "页未找到", "404Message": "页未找到",
"404MessageDetail": "抱歉, 这个地址是空的.", "404MessageDetail": "抱歉, 这个地址是空的.",
"500Message": "内部服务器错误", "500Message": "内部服务器错误",
"Avatar": "头像",
"Center:Feedback": "意见反馈", "Center:Feedback": "意见反馈",
"Center:Help": "在线帮助", "Center:Help": "在线帮助",
"Center:Info": "关于", "Center:Info": "关于",
@ -12,6 +13,9 @@
"Center:Settings": "设置", "Center:Settings": "设置",
"DisplayName:Abp.Localization.DefaultLanguage": "默认语言", "DisplayName:Abp.Localization.DefaultLanguage": "默认语言",
"Description:Abp.Localization.DefaultLanguage": "应用程序的默认语言.", "Description:Abp.Localization.DefaultLanguage": "应用程序的默认语言.",
"DisplayName:UserName": "用户名",
"DisplayName:Email": "邮件地址",
"DisplayName:PhoneNumber": "手机号码",
"DefaultErrorMessage": "发生错误!", "DefaultErrorMessage": "发生错误!",
"DefaultErrorMessageDetail": "服务器未发送错误的详细信息.", "DefaultErrorMessageDetail": "服务器未发送错误的详细信息.",
"DefaultErrorMessage401": "未通过身份验证!", "DefaultErrorMessage401": "未通过身份验证!",
@ -37,6 +41,7 @@
"Label:NotifierSettings": "通知设置", "Label:NotifierSettings": "通知设置",
"Label:PasswordRequired": "请输入密码", "Label:PasswordRequired": "请输入密码",
"Label:PhoneNumberNotBound": "未绑定手机号", "Label:PhoneNumberNotBound": "未绑定手机号",
"Label:SearchFeatures": "搜索功能",
"Label:Submit": "提交", "Label:Submit": "提交",
"Label:SwitchTheme": "切换主题", "Label:SwitchTheme": "切换主题",
"Label:SystemSettings": "系统设置", "Label:SystemSettings": "系统设置",
@ -45,6 +50,8 @@
"Label:Cancel": "取消", "Label:Cancel": "取消",
"Label:Confirm": "确认", "Label:Confirm": "确认",
"Label:LoginToPortal": "登录到门户", "Label:LoginToPortal": "登录到门户",
"Label:QuickNavigation": "快捷导航",
"Label:MyFavorite": "我的收藏",
"Languages": "语言", "Languages": "语言",
"Page:Center": "个人中心", "Page:Center": "个人中心",
"Page:Home": "首页", "Page:Home": "首页",

14
apps/flutter/platform/lib/services/favorite.menu.state.service.dart

@ -1,5 +1,6 @@
import 'package:core/services/environment.service.dart'; import 'package:core/services/environment.service.dart';
import 'package:core/services/service.base.dart'; import 'package:core/services/service.base.dart';
import 'package:core/services/session.service.dart';
import 'package:core/utils/index.dart'; import 'package:core/utils/index.dart';
import 'package:platforms/modes/state.dart'; import 'package:platforms/modes/state.dart';
import 'package:platforms/modes/menu.dto.dart'; import 'package:platforms/modes/menu.dto.dart';
@ -10,13 +11,24 @@ class FavoriteMenuStateService extends ServiceBase {
final InternalStore<FavoriteMenuState> _state = InternalStore<FavoriteMenuState>(state: FavoriteMenuState()); final InternalStore<FavoriteMenuState> _state = InternalStore<FavoriteMenuState>(state: FavoriteMenuState());
SessionService get _sessionService => resolve<SessionService>();
EnvironmentService get _environmentService => resolve<EnvironmentService>(); EnvironmentService get _environmentService => resolve<EnvironmentService>();
FavoriteMenuService get _favoriteMenuService => resolve<FavoriteMenuService>(); FavoriteMenuService get _favoriteMenuService => resolve<FavoriteMenuService>();
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
refreshState(); _initState();
}
void _initState() {
_sessionService.getToken$()
.listen((token) {
_state.patch((state) => state.menus = []);
if (token != null) {
refreshState();
}
});
} }
Future<void> refreshState() async { Future<void> refreshState() async {

14
apps/flutter/platform/lib/services/menu.state.service.dart

@ -1,5 +1,6 @@
import 'package:core/services/environment.service.dart'; import 'package:core/services/environment.service.dart';
import 'package:core/services/service.base.dart'; import 'package:core/services/service.base.dart';
import 'package:core/services/session.service.dart';
import 'package:core/utils/index.dart'; import 'package:core/utils/index.dart';
import 'package:platforms/modes/state.dart'; import 'package:platforms/modes/state.dart';
import 'package:platforms/modes/menu.dto.dart'; import 'package:platforms/modes/menu.dto.dart';
@ -11,12 +12,23 @@ class MenuStateService extends ServiceBase {
final InternalStore<MenuState> _state = InternalStore<MenuState>(state: MenuState()); final InternalStore<MenuState> _state = InternalStore<MenuState>(state: MenuState());
EnvironmentService get _environmentService => resolve<EnvironmentService>(); EnvironmentService get _environmentService => resolve<EnvironmentService>();
SessionService get _sessionService => resolve<SessionService>();
MenuService get _menuService => resolve<MenuService>(); MenuService get _menuService => resolve<MenuService>();
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
refreshState(); _initState();
}
void _initState() {
_sessionService.getToken$()
.listen((token) {
_state.patch((state) => state.menus = []);
if (token != null) {
refreshState();
}
});
} }
Future<void> refreshState() async { Future<void> refreshState() async {

Loading…
Cancel
Save