From 69f3d9d64c798f4c867ee4ce77cec21009d51f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=A4=A9?= Date: Fri, 21 Jul 2023 18:15:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90Application-Main=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E7=9A=84=E4=B8=80=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/config/proxy.dart | 5 +- lib/data/model/categories.dart | 31 +++++ lib/data/model/channels.dart | 27 ++++ lib/data/model/news.dart | 131 ++++++++++++++++++ lib/data/model/tag.dart | 61 ++++++++ lib/data/provider/news.dart | 83 +++++++++++ lib/data/repository/news_repository.dart | 51 +++++++ lib/main.dart | 3 +- lib/modules/application/application_page.dart | 6 +- lib/modules/category/category_binding.dart | 10 ++ lib/modules/category/category_controller.dart | 5 + lib/modules/category/category_page.dart | 15 ++ lib/modules/main/main_binding.dart | 5 +- lib/modules/main/main_controller.dart | 51 +++++++ lib/modules/main/main_page.dart | 22 ++- lib/modules/main/main_state.dart | 47 +++++++ lib/modules/main/widgets/categories.dart | 47 +++++++ lib/modules/main/widgets/recommend.dart | 106 ++++++++++++++ lib/modules/widgets/image.dart | 34 +++++ lib/routes/app_pages.dart | 10 ++ lib/utils/date.dart | 27 ++++ lib/utils/net_cache.dart | 1 + 22 files changed, 767 insertions(+), 11 deletions(-) create mode 100644 lib/data/model/categories.dart create mode 100644 lib/data/model/channels.dart create mode 100644 lib/data/model/news.dart create mode 100644 lib/data/model/tag.dart create mode 100644 lib/data/provider/news.dart create mode 100644 lib/data/repository/news_repository.dart create mode 100644 lib/modules/category/category_binding.dart create mode 100644 lib/modules/category/category_controller.dart create mode 100644 lib/modules/category/category_page.dart create mode 100644 lib/modules/main/main_state.dart create mode 100644 lib/modules/main/widgets/categories.dart create mode 100644 lib/modules/main/widgets/recommend.dart create mode 100644 lib/modules/widgets/image.dart create mode 100644 lib/utils/date.dart diff --git a/lib/config/proxy.dart b/lib/config/proxy.dart index ef9a530..eabd7ab 100644 --- a/lib/config/proxy.dart +++ b/lib/config/proxy.dart @@ -2,8 +2,7 @@ const ProxyEnable = false; /// 代理服务IP -// const PROXY_IP = '192.168.1.105'; -const ProxyIP = '172.16.43.74'; +const ProxyIP = '172.31.163.87'; /// 代理服务端口 -const ProxyPort = 8866; \ No newline at end of file +const ProxyPort = 7890; \ No newline at end of file diff --git a/lib/data/model/categories.dart b/lib/data/model/categories.dart new file mode 100644 index 0000000..b18a14a --- /dev/null +++ b/lib/data/model/categories.dart @@ -0,0 +1,31 @@ +import 'dart:convert'; + +/// 新闻分类 response +class CategoryResponse { + String code; + String title; + + CategoryResponse({ + required this.code, + required this.title, + }); + + factory CategoryResponse.fromRawJson(String str) => CategoryResponse.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory CategoryResponse.fromJson(Map json) => CategoryResponse( + code: json["code"], + title: json["title"], + ); + + Map toJson() => { + "code": code, + "title": title, + }; + + @override + String toString() { + return "$title【$code】"; + } +} diff --git a/lib/data/model/channels.dart b/lib/data/model/channels.dart new file mode 100644 index 0000000..45f5e35 --- /dev/null +++ b/lib/data/model/channels.dart @@ -0,0 +1,27 @@ +import 'dart:convert'; + + +/// 频道列表 response +class ChannelResponse { + String code; + String title; + + ChannelResponse({ + required this.code, + required this.title, + }); + + factory ChannelResponse.fromRawJson(String str) => ChannelResponse.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory ChannelResponse.fromJson(Map json) => ChannelResponse( + code: json["code"], + title: json["title"], + ); + + Map toJson() => { + "code": code, + "title": title, + }; +} diff --git a/lib/data/model/news.dart b/lib/data/model/news.dart new file mode 100644 index 0000000..2ed422d --- /dev/null +++ b/lib/data/model/news.dart @@ -0,0 +1,131 @@ +/// 新闻分页 request +class NewsPageListRequest { + String? categoryCode; + String? channelCode; + String? tag; + String? keyword; + int? pageNum; + int? pageSize; + + NewsPageListRequest({ + this.categoryCode, + this.channelCode, + this.tag, + this.keyword, + this.pageNum, + this.pageSize, + }); + + Map toJson() => { + "categoryCode": categoryCode, + "channelCode": channelCode, + "tag": tag, + "keyword": keyword, + "pageNum": pageNum, + "pageSize": pageSize, + }; +} + + +/// 新闻分页 response +class NewsPageListResponse { + int? counts; + int? pagesize; + int? pages; + int? page; + List? items; + + NewsPageListResponse({ + this.counts, + this.pagesize, + this.pages, + this.page, + this.items, + }); + + factory NewsPageListResponse.fromJson(Map json) => + NewsPageListResponse( + counts: json["counts"], + pagesize: json["pagesize"], + pages: json["pages"], + page: json["page"], + items: json["items"] == null + ? [] + : List.from( + json["items"].map((x) => NewsItem.fromJson(x))), + ); + + Map toJson() => { + "counts": counts ?? 0, + "pagesize": pagesize ?? 0, + "pages": pages ?? 0, + "page": page ?? 0, + "items": items == null + ? [] + : List.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 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 toJson() => { + "id": id, + "title": title, + "category": category, + "thumbnail": thumbnail, + "author": author, + "addtime": addtime?.toIso8601String(), + "url": url, + }; +} + + +/// 新闻推荐 request +class NewsRecommendRequest { + String? categoryCode; + String? channelCode; + String? tag; + String? keyword; + + NewsRecommendRequest({ + this.categoryCode, + this.channelCode, + this.tag, + this.keyword, + }); + + Map toJson() => { + "categoryCode": categoryCode, + "channelCode": channelCode, + "tag": tag, + "keyword": keyword, + }; +} \ No newline at end of file diff --git a/lib/data/model/tag.dart b/lib/data/model/tag.dart new file mode 100644 index 0000000..bdb53f8 --- /dev/null +++ b/lib/data/model/tag.dart @@ -0,0 +1,61 @@ +import 'dart:convert'; + +/// 标签列表 Request +class TagRequest { + String categoryCode; + String channelCode; + String tag; + String keyword; + String newsId; + + TagRequest({ + required this.categoryCode, + required this.channelCode, + required this.tag, + required this.keyword, + required this.newsId, + }); + + factory TagRequest.fromRawJson(String str) => TagRequest.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory TagRequest.fromJson(Map json) => TagRequest( + categoryCode: json["categoryCode"], + channelCode: json["channelCode"], + tag: json["tag"], + keyword: json["keyword"], + newsId: json["newsID"], + ); + + Map toJson() => { + "categoryCode": categoryCode, + "channelCode": channelCode, + "tag": tag, + "keyword": keyword, + "newsID": newsId, + }; +} + + +/// 标签列表 Response +class TagResponse { + String? tag; + + TagResponse({ + this.tag, + }); + + factory TagResponse.fromRawJson(String str) => TagResponse.fromJson(json.decode(str)); + + String toRawJson() => json.encode(toJson()); + + factory TagResponse.fromJson(Map json) => TagResponse( + tag: json["tag"], + ); + + Map toJson() => { + "tag": tag, + }; +} + diff --git a/lib/data/provider/news.dart b/lib/data/provider/news.dart new file mode 100644 index 0000000..0bb6c80 --- /dev/null +++ b/lib/data/provider/news.dart @@ -0,0 +1,83 @@ +import 'package:news_getx/config/storage.dart'; +import 'package:news_getx/data/model/categories.dart'; +import 'package:news_getx/data/model/channels.dart'; +import 'package:news_getx/data/model/news.dart'; +import 'package:news_getx/data/model/tag.dart'; +import 'package:news_getx/utils/http.dart'; + +/// 新闻API +class NewsAPI { + /// 翻页 + /// refresh 是否刷新 + static Future newsPageList({ + NewsPageListRequest? params, + bool refresh = false, + bool cacheDisk = false, + }) async { + var response = await HttpUtil().get( + "/news", + queryParameters: params?.toJson(), + refresh: refresh, + cacheDisk: cacheDisk, + cacheKey: StorageIndexNewsCacheKey, + ); + return NewsPageListResponse.fromJson(response); + } + + /// 推荐 + static Future newsRecommend({ + NewsRecommendRequest? 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> categories({ + bool cacheDisk = false, + }) async { + var response = await HttpUtil().get( + '/categories', + cacheDisk: cacheDisk, + ); + return response + .map((item) => CategoryResponse.fromJson(item)) + .toList(); + } + + /// 频道 + static Future> channels({ + bool cacheDisk = false, + }) async { + var response = await HttpUtil().get( + '/channels', + cacheDisk: cacheDisk, + ); + return response + .map((item) => ChannelResponse.fromJson(item)) + .toList(); + } + + /// 标签列表 + static Future> tags({ + TagRequest? params, + bool cacheDisk = false, + }) async { + var response = await HttpUtil().get( + '/tags', + queryParameters: params?.toJson(), + cacheDisk: cacheDisk, + ); + + return response + .map((item) => TagResponse.fromJson(item)) + .toList(); + } +} diff --git a/lib/data/repository/news_repository.dart b/lib/data/repository/news_repository.dart new file mode 100644 index 0000000..72565af --- /dev/null +++ b/lib/data/repository/news_repository.dart @@ -0,0 +1,51 @@ +import 'package:news_getx/data/model/news.dart'; +import 'package:news_getx/data/provider/news.dart'; + +import '../model/categories.dart'; +import '../model/channels.dart'; +import '../model/tag.dart'; + +class NewsRepository { + Future newsPageList({ + NewsPageListRequest? params, + bool refresh = false, + bool cacheDisk = false, + }) { + return NewsAPI.newsPageList( + params: params, + refresh: refresh, + cacheDisk: cacheDisk, + ); + } + + Future newsRecommend({ + NewsRecommendRequest? params, + bool refresh = false, + bool cacheDisk = false, + }) { + return NewsAPI.newsRecommend( + params: params, + refresh: refresh, + cacheDisk: cacheDisk, + ); + } + + Future> categories({ + bool cacheDisk = false, + }) { + return NewsAPI.categories(cacheDisk: cacheDisk); + } + + Future> channels({ + bool cacheDisk = false, + }) { + return NewsAPI.channels(cacheDisk: cacheDisk); + } + + Future> tags({ + TagRequest? params, + bool cacheDisk = false, + }) { + return NewsAPI.tags(params: params, cacheDisk: cacheDisk); + } +} diff --git a/lib/main.dart b/lib/main.dart index 583c277..04d1d66 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -34,7 +34,8 @@ class MyApp extends StatelessWidget { title: 'News', debugShowCheckedModeBanner: false, theme: AppTheme.light, - initialRoute: AppRoutes.Initial, + // initialRoute: AppRoutes.Initial, + initialRoute: AppRoutes.Application, getPages: AppPages.pages, builder: EasyLoading.init(), ), diff --git a/lib/modules/application/application_page.dart b/lib/modules/application/application_page.dart index df73b72..8806ba3 100644 --- a/lib/modules/application/application_page.dart +++ b/lib/modules/application/application_page.dart @@ -1,6 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; +import 'package:news_getx/modules/category/category_page.dart'; +import 'package:news_getx/modules/main/main_page.dart'; import 'package:news_getx/modules/widgets/app_bar.dart'; import 'package:news_getx/theme/app_colors.dart'; @@ -41,8 +43,8 @@ class ApplicationPage extends GetView { controller: controller.pageController, onPageChanged: controller.handlePageChange, children: [ - Text('Main'), - Text('Category'), + MainPage(), + Text('Categories'), Text('BookmarksPage'), Text('AccountPage'), ], diff --git a/lib/modules/category/category_binding.dart b/lib/modules/category/category_binding.dart new file mode 100644 index 0000000..487dd98 --- /dev/null +++ b/lib/modules/category/category_binding.dart @@ -0,0 +1,10 @@ +import 'package:get/get.dart'; + +import 'category_controller.dart'; + +class CategoryBinding extends Bindings { + @override + void dependencies() { + Get.lazyPut(() => CategoryController()); + } +} diff --git a/lib/modules/category/category_controller.dart b/lib/modules/category/category_controller.dart new file mode 100644 index 0000000..22c7ccc --- /dev/null +++ b/lib/modules/category/category_controller.dart @@ -0,0 +1,5 @@ +import 'package:get/get.dart'; + +class CategoryController extends GetxController { + +} diff --git a/lib/modules/category/category_page.dart b/lib/modules/category/category_page.dart new file mode 100644 index 0000000..a795815 --- /dev/null +++ b/lib/modules/category/category_page.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import 'category_controller.dart'; + +class CategoryPage extends StatelessWidget { + const CategoryPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final controller = Get.find(); + + return Container(); + } +} diff --git a/lib/modules/main/main_binding.dart b/lib/modules/main/main_binding.dart index b34edf1..fa70494 100644 --- a/lib/modules/main/main_binding.dart +++ b/lib/modules/main/main_binding.dart @@ -1,10 +1,13 @@ import 'package:get/get.dart'; +import 'package:news_getx/data/repository/news_repository.dart'; import 'main_controller.dart'; class MainBinding extends Bindings { @override void dependencies() { - Get.lazyPut(() => MainController()); + Get.lazyPut(() => MainController( + newsRepository: NewsRepository(), + )); } } diff --git a/lib/modules/main/main_controller.dart b/lib/modules/main/main_controller.dart index 027fc9e..c319493 100644 --- a/lib/modules/main/main_controller.dart +++ b/lib/modules/main/main_controller.dart @@ -1,5 +1,56 @@ import 'package:get/get.dart'; +import 'package:news_getx/data/model/news.dart'; +import 'package:news_getx/data/repository/news_repository.dart'; +import 'package:news_getx/modules/main/main_state.dart'; class MainController extends GetxController { + NewsRepository newsRepository; + MainController({required this.newsRepository}); + + /// 响应式成员变量 + /// 在Getx中,当一个对象被注册为可观察对象(Observable), + /// Getx会自动将其所有属性都转换为可观察属性(Observable)。 + /// 这意味着,无论是直接在GetxController中定义的属性, + /// 还是在其内部嵌套的对象中定义的属性, + /// 只要它们被定义为可观察属性,GetxController都会监听它们的变化。 + final state = MainState(); + + /// 方法 + // 拉取数据 + asyncLoadAllData() async { + state.categories = await newsRepository.categories(cacheDisk: true); + state.channels = await newsRepository.channels(cacheDisk: true); + // 分类对应的数据(推荐、新闻) + state.newsRecommend = await newsRepository.newsRecommend(cacheDisk: true); + state.newsPageList = await newsRepository.newsPageList(cacheDisk: true); + // 所选分类 + state.selCategoryCode = state.categories?.first.code; + } + + // 拉取推荐、新闻 + asyncLoadNewsData( + categoryCode, { + bool refresh = false, + }) async { + state.selCategoryCode = categoryCode; + state.newsRecommend = await newsRepository.newsRecommend( + params: NewsRecommendRequest(categoryCode: categoryCode), + refresh: refresh, + cacheDisk: true, + ); + state.newsPageList = await newsRepository.newsPageList( + params: NewsPageListRequest(categoryCode: categoryCode), + refresh: refresh, + cacheDisk: true, + ); + } + + /// 生命周期 + @override + void onReady() { + super.onReady(); + // 异步拉取数据 + asyncLoadAllData(); + } } diff --git a/lib/modules/main/main_page.dart b/lib/modules/main/main_page.dart index 95ef0ba..5129bc9 100644 --- a/lib/modules/main/main_page.dart +++ b/lib/modules/main/main_page.dart @@ -1,15 +1,29 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; +import 'package:news_getx/modules/main/widgets/categories.dart'; +import 'package:news_getx/modules/main/widgets/recommend.dart'; import 'main_controller.dart'; -class MainPage extends StatelessWidget { +class MainPage extends GetView { const MainPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - final controller = Get.find(); - - return Container(); + return SingleChildScrollView( + child: Column( + children: [ + NewsCategoriesWidget(), + Divider(height: 1), + NewsRecommendWidget(), + Divider(height: 1), + Text('NewsChannelsWidget'), + Divider(height: 1), + Text('NewsListWidget'), + Divider(height: 1), + Text('NewsletterWidget'), + ], + ), + ); } } diff --git a/lib/modules/main/main_state.dart b/lib/modules/main/main_state.dart new file mode 100644 index 0000000..c0a09d7 --- /dev/null +++ b/lib/modules/main/main_state.dart @@ -0,0 +1,47 @@ +import 'package:get/get.dart'; +import 'package:news_getx/data/model/categories.dart'; +import 'package:news_getx/data/model/channels.dart'; +import 'package:news_getx/data/model/news.dart'; + +class MainState { + // 分类 + var _categories = Rx?>(null); + + set categories(value) => _categories.value = value; + + List? get categories => _categories.value; + + // 新闻翻页 + var _newsPageList = Rx(null); + + set newsPageList(value) => _newsPageList.value = value; + + NewsPageListResponse? get newsPageList => _newsPageList.value; + + void appendNewsPageList(NewsPageListResponse value) { + if (_newsPageList.value != null) { + _newsPageList.value!.items?.addAll(value.items!.toList()); + } + } + + // 新闻推荐 + var _newsRecommend = Rx(null); + + set newsRecommend(value) => _newsRecommend.value = value; + + NewsItem? get newsRecommend => _newsRecommend.value; + + // 频道 + var _channels = Rx?>(null); + + set channels(value) => _channels.value = value; + + List? get channels => _channels.value; + + // 选中的分类Code + var _selCategoryCode = "".obs; + + set selCategoryCode(value) => _selCategoryCode.value = value; + + String get selCategoryCode => _selCategoryCode.value; +} diff --git a/lib/modules/main/widgets/categories.dart b/lib/modules/main/widgets/categories.dart new file mode 100644 index 0000000..eaab1a8 --- /dev/null +++ b/lib/modules/main/widgets/categories.dart @@ -0,0 +1,47 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:news_getx/modules/main/main_controller.dart'; +import 'package:news_getx/theme/app_colors.dart'; + +class NewsCategoriesWidget extends GetView { + @override + Widget build(BuildContext context) { + // 用的是Row 而不是 Tab + return Obx( + () => controller.state.categories == null + ? Container() + : SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: controller.state.categories!.map( + (item) { + return Container( + alignment: Alignment.center, + height: 52.h, + padding: EdgeInsets.symmetric(horizontal: 8), + child: GestureDetector( + onTap: () { + // 拉取对应分类的数据 + controller.asyncLoadNewsData(item.code); + }, + child: Text( + item.title, + style: TextStyle( + color: controller.state.selCategoryCode == item.code + ? AppColors.secondaryElementText + : AppColors.primaryText, + fontSize: 18.h, + fontFamily: 'Montserrat', + fontWeight: FontWeight.w600, + ), + ), + ), + ); + }, + ).toList(), + ), + ), + ); + } +} diff --git a/lib/modules/main/widgets/recommend.dart b/lib/modules/main/widgets/recommend.dart new file mode 100644 index 0000000..77864b1 --- /dev/null +++ b/lib/modules/main/widgets/recommend.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:news_getx/modules/main/main_controller.dart'; +import 'package:news_getx/modules/widgets/image.dart'; +import 'package:news_getx/theme/app_colors.dart'; +import 'package:news_getx/utils/date.dart'; + +class NewsRecommendWidget extends GetView { + @override + Widget build(BuildContext context) { + print(controller.state.newsRecommend?.thumbnail); + return Obx( + () => controller.state.newsRecommend == null + ? Container() + : Container( + margin: EdgeInsets.all(20.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 图 + InkWell( + onTap: () { + print("进入详情页"); + }, + child: netImageCached( + controller.state.newsRecommend?.thumbnail ?? "", + width: 335.w, + height: 290.h, + ), + ), + // 作者 + Container( + margin: EdgeInsets.only(top: 14.h), + child: Text( + controller.state.newsRecommend!.author ?? "", + style: TextStyle( + fontFamily: 'Avenir', + fontWeight: FontWeight.normal, + color: AppColors.thirdElementText, + fontSize: 14.sp, + ), + ), + ), + // 标题 + + // 一行 3 列 + Container( + margin: EdgeInsets.only(top: 10.h), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 120), + child: Text( + controller.state.newsRecommend!.category ?? "", + style: TextStyle( + fontFamily: 'Avenir', + fontWeight: FontWeight.normal, + color: AppColors.secondaryElementText, + fontSize: 14.sp, + height: 1, + ), + overflow: TextOverflow.clip, + maxLines: 1, + ), + ), + // 添加时间 + Container( + width: 15.w, + ), + ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 120), + child: Text( + '• ${timeLineFormat(controller.state.newsRecommend!.addtime!)}', + style: TextStyle( + fontFamily: 'Avenir', + fontWeight: FontWeight.normal, + color: AppColors.thirdElementText, + fontSize: 14.sp, + height: 1, + ), + overflow: TextOverflow.clip, + maxLines: 1, + ), + ), + // 占满剩余空间 + Spacer(), + // 更多 + InkWell( + child: Icon( + Icons.more_horiz, + color: AppColors.primaryText, + size: 24, + ), + onTap: () {}, + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/modules/widgets/image.dart b/lib/modules/widgets/image.dart new file mode 100644 index 0000000..e59afdd --- /dev/null +++ b/lib/modules/widgets/image.dart @@ -0,0 +1,34 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:news_getx/theme/app_radii.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, + )), + ), + placeholder: (context, url) { + return Container( + alignment: Alignment.center, + child: CircularProgressIndicator(), + ); + }, + errorWidget: (context, url, error) => Icon(Icons.error), + ); +} diff --git a/lib/routes/app_pages.dart b/lib/routes/app_pages.dart index 6dcfdd7..c559bdc 100644 --- a/lib/routes/app_pages.dart +++ b/lib/routes/app_pages.dart @@ -1,6 +1,9 @@ import 'package:get/get.dart'; import 'package:news_getx/modules/application/application_binding.dart'; import 'package:news_getx/modules/application/application_page.dart'; +import 'package:news_getx/modules/category/category_binding.dart'; +import 'package:news_getx/modules/category/category_page.dart'; +import 'package:news_getx/modules/main/main_binding.dart'; import 'package:news_getx/modules/not_found/not_found_binding.dart'; import 'package:news_getx/modules/not_found/not_found_page.dart'; import 'package:news_getx/modules/sign_in/sign_in_binding.dart'; @@ -40,6 +43,13 @@ abstract class AppPages { name: AppRoutes.Application, page: () => ApplicationPage(), binding: ApplicationBinding(), + bindings: [MainBinding(), CategoryBinding()] + ), + // 分类页 + GetPage( + name: AppRoutes.Category, + page: () => CategoryPage(), + binding: CategoryBinding(), ), ]; } diff --git a/lib/utils/date.dart b/lib/utils/date.dart new file mode 100644 index 0000000..f493fdd --- /dev/null +++ b/lib/utils/date.dart @@ -0,0 +1,27 @@ +import 'package:intl/intl.dart'; + +/// 格式化时间 +String timeLineFormat(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 = DateFormat('MM-dd'); + return dtFormat.format(dt); + } + // yyyy-MM-dd + else { + final dtFormat = DateFormat('yyyy-MM-dd'); + var str = dtFormat.format(dt); + return str; + } +} \ No newline at end of file diff --git a/lib/utils/net_cache.dart b/lib/utils/net_cache.dart index fc0029c..6a1e162 100644 --- a/lib/utils/net_cache.dart +++ b/lib/utils/net_cache.dart @@ -21,6 +21,7 @@ class CacheObject { class NetCache extends Interceptor { // 为确保迭代器顺序和对象插入时间一致顺序一致,我们使用LinkedHashMap, 默认的字面量{}就是有序的 + // 内存缓存 var cache = {}; @override