Commit f6538347 authored by 关振斌's avatar 关振斌

init getx

parent 70214295
This diff is collapsed.
......@@ -78,6 +78,9 @@ PODS:
- fluttertoast (0.0.2):
- Flutter
- Toast
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- GoogleUtilities/AppDelegateSwizzler (7.11.0):
- GoogleUtilities/Environment
- GoogleUtilities/Logger
......@@ -99,6 +102,8 @@ PODS:
- open_filex (0.0.2):
- Flutter
- OrderedSet (5.0.0)
- package_info (0.0.1):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
......@@ -112,6 +117,9 @@ PODS:
- FlutterMacOS
- smart_auth (0.0.1):
- Flutter
- sqflite (0.0.2):
- Flutter
- FMDB (>= 2.7.5)
- SwiftyGif (5.4.4)
- Toast (4.0.0)
- url_launcher_ios (0.0.1):
......@@ -133,9 +141,11 @@ DEPENDENCIES:
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- open_filex (from `.symlinks/plugins/open_filex/ios`)
- package_info (from `.symlinks/plugins/package_info/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/ios`)
- smart_auth (from `.symlinks/plugins/smart_auth/ios`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`)
......@@ -147,6 +157,7 @@ SPEC REPOS:
- FirebaseAuth
- FirebaseCore
- FirebaseCoreInternal
- FMDB
- GoogleUtilities
- GTMSessionFetcher
- OrderedSet
......@@ -183,12 +194,16 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/image_picker_ios/ios"
open_filex:
:path: ".symlinks/plugins/open_filex/ios"
package_info:
:path: ".symlinks/plugins/package_info/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/ios"
smart_auth:
:path: ".symlinks/plugins/smart_auth/ios"
sqflite:
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
webview_flutter_wkwebview:
......@@ -212,17 +227,20 @@ SPEC CHECKSUMS:
flutter_inappwebview: bfd58618f49dc62f2676de690fc6dcda1d6c3721
fluttercontactpicker: d582836dea6b5d489f3d259f35d7817ae82ee5e6
fluttertoast: eb263d302cc92e04176c053d2385237e9f43fad0
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
GoogleUtilities: c2bdc4cf2ce786c4d2e6b3bcfd599a25ca78f06f
GTMSessionFetcher: c9e714f7eec91a55641e2bab9f45fd83a219b882
image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
open_filex: 6e26e659846ec990262224a12ef1c528bb4edbe4
OrderedSet: aaeb196f7fef5a9edf55d89760da9176ad40b93c
package_info: 873975fc26034f0b863a300ad47e7f1ac6c7ec62
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
PromisesObjC: ab77feca74fa2823e7af4249b8326368e61014cb
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
SDWebImage: 8ab87d4b3e5cc4927bd47f78db6ceb0b94442577
shared_preferences_foundation: 297b3ebca31b34ec92be11acd7fb0ba932c822ca
smart_auth: 4bedbc118723912d0e45a07e8ab34039c19e04f2
sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904
SwiftyGif: 93a1cc87bf3a51916001cf8f3d63835fb64c819f
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
url_launcher_ios: fb12c43172927bb5cf75aeebd073f883801f1993
......
library apis;
export 'user.dart';
export 'news.dart';
import 'package:chart/common/entities/classFyDetail.dart';
import 'package:chart/common/entities/entities.dart';
import 'package:chart/common/utils/utils.dart';
import 'package:chart/common/values/values.dart';
import '../../entity/plan_entity.dart';
import '../../entity/square_entity.dart';
/// 新闻
class NewsAPI {
/// 翻页
/// refresh 是否刷新
static Future<List<SearchRecordEntity>> newsPageList(
Map<String, int> params) async {
var response = await HttpUtil().get(
'/searchRecord/getSearchRecord/${params['page']}/${params['size']}',
);
return searchRecordEntityFromList(response.data);
}
/// 翻页
/// refresh 是否刷新
static Future<List<MessageEntity>?> bannerList() async {
var response = await HttpUtil().get(
'/hotSearch/getHotSearch',
);
return messageEntityFromList(response['data']);
// NewsPageListResponseEntity.fromJson(response);
}
/// 获取分类
static Future<List<ClassifyEntity>> bannerPage() async {
var response = await HttpUtil().get(
'/classify/getClassifyList',
);
return classifyEntityFromList(response['data']);
// NewsPageListResponseEntity.fromJson(response);
}
/// 分类详情
// / /api/classifyDetail/getClassifyDetailById/1
static Future<List<ClassifyDetialEntity>> classFyDetialList(
Map<String, int> params) async {
var response = await HttpUtil().get(
'/classifyDetail/getClassifyDetailById/${params['id']}',
);
return classifyDetialEntityFromList(response['data']);
// NewsPageListResponseEntity.fromJson(response);
}
// classFyDetialList
/// 推荐
static Future<NewsItem> newsRecommend({
NewsRecommendRequestEntity? params,
bool refresh = false,
bool cacheDisk = false,
}) async {
var response = await HttpUtil().get(
'/news/recommend',
queryParameters: params?.toJson(),
refresh: refresh,
cacheDisk: cacheDisk,
);
return NewsItem.fromJson(response);
}
/// 分类
static Future<List<CategoryResponseEntity>> categories({
bool cacheDisk = false,
}) async {
var response = await HttpUtil().get(
'/categories',
cacheDisk: cacheDisk,
);
return response
.map<CategoryResponseEntity>(
(item) => CategoryResponseEntity.fromJson(item))
.toList();
}
/// 频道
static Future<List<ChannelResponseEntity>> channels({
bool cacheDisk = false,
}) async {
var response = await HttpUtil().get(
'/channels',
cacheDisk: cacheDisk,
);
return response
.map<ChannelResponseEntity>(
(item) => ChannelResponseEntity.fromJson(item))
.toList();
}
/// 标签列表
static Future<List<TagResponseEntity>> tags({
TagRequestEntity? params,
bool cacheDisk = false,
}) async {
var response = await HttpUtil().get(
'/tags',
queryParameters: params?.toJson(),
cacheDisk: cacheDisk,
);
return response
.map<TagResponseEntity>((item) => TagResponseEntity.fromJson(item))
.toList();
}
}
import 'package:chart/common/entities/entities.dart';
import 'package:chart/common/utils/utils.dart';
/// 用户
class UserAPI {
/// 登录
static Future<UserLoginResponseEntity> login({
UserLoginRequestEntity? params,
}) async {
var response = await HttpUtil().post(
'/user/login',
data: params?.toJson(),
);
return UserLoginResponseEntity.fromJson(response);
}
/// 注册
static Future<UserRegisterRequestEntity> register({
UserRegisterRequestEntity? params,
}) async {
var response = await HttpUtil().post(
'/user/register',
data: params?.toJson(),
);
return UserRegisterRequestEntity.fromJson(response);
}
/// Profile
static Future<UserLoginResponseEntity> profile() async {
var response = await HttpUtil().post(
'/user/profile',
);
return UserLoginResponseEntity.fromJson(response);
}
/// Logout
static Future logout() async {
return await HttpUtil().post(
'/user/logout',
);
}
}
/*
app 升级
*/
class AppUpdateRequestEntity {
String? device;
String? channel;
String? architecture;
String? model;
AppUpdateRequestEntity({
this.device,
this.channel,
this.architecture,
this.model,
});
factory AppUpdateRequestEntity.fromJson(Map<String, dynamic> json) =>
AppUpdateRequestEntity(
device: json["device"],
channel: json["channel"],
architecture: json["architecture"],
model: json["model"],
);
Map<String, dynamic> toJson() => {
"device": device,
"channel": channel,
"architecture": architecture,
"model": model,
};
}
class AppUpdateResponseEntity {
String? shopUrl;
String? fileUrl;
String? latestVersion;
String? latestDescription;
AppUpdateResponseEntity({
this.shopUrl,
this.fileUrl,
this.latestVersion,
this.latestDescription,
});
factory AppUpdateResponseEntity.fromJson(Map<String, dynamic> json) =>
AppUpdateResponseEntity(
shopUrl: json["shopUrl"],
fileUrl: json["fileUrl"],
latestVersion: json["latestVersion"],
latestDescription: json["latestDescription"],
);
Map<String, dynamic> toJson() => {
"shopUrl": shopUrl,
"fileUrl": fileUrl,
"latestVersion": latestVersion,
"latestDescription": latestDescription,
};
}
/// 新闻分类 response
class CategoryResponseEntity {
String code;
String title;
CategoryResponseEntity({
required this.code,
required this.title,
});
factory CategoryResponseEntity.fromJson(Map<String, dynamic> json) =>
CategoryResponseEntity(
code: json["code"],
title: json["title"],
);
Map<String, dynamic> toJson() => {
"code": code,
"title": title,
};
}
/// 频道列表 response
class ChannelResponseEntity {
String code;
String title;
ChannelResponseEntity({
required this.code,
required this.title,
});
factory ChannelResponseEntity.fromJson(Map<String, dynamic> json) =>
ChannelResponseEntity(
code: json["code"],
title: json["title"],
);
Map<String, dynamic> toJson() => {
"code": code,
"title": title,
};
}
import 'dart:convert';
class ClassifyDetialEntity {
ClassifyDetialEntity({
required this.id,
required this.detailName,
required this.detailDesc,
required this.isShow,
required this.template,
});
final int id;
final String detailName;
final String detailDesc;
final int isShow;
final String template;
factory ClassifyDetialEntity.fromJson(String str) =>
ClassifyDetialEntity.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory ClassifyDetialEntity.fromMap(Map<String, dynamic> json) =>
ClassifyDetialEntity(
id: json["id"],
detailName: json["detailName"],
detailDesc: json["detailDesc"],
template: json['template'],
isShow: json['isShow']);
Map<String, dynamic> toMap() => {
"id": id,
"detailName": detailName,
"detailDesc": detailDesc,
"isShow": isShow,
"template": template,
};
}
List<ClassifyDetialEntity> classifyDetialEntityFromList(List data) =>
List<ClassifyDetialEntity>.from(
data.map((x) => ClassifyDetialEntity.fromMap(x)));
library entities;
export 'user.dart';
export 'news.dart';
export 'categories.dart';
export 'channels.dart';
export 'tags.dart';
export 'app.dart';
/// 新闻分页 request
class NewsPageListRequestEntity {
String? categoryCode;
String? channelCode;
String? tag;
String? keyword;
int? pageNum;
int? pageSize;
NewsPageListRequestEntity({
this.categoryCode,
this.channelCode,
this.tag,
this.keyword,
this.pageNum,
this.pageSize,
});
Map<String, dynamic> toJson() => {
"categoryCode": categoryCode,
"channelCode": channelCode,
"tag": tag,
"keyword": keyword,
"pageNum": pageNum,
"pageSize": pageSize,
};
}
/// 新闻分页 response
class NewsPageListResponseEntity {
int? counts;
int? pagesize;
int? pages;
int? page;
List<NewsItem>? items;
NewsPageListResponseEntity({
this.counts,
this.pagesize,
this.pages,
this.page,
this.items,
});
factory NewsPageListResponseEntity.fromJson(Map<String, dynamic> json) =>
NewsPageListResponseEntity(
counts: json["counts"],
pagesize: json["pagesize"],
pages: json["pages"],
page: json["page"],
items: json["items"] == null
? []
: List<NewsItem>.from(
json["items"].map((x) => NewsItem.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"counts": counts ?? 0,
"pagesize": pagesize ?? 0,
"pages": pages ?? 0,
"page": page ?? 0,
"items": items == null
? []
: List<dynamic>.from(items!.map((x) => x.toJson())),
};
}
class NewsItem {
String? id;
String? title;
String? category;
String? thumbnail;
String? author;
DateTime? addtime;
String? url;
NewsItem({
this.id,
this.title,
this.category,
this.thumbnail,
this.author,
this.addtime,
this.url,
});
factory NewsItem.fromJson(Map<String, dynamic> json) => NewsItem(
id: json["id"],
title: json["title"],
category: json["category"],
thumbnail: json["thumbnail"],
author: json["author"],
addtime: DateTime.parse(json["addtime"]),
url: json["url"],
);
Map<String, dynamic> toJson() => {
"id": id,
"title": title,
"category": category,
"thumbnail": thumbnail,
"author": author,
"addtime": addtime?.toIso8601String(),
"url": url,
};
}
/// 新闻推荐 request
class NewsRecommendRequestEntity {
String? categoryCode;
String? channelCode;
String? tag;
String? keyword;
NewsRecommendRequestEntity({
this.categoryCode,
this.channelCode,
this.tag,
this.keyword,
});
Map<String, dynamic> toJson() => {
"categoryCode": categoryCode,
"channelCode": channelCode,
"tag": tag,
"keyword": keyword,
};
}
/// 标签列表 Request
class TagRequestEntity {
String categoryCode;
String channelCode;
String tag;
String keyword;
String newsID;
TagRequestEntity({
required this.categoryCode,
required this.channelCode,
required this.tag,
required this.keyword,
required this.newsID,
});
Map<String, dynamic> toJson() => {
"categoryCode": categoryCode,
"channelCode": channelCode,
"tag": tag,
"keyword": keyword,
"newsID": newsID,
};
}
/// 标签列表 Response
class TagResponseEntity {
String? tag;
TagResponseEntity({
this.tag,
});
factory TagResponseEntity.fromJson(Map<String, dynamic> json) =>
TagResponseEntity(
tag: json["tag"],
);
Map<String, dynamic> toJson() => {
"tag": tag,
};
}
// 注册请求
class UserRegisterRequestEntity {
String email;
String password;
UserRegisterRequestEntity({
required this.email,
required this.password,
});
factory UserRegisterRequestEntity.fromJson(Map<String, dynamic> json) =>
UserRegisterRequestEntity(
email: json["email"],
password: json["password"],
);
Map<String, dynamic> toJson() => {
"email": email,
"password": password,
};
}
// 登录请求
class UserLoginRequestEntity {
String email;
String password;
UserLoginRequestEntity({
required this.email,
required this.password,
});
factory UserLoginRequestEntity.fromJson(Map<String, dynamic> json) =>
UserLoginRequestEntity(
email: json["email"],
password: json["password"],
);
Map<String, dynamic> toJson() => {
"email": email,
"password": password,
};
}
// 登录返回
class UserLoginResponseEntity {
String? accessToken;
String? displayName;
List<String>? channels;
UserLoginResponseEntity({
this.accessToken,
this.displayName,
this.channels,
});
factory UserLoginResponseEntity.fromJson(Map<String, dynamic> json) =>
UserLoginResponseEntity(
accessToken: json["access_token"],
displayName: json["display_name"],
channels: List<String>.from(json["channels"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"access_token": accessToken,
"display_name": displayName,
"channels":
channels == null ? [] : List<dynamic>.from(channels!.map((x) => x)),
};
}
const Map<String, String> en_US = {
'title': 'This is Title!',
'login': 'logged in as @name with email @email',
};
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'en_US.dart';
import 'zh_Hans.dart';
import 'zh_HK.dart';
/*
https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html
https://www.ibabbleon.com/iOS-Language-Codes-ISO-639.html
*/
class TranslationService extends Translations {
static Locale? get locale => Get.deviceLocale;
static final fallbackLocale = Locale('en', 'US');
@override
Map<String, Map<String, String>> get keys => {
'en_US': en_US,
'zh_Hans': zh_Hans,
'zh_HK': zh_HK,
};
}
const Map<String, String> zh_HK = {
'title': '這是標題',
'login': '登錄用戶 @name,郵箱賬號 @email',
};
const Map<String, String> zh_Hans = {
'title': '这是标题',
'login': '登录用户 @name,邮箱账号 @email',
};
library middlewares;
export './router_auth.dart';
export './router_welcome.dart';
import 'package:flutter/material.dart';
import 'package:chart/common/routers/routes.dart';
import 'package:chart/common/store/store.dart';
import 'package:get/get.dart';
/// 检查是否登录
class RouteAuthMiddleware extends GetMiddleware {
// priority 数字小优先级高
@override
int? priority = 0;
RouteAuthMiddleware({required this.priority});
@override
RouteSettings? redirect(String? route) {
if (UserStore.to.isLogin ||
route == AppRoutes.SIGN_IN ||
route == AppRoutes.SIGN_UP ||
route == AppRoutes.INITIAL) {
return null;
} else {
Future.delayed(
Duration(seconds: 1), () => Get.snackbar("提示", "登录过期,请重新登录"));
return RouteSettings(name: AppRoutes.SIGN_IN);
}
}
}
import 'package:flutter/material.dart';
import 'package:chart/common/routers/routes.dart';
import 'package:chart/common/store/store.dart';
import 'package:get/get.dart';
/// 第一次欢迎页面
class RouteWelcomeMiddleware extends GetMiddleware {
// priority 数字小优先级高
@override
int? priority = 0;
RouteWelcomeMiddleware({required this.priority});
@override
RouteSettings? redirect(String? route) {
if (ConfigStore.to.isFirstOpen == true) {
return null;
} else if (UserStore.to.isLogin == true) {
return RouteSettings(name: AppRoutes.Application);
} else {
return RouteSettings(name: AppRoutes.SIGN_IN);
}
}
}
class AppRoutes {
static const INITIAL = '/';
static const SIGN_IN = '/sign_in';
static const SIGN_UP = '/sign_up';
static const NotFound = '/not_found';
static const Application = '/application';
static const Category = '/category';
}
static const application = '/application';
static const category = '/category';
static const frameNotfound = '/frame_notfound';
static const frameSignIn = '/frame_sign_in';
static const frameSignUp = '/frame_sign_up';
static const frameWelcome = '/frame_welcome';
static const main = '/main';
import 'package:flutter/material.dart';
import 'routes.dart';
class RouteObservers<R extends Route<dynamic>> extends RouteObserver<R> {
@override
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPush(route, previousRoute);
var name = route.settings.name ?? '';
if (name.isNotEmpty) AppPages.history.add(name);
print('didPush');
print(AppPages.history);
}
@override
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didPop(route, previousRoute);
AppPages.history.remove(route.settings.name);
print('didPop');
print(AppPages.history);
}
@override
void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
super.didReplace(newRoute: newRoute, oldRoute: oldRoute);
if (newRoute != null) {
var index = AppPages.history.indexWhere((element) {
return element == oldRoute?.settings.name;
});
var name = newRoute.settings.name ?? '';
if (name.isNotEmpty) {
if (index > 0) {
AppPages.history[index] = name;
} else {
AppPages.history.add(name);
}
}
}
print('didReplace');
print(AppPages.history);
}
@override
void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didRemove(route, previousRoute);
AppPages.history.remove(route.settings.name);
print('didRemove');
print(AppPages.history);
}
@override
void didStartUserGesture(
Route<dynamic> route, Route<dynamic>? previousRoute) {
super.didStartUserGesture(route, previousRoute);
}
@override
void didStopUserGesture() {
super.didStopUserGesture();
}
}
import 'package:flutter/material.dart';
import 'package:chart/common/middlewares/middlewares.dart';
import 'package:chart/pages/application/index.dart';
import 'package:chart/pages/category/index.dart';
import 'package:chart/pages/frame/sign_in/index.dart';
import 'package:chart/pages/frame/sign_up/index.dart';
import 'package:chart/pages/frame/welcome/index.dart';
// import 'package:chart/pages/home/home_page.dart';
import 'package:get/get.dart';
import 'routes.dart';
class AppPages {
static const INITIAL = AppRoutes.INITIAL;
static final RouteObserver<Route> observer = RouteObservers();
static List<String> history = [];
static final List<GetPage> routes = [
// // 免登陆
// GetPage(
// name: AppRoutes.INITIAL,
// page: () => WelcomePage(),
// binding: WelcomeBinding(),
// middlewares: [
// RouteWelcomeMiddleware(priority: 1),
// ],
// ),
// 需要登录
GetPage(
name: AppRoutes.INITIAL,
page: () => WelcomePage(), //ApplicationPage(),
binding: WelcomeBinding(), // ApplicationBinding(),
middlewares: [
// RouteAuthMiddleware(priority: 1),
],
),
GetPage(
name: AppRoutes.SIGN_IN,
page: () => SignInPage(),
binding: SignInBinding(),
),
GetPage(
name: AppRoutes.SIGN_UP,
page: () => SignUpPage(),
binding: SignUpBinding(),
),
// 需要登录
GetPage(
name: AppRoutes.Application,
page: () => ApplicationPage(),
binding: ApplicationBinding(),
middlewares: [
// RouteAuthMiddleware(priority: 1),
],
),
// 分类列表
GetPage(
name: AppRoutes.Category,
page: () => CategoryPage(),
binding: CategoryBinding(),
),
];
// static final unknownRoute = GetPage(
// name: AppRoutes.NotFound,
// page: () => NotfoundView(),
// );
}
GetPage(
name: RouteNames.application,
page: () => const ApplicationPage(),
),
GetPage(
name: RouteNames.category,
page: () => const CategoryPage(),
),
GetPage(
name: RouteNames.frameNotfound,
page: () => const NotfoundPage(),
),
GetPage(
name: RouteNames.frameSignIn,
page: () => const SignInPage(),
),
GetPage(
name: RouteNames.frameSignUp,
page: () => const SignUpPage(),
),
GetPage(
name: RouteNames.frameWelcome,
page: () => const WelcomePage(),
),
GetPage(
name: RouteNames.main,
page: () => const MainPage(),
),
\ No newline at end of file
library routes;
export 'names.dart';
export 'pages.dart';
export './observers.dart';
library services;
export './storage.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
class StorageService extends GetxService {
static StorageService get to => Get.put(StorageService());
// static StorageService get to => Get.find();
//
late final SharedPreferences _prefs;
Future<StorageService> init() async {
_prefs = await SharedPreferences.getInstance();
return this;
}
Future<bool> setString(String key, String value) async {
return await _prefs.setString(key, value);
}
Future<bool> setBool(String key, bool value) async {
return await _prefs.setBool(key, value);
}
Future<bool> setList(String key, List<String> value) async {
return await _prefs.setStringList(key, value);
}
String getString(String key) {
return _prefs.getString(key) ?? '';
}
bool getBool(String key) {
return _prefs.getBool(key) ?? false;
}
List<String> getList(String key) {
return _prefs.getStringList(key) ?? [];
}
Future<bool> remove(String key) async {
return await _prefs.remove(key);
}
}
import 'package:flutter/material.dart';
import 'package:chart/common/services/services.dart';
import 'package:chart/common/values/values.dart';
import 'package:get/get.dart';
import 'package:package_info/package_info.dart';
class ConfigStore extends GetxController {
static ConfigStore get to => Get.put(ConfigStore());
// .find();
bool isFirstOpen = false;
PackageInfo? _platform;
String get version => _platform?.version ?? '-';
bool get isRelease => bool.fromEnvironment("dart.vm.product");
Locale locale = Locale('en', 'US');
List<Locale> languages = [
Locale('en', 'US'),
Locale('zh', 'CN'),
];
@override
void onInit() {
super.onInit();
isFirstOpen = StorageService.to.getBool(STORAGE_DEVICE_FIRST_OPEN_KEY);
}
Future<void> getPlatform() async {
_platform = await PackageInfo.fromPlatform();
}
// 标记用户已打开APP
Future<bool> saveAlreadyOpen() {
return StorageService.to.setBool(STORAGE_DEVICE_FIRST_OPEN_KEY, false);
}
void onInitLocale() {
var langCode = StorageService.to.getString(STORAGE_LANGUAGE_CODE);
if (langCode.isEmpty) return;
var index = languages.indexWhere((element) {
return element.languageCode == langCode;
});
if (index < 0) return;
locale = languages[index];
}
void onLocaleUpdate(Locale value) {
locale = value;
Get.updateLocale(value);
StorageService.to.setString(STORAGE_LANGUAGE_CODE, value.languageCode);
}
}
library store;
export './user.dart';
export './config.dart';
import 'dart:convert';
import 'package:chart/common/apis/apis.dart';
import 'package:chart/common/entities/entities.dart';
import 'package:chart/common/services/services.dart';
import 'package:chart/common/values/values.dart';
import 'package:get/get.dart';
class UserStore extends GetxController {
static UserStore get to => Get.find();
// 是否登录
final _isLogin = false.obs;
// 令牌 token
String token = '';
// 用户 profile
final _profile = UserLoginResponseEntity().obs;
bool get isLogin => _isLogin.value;
UserLoginResponseEntity get profile => _profile.value;
bool get hasToken => token.isNotEmpty;
@override
void onInit() {
super.onInit();
token = StorageService.to.getString(STORAGE_USER_TOKEN_KEY);
var profileOffline = StorageService.to.getString(STORAGE_USER_PROFILE_KEY);
if (profileOffline.isNotEmpty) {
_profile(UserLoginResponseEntity.fromJson(jsonDecode(profileOffline)));
}
}
// 保存 token
Future<void> setToken(String value) async {
await StorageService.to.setString(STORAGE_USER_TOKEN_KEY, value);
token = value;
}
// 获取 profile
Future<void> getProfile() async {
if (token.isEmpty) return;
var result = await UserAPI.profile();
_profile(result);
_isLogin.value = true;
StorageService.to.setString(STORAGE_USER_PROFILE_KEY, jsonEncode(result));
}
// 保存 profile
Future<void> saveProfile(UserLoginResponseEntity profile) async {
_isLogin.value = true;
StorageService.to.setString(STORAGE_USER_PROFILE_KEY, jsonEncode(profile));
}
// 注销
Future<void> onLogout() async {
if (_isLogin.value) await UserAPI.logout();
await StorageService.to.remove(STORAGE_USER_TOKEN_KEY);
_isLogin.value = false;
token = '';
}
}
import 'package:flutter/material.dart';
class AppColor {
/// 页面背景颜色
static const Color scaffoldBackground = Color(0xFFFFFFFF);
/// 主要背景颜色
// static const Color primaryBackground = Color(0xFF5C78FF);
/// 主要文本颜色
static const Color primaryText = Color(0xFF333333);
/// 次要文本颜色
static const Color secondaryText = Color(0xFF74788D);
/// 高亮颜色
static const Color accentColor = Color(0xFF5C78FF);
/// 次要颜色
static const Color secondaryColor = Color(0xFFDEE3FF);
/// 警告颜色
static const Color warnColor = Color(0xFFFFB822);
/// 边框颜色
static const Color borderColor = Color(0xFFDEE3FF);
static const Color pinkColor = Color(0xFFF77866);
static const Color yellowColor = Color(0xFFFFB822);
}
library style;
export './color.dart';
export './theme.dart';
import 'package:flutter/material.dart';
import 'color.dart';
class AppTheme {
static const horizontalMargin = 16.0;
static const radius = 10.0;
static ThemeData light = ThemeData(
brightness: Brightness.light,
scaffoldBackgroundColor: AppColor.scaffoldBackground,
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
primaryColor: AppColor.accentColor,
colorScheme: ColorScheme.fromSwatch().copyWith(
secondary: AppColor.accentColor,
),
appBarTheme: AppBarTheme(
elevation: 0,
centerTitle: true,
backgroundColor: Colors.white,
iconTheme: IconThemeData(
color: AppColor.primaryText,
),
titleTextStyle: TextStyle(
color: AppColor.primaryText,
fontSize: 20,
fontWeight: FontWeight.w500,
),
toolbarTextStyle: TextStyle(
color: AppColor.primaryText,
fontSize: 20,
fontWeight: FontWeight.w500,
),
),
bottomNavigationBarTheme: BottomNavigationBarThemeData(
backgroundColor: AppColor.scaffoldBackground,
unselectedLabelStyle: TextStyle(fontSize: 12),
selectedLabelStyle: TextStyle(fontSize: 12),
unselectedItemColor: Color(0xffA2A5B9),
selectedItemColor: AppColor.accentColor,
),
tabBarTheme: TabBarTheme(
indicatorSize: TabBarIndicatorSize.label,
labelColor: AppColor.accentColor,
unselectedLabelColor: AppColor.secondaryText,
),
);
}
import 'package:intl/intl.dart';
/// 格式化时间
String duTimeLineFormat(DateTime dt) {
var now = DateTime.now();
var difference = now.difference(dt);
// 1天内
if (difference.inHours < 24) {
return "${difference.inHours} hours ago";
}
// 30天内
else if (difference.inDays < 30) {
return "${difference.inDays} days ago";
}
// MM-dd
else if (difference.inDays < 365) {
final dtFormat = new DateFormat('MM-dd');
return dtFormat.format(dt);
}
// yyyy-MM-dd
else {
final dtFormat = new DateFormat('yyyy-MM-dd');
var str = dtFormat.format(dt);
return str;
}
}
This diff is collapsed.
import 'package:flutter/material.dart';
class Iconfont {
// iconName: share
static const share = IconData(
0xe60d,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: fav
static const fav = IconData(
0xe60c,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-linkedin
static const sociallinkedin = IconData(
0xe605,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-apple
static const socialapple = IconData(
0xe606,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-octocat
static const socialoctocat = IconData(
0xe607,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-reddit
static const socialreddit = IconData(
0xe608,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-snapchat
static const socialsnapchat = IconData(
0xe609,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-skype
static const socialskype = IconData(
0xe60a,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: social-twitter
static const socialtwitter = IconData(
0xe60b,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: me
static const me = IconData(
0xe604,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: tag
static const tag = IconData(
0xe603,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: grid
static const grid = IconData(
0xe602,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
// iconName: home
static const home = IconData(
0xe601,
fontFamily: 'Iconfont',
matchTextDirection: true,
);
}
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
class Loading {
Loading() {
EasyLoading.instance
..displayDuration = const Duration(milliseconds: 2000)
..indicatorType = EasyLoadingIndicatorType.ring
..loadingStyle = EasyLoadingStyle.custom
..indicatorSize = 35.0
..lineWidth = 2
..radius = 10.0
..progressColor = Colors.white
..backgroundColor = Colors.black.withOpacity(0.7)
..indicatorColor = Colors.white
..textColor = Colors.white
..maskColor = Colors.black.withOpacity(0.6)
..userInteractions = true
..dismissOnTap = false
..maskType = EasyLoadingMaskType.custom;
}
static void show([String? text]) {
EasyLoading.instance.userInteractions = false;
EasyLoading.show(status: text ?? 'Loading...');
}
static void toast(String text) {
EasyLoading.showToast(text);
}
static void dismiss() {
EasyLoading.instance.userInteractions = true;
EasyLoading.dismiss();
}
}
class Logger {
// Sample of abstract logging function
static void write(String text, {bool isError = false}) {
Future.microtask(() => print('** $text. isError: [$isError]'));
}
}
import 'dart:convert';
import 'package:crypto/crypto.dart';
/// SHA256
String duSHA256(String input) {
String salt = 'EIpWsyfiy@R@X#qn17!StJNdZK1fFF8iV6ffN!goZkqt#JxO'; // 加盐
var bytes = utf8.encode(input + salt);
var digest = sha256.convert(bytes);
return digest.toString();
}
library utils;
export 'validator.dart';
export 'http.dart';
export 'security.dart';
export 'iconfont.dart';
export 'date.dart';
export 'logger.dart';
export 'loading.dart';
/// 检查邮箱格式
bool duIsEmail(String? input) {
if (input == null || input.isEmpty) return false;
// 邮箱正则
String regexEmail = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$";
return RegExp(regexEmail).hasMatch(input);
}
/// 检查字符长度
bool duCheckStringLength(String? input, int length) {
if (input == null || input.isEmpty) return false;
return input.length >= length;
}
import 'package:flutter/rendering.dart';
class Borders {
static const BorderSide primaryBorder = BorderSide(
color: Color.fromARGB(255, 230, 230, 231),
width: 1,
style: BorderStyle.solid,
);
}
\ No newline at end of file
// 是否启用缓存
const CACHE_ENABLE = false;
// 缓存的最长时间,单位(秒)
const CACHE_MAXAGE = 1000;
// 最大缓存数
const CACHE_MAXCOUNT = 100;
import 'dart:ui';
class AppColors {
/// 主背景 白色
static const Color primaryBackground = Color.fromARGB(255, 255, 255, 255);
/// 主文本 灰色
static const Color primaryText = Color.fromARGB(255, 45, 45, 47);
/// 主控件-背景 蓝色
static const Color primaryElement = Color.fromARGB(255, 41, 103, 255);
/// 主控件-文本 白色
static const Color primaryElementText = Color.fromARGB(255, 255, 255, 255);
// *****************************************
/// 第二种控件-背景色 淡灰色
static const Color secondaryElement = Color.fromARGB(255, 246, 246, 246);
/// 第二种控件-文本 浅蓝色
static const Color secondaryElementText = Color.fromARGB(255, 41, 103, 255);
// *****************************************
/// 第三种控件-背景色 石墨色
static const Color thirdElement = Color.fromARGB(255, 45, 45, 47);
/// 第三种控件-文本 浅灰色2
static const Color thirdElementText = Color.fromARGB(255, 141, 141, 142);
// *****************************************
/// tabBar 默认颜色 灰色
static const Color tabBarElement = Color.fromARGB(255, 208, 208, 208);
/// tabCellSeparator 单元格底部分隔条 颜色
static const Color tabCellSeparator = Color.fromARGB(255, 230, 230, 231);
}
// 是否启用代理
const PROXY_ENABLE = false;
/// 代理服务IP
// const PROXY_IP = '192.168.1.105';
const PROXY_IP = '172.16.43.74';
/// 代理服务端口
const PROXY_PORT = 8866;
import 'package:flutter/rendering.dart';
class Radii {
static const BorderRadiusGeometry k6pxRadius =
BorderRadius.all(Radius.circular(6));
static const BorderRadiusGeometry k54pxRadius =
BorderRadius.all(Radius.circular(54));
}
// baidu yapi
// const SERVER_API_URL = 'https://yapi.baidu.com/mock/41008';
// const SERVER_API_URL = 'https://yapi.ducafecat.tech/mock/11';
const SERVER_API_URL = 'http://192.168.110.1:8083/api';
// static const String baseUrl = 'http://101.34.153.228:8083'; // 基础接口地址
// static const String baseApiUrl = '${baseUrl}/api'; // 基础接口地址
// http://101.34.153.228:8083/api/doc.html
//192.168.110.1:8083
// 本地搭建 yapi
// const SERVER_API_URL = 'http://yapi.ducafecat.tech/mock/11';
import 'package:flutter/rendering.dart';
class Shadows {
static const BoxShadow primaryShadow = BoxShadow(
color: Color.fromARGB(38, 27, 27, 29),
offset: Offset(0, 5),
blurRadius: 10,
);
}
\ No newline at end of file
/// 用户 - 配置信息
const String STORAGE_USER_PROFILE_KEY = 'user_profile';
/// 用户 - 配置信息
const String STORAGE_USER_TOKEN_KEY = 'user_token';
/// 设备是否第一次打开
const String STORAGE_DEVICE_FIRST_OPEN_KEY = 'device_first_open';
/// 首页新闻cacheKey
const String STORAGE_INDEX_NEWS_CACHE_KEY = 'cache_index_news';
/// 多语言
const String STORAGE_LANGUAGE_CODE = 'language_code';
library values;
export 'colors.dart';
export 'borders.dart';
export 'radii.dart';
export 'shadows.dart';
export 'server.dart';
export 'storage.dart';
export 'cache.dart';
export 'proxy.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:chart/common/values/values.dart';
/// 透明背景 AppBar
AppBar transparentAppBar({
Widget? title,
Widget? leading,
List<Widget>? actions,
}) {
return AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
title: title != null
? Center(
child: title,
)
: null,
leading: leading,
actions: actions,
);
}
/// 10像素 Divider
Widget divider10Px({Color bgColor = AppColors.secondaryElement}) {
return Container(
height: 10.w,
decoration: BoxDecoration(
color: bgColor,
),
);
}
import 'package:flutter/material.dart';
import 'package:chart/common/values/values.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
/// 扁平圆角按钮
Widget btnFlatButtonWidget({
required VoidCallback onPressed,
double width = 140,
double height = 44,
Color gbColor = AppColors.primaryElement,
String title = "button",
Color fontColor = AppColors.primaryElementText,
double fontSize = 18,
String fontName = "Montserrat",
FontWeight fontWeight = FontWeight.w400,
}) {
return Container(
width: width.w,
height: height.h,
child: TextButton(
style: ButtonStyle(
textStyle: MaterialStateProperty.all(TextStyle(
fontSize: 16.sp,
)),
foregroundColor: MaterialStateProperty.resolveWith(
(states) {
if (states.contains(MaterialState.focused) &&
!states.contains(MaterialState.pressed)) {
return Colors.blue;
} else if (states.contains(MaterialState.pressed)) {
return Colors.deepPurple;
}
return fontColor;
},
),
backgroundColor: MaterialStateProperty.resolveWith((states) {
if (states.contains(MaterialState.pressed)) {
return Colors.blue[200];
}
return gbColor;
}),
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: Radii.k6pxRadius,
)),
),
child: Text(
title,
textAlign: TextAlign.center,
style: TextStyle(
color: fontColor,
fontFamily: fontName,
fontWeight: fontWeight,
fontSize: fontSize.sp,
height: 1,
),
),
onPressed: onPressed,
),
);
}
/// 第三方按钮
Widget btnFlatButtonBorderOnlyWidget({
required VoidCallback onPressed,
double width = 88,
double height = 44,
required String iconFileName,
}) {
return Container(
width: width.w,
height: height.h,
child: TextButton(
style: ButtonStyle(
// textStyle: MaterialStateProperty.all(TextStyle(
// fontSize: 16.sp,
// )),
// foregroundColor: MaterialStateProperty.resolveWith(
// (states) {
// if (states.contains(MaterialState.focused) &&
// !states.contains(MaterialState.pressed)) {
// return Colors.blue;
// } else if (states.contains(MaterialState.pressed)) {
// return Colors.deepPurple;
// }
// return AppColors.primaryElementText;
// },
// ),
// backgroundColor: MaterialStateProperty.resolveWith((states) {
// if (states.contains(MaterialState.pressed)) {
// return Colors.blue[200];
// }
// return AppColors.primaryElement;
// }),
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: Radii.k6pxRadius,
)),
),
child: Image.asset(
"assets/images/icons-$iconFileName.png",
),
onPressed: onPressed,
),
);
}
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:chart/common/values/values.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
/// 缓存图片
Widget netImageCached(
String url, {
double width = 48,
double height = 48,
EdgeInsetsGeometry? margin,
}) {
return CachedNetworkImage(
imageUrl: url,
imageBuilder: (context, imageProvider) => Container(
height: height.h,
width: width.w,
margin: margin,
decoration: BoxDecoration(
borderRadius: Radii.k6pxRadius,
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
// colorFilter: ColorFilter.mode(Colors.red, BlendMode.colorBurn),
),
),
),
placeholder: (context, url) {
return Container(
alignment: Alignment.center,
child: CircularProgressIndicator(),
);
},
errorWidget: (context, url, error) => Icon(Icons.error),
);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment