├── ios
├── Runner
│ ├── Runner-Bridging-Header.h
│ ├── Assets.xcassets
│ │ ├── LaunchImage.imageset
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ ├── README.md
│ │ │ └── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-83.5x83.5@2x.png
│ │ │ └── Contents.json
│ ├── AppDelegate.swift
│ ├── Base.lproj
│ │ ├── Main.storyboard
│ │ └── LaunchScreen.storyboard
│ └── Info.plist
├── Flutter
│ ├── Debug.xcconfig
│ ├── Release.xcconfig
│ └── AppFrameworkInfo.plist
├── Runner.xcodeproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── WorkspaceSettings.xcsettings
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── WorkspaceSettings.xcsettings
│ │ └── IDEWorkspaceChecks.plist
├── .gitignore
└── Podfile
├── assets
├── screenshot
│ ├── me.png
│ ├── book.png
│ ├── home.png
│ ├── login.png
│ ├── project.png
│ ├── search.png
│ ├── home_dark.png
│ ├── knowledge.png
│ ├── register.png
│ ├── book_details.png
│ ├── article_details.png
│ ├── category_dark.png
│ └── knowledge_dark.png
└── images
│ ├── ic_logo.png
│ ├── ic_tab_me.png
│ ├── ic_tab_book.png
│ ├── ic_tab_home.png
│ ├── ic_tab_project.png
│ └── ic_tab_knowledge.png
├── android
├── gradle.properties
├── app
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── drawable
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── drawable-v21
│ │ │ │ │ └── launch_background.xml
│ │ │ │ ├── values
│ │ │ │ │ └── styles.xml
│ │ │ │ └── values-night
│ │ │ │ │ └── styles.xml
│ │ │ ├── kotlin
│ │ │ │ └── com
│ │ │ │ │ └── zt
│ │ │ │ │ └── flutter_wan_android
│ │ │ │ │ └── MainActivity.kt
│ │ │ └── AndroidManifest.xml
│ │ ├── debug
│ │ │ └── AndroidManifest.xml
│ │ └── profile
│ │ │ └── AndroidManifest.xml
│ └── build.gradle
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
├── .gitignore
├── settings.gradle
└── build.gradle
├── lib
├── core
│ └── net
│ │ ├── cancel
│ │ ├── canceler.dart
│ │ ├── zt_http_cancel.dart
│ │ ├── cancel_manager.dart
│ │ ├── http_canceler.dart
│ │ └── http_cancel_manager.dart
│ │ ├── http_config.dart
│ │ ├── observer
│ │ └── http_lifecycle_observer.dart
│ │ ├── http_result.dart
│ │ ├── convert
│ │ └── json_converter.dart
│ │ └── http_request.dart
├── config
│ ├── hero_config.dart
│ └── router_config.dart
├── utils
│ ├── string_util.dart
│ ├── log_util.dart
│ ├── toast_util.dart
│ ├── format_util.dart
│ ├── shared_preferences_utils.dart
│ └── screen_util.dart
├── base
│ └── abs_dao.dart
├── modules
│ ├── knowledge
│ │ ├── model
│ │ │ ├── knowledge_entity.dart
│ │ │ ├── nav_entity.dart
│ │ │ └── knowledge_model.dart
│ │ ├── view_model
│ │ │ ├── knowledge_view_model.dart
│ │ │ └── knowledge_child_view_model.dart
│ │ └── view
│ │ │ └── main_knowledge.dart
│ ├── book
│ │ ├── model
│ │ │ ├── study_entity.dart
│ │ │ ├── book_entity.dart
│ │ │ ├── book_model.dart
│ │ │ └── study_dao.dart
│ │ ├── view_model
│ │ │ ├── book_view_model.dart
│ │ │ └── book_details_view_model.dart
│ │ └── view
│ │ │ └── main_book.dart
│ ├── home
│ │ ├── model
│ │ │ ├── banner_entity.dart
│ │ │ └── home_model.dart
│ │ ├── view_model
│ │ │ └── home_view_model.dart
│ │ └── widget
│ │ │ └── banner_widget.dart
│ ├── account
│ │ ├── view_model
│ │ │ ├── login_view_model.dart
│ │ │ └── register_view_model.dart
│ │ ├── model
│ │ │ ├── user_entity.dart
│ │ │ └── account_model.dart
│ │ └── widget
│ │ │ ├── login_button.dart
│ │ │ └── login_text_field.dart
│ ├── article
│ │ ├── view_model
│ │ │ └── article_details_view_model.dart
│ │ ├── model
│ │ │ └── article_entity.dart
│ │ ├── widget
│ │ │ └── item_article_widget.dart
│ │ └── view
│ │ │ └── article_details_page.dart
│ ├── search
│ │ ├── model
│ │ │ ├── search_entity.dart
│ │ │ ├── search_model.dart
│ │ │ └── search_dao.dart
│ │ └── view_model
│ │ │ └── search_view_model.dart
│ ├── project
│ │ ├── model
│ │ │ ├── category_entity.dart
│ │ │ └── project_model.dart
│ │ └── view_model
│ │ │ ├── project_item_view_model.dart
│ │ │ └── project_view_model.dart
│ ├── main
│ │ ├── view_model
│ │ │ ├── locale_view_model.dart
│ │ │ └── theme_view_model.dart
│ │ └── view
│ │ │ ├── preview_page.dart
│ │ │ └── main_page.dart
│ ├── collect
│ │ ├── view_model
│ │ │ └── collection_list_view_model.dart
│ │ └── model
│ │ │ └── collect_model.dart
│ └── me
│ │ └── view_model
│ │ └── me_view_model.dart
├── generated
│ ├── json
│ │ ├── base
│ │ │ ├── json_field.dart
│ │ │ └── json_convert_content.dart
│ │ ├── search_entity.g.dart
│ │ ├── category_entity.g.dart
│ │ ├── nav_entity.g.dart
│ │ ├── banner_entity.g.dart
│ │ ├── user_entity.g.dart
│ │ ├── book_entity.g.dart
│ │ └── article_entity.g.dart
│ └── intl
│ │ ├── messages_all.dart
│ │ ├── messages_zh.dart
│ │ └── messages_en.dart
├── widget
│ ├── loading_dialog_helper.dart
│ └── loading_dialog_widget.dart
├── l10n
│ ├── intl_zh.arb
│ └── intl_en.arb
├── helper
│ ├── cookie_helper.dart
│ ├── db_helper.dart
│ ├── image_helper.dart
│ └── router_helper.dart
├── common
│ └── global_value.dart
└── main.dart
├── .gitignore
├── test
└── widget_test.dart
├── .metadata
├── analysis_options.yaml
├── pubspec.yaml
└── README.md
/ios/Runner/Runner-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | #import "GeneratedPluginRegistrant.h"
2 |
--------------------------------------------------------------------------------
/assets/screenshot/me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/me.png
--------------------------------------------------------------------------------
/assets/images/ic_logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/images/ic_logo.png
--------------------------------------------------------------------------------
/assets/images/ic_tab_me.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/images/ic_tab_me.png
--------------------------------------------------------------------------------
/assets/screenshot/book.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/book.png
--------------------------------------------------------------------------------
/assets/screenshot/home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/home.png
--------------------------------------------------------------------------------
/assets/screenshot/login.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/login.png
--------------------------------------------------------------------------------
/assets/images/ic_tab_book.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/images/ic_tab_book.png
--------------------------------------------------------------------------------
/assets/images/ic_tab_home.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/images/ic_tab_home.png
--------------------------------------------------------------------------------
/assets/screenshot/project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/project.png
--------------------------------------------------------------------------------
/assets/screenshot/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/search.png
--------------------------------------------------------------------------------
/android/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1536M
2 | android.useAndroidX=true
3 | android.enableJetifier=true
4 |
--------------------------------------------------------------------------------
/assets/images/ic_tab_project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/images/ic_tab_project.png
--------------------------------------------------------------------------------
/assets/screenshot/home_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/home_dark.png
--------------------------------------------------------------------------------
/assets/screenshot/knowledge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/knowledge.png
--------------------------------------------------------------------------------
/assets/screenshot/register.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/register.png
--------------------------------------------------------------------------------
/assets/images/ic_tab_knowledge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/images/ic_tab_knowledge.png
--------------------------------------------------------------------------------
/assets/screenshot/book_details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/book_details.png
--------------------------------------------------------------------------------
/assets/screenshot/article_details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/article_details.png
--------------------------------------------------------------------------------
/assets/screenshot/category_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/category_dark.png
--------------------------------------------------------------------------------
/assets/screenshot/knowledge_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/assets/screenshot/knowledge_dark.png
--------------------------------------------------------------------------------
/lib/core/net/cancel/canceler.dart:
--------------------------------------------------------------------------------
1 | /// 取消器
2 | abstract class Canceler {
3 | ///取消
4 | void cancel({dynamic reason});
5 | }
6 |
--------------------------------------------------------------------------------
/ios/Flutter/Debug.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/lib/config/hero_config.dart:
--------------------------------------------------------------------------------
1 | ///Hero动画配置
2 | class HeroConfig {
3 | ///图片预览
4 | static const String tagPreview = "tagPreview";
5 | }
6 |
--------------------------------------------------------------------------------
/ios/Flutter/Release.xcconfig:
--------------------------------------------------------------------------------
1 | #include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
2 | #include "Generated.xcconfig"
3 |
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
--------------------------------------------------------------------------------
/lib/utils/string_util.dart:
--------------------------------------------------------------------------------
1 | class StringUtil {
2 | ///移除html标签
3 | static String removeHtmlLabel(String data) {
4 | return data.replaceAll(RegExp('<[^>]+>'), '');
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png
--------------------------------------------------------------------------------
/lib/core/net/http_config.dart:
--------------------------------------------------------------------------------
1 | /// http 配置类
2 | class HttpConfig {
3 | static const String baseUrl = "https://www.wanandroid.com/"; //基础URL
4 | static const int timeout = 5000; //超时时间
5 | }
6 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RuffianZhong/FlutterApp/HEAD/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png
--------------------------------------------------------------------------------
/lib/core/net/cancel/zt_http_cancel.dart:
--------------------------------------------------------------------------------
1 | library zt_http_cancel;
2 |
3 | export 'cancel_manager.dart';
4 | export 'canceler.dart';
5 | export 'http_canceler.dart';
6 | export 'http_cancel_manager.dart';
7 |
--------------------------------------------------------------------------------
/android/app/src/main/kotlin/com/zt/flutter_wan_android/MainActivity.kt:
--------------------------------------------------------------------------------
1 | package com.zt.flutter_wan_android
2 |
3 | import io.flutter.embedding.android.FlutterActivity
4 |
5 | class MainActivity: FlutterActivity() {
6 | }
7 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/lib/utils/log_util.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/foundation.dart';
2 |
3 | /// 日志工具类
4 | class Logger {
5 | static void log(Object? object) {
6 | if (kDebugMode) {
7 | print(object);
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Fri Jun 23 08:50:38 CEST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-all.zip
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .dart_tool/*
2 | .idea/*
3 | build/*
4 | pubspec.lock
5 | .flutter-plugins
6 | .flutter-plugins-dependencies
7 | .packages
8 | flutter_wan_android.iml
9 |
10 | #ios
11 | ios/Pods/*
12 | ios/.symlinks/*
13 | ios/Podfile.lock
14 |
15 | #android
16 | android/.idea/*
17 | android/.gradle/*
18 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/lib/base/abs_dao.dart:
--------------------------------------------------------------------------------
1 | import '../helper/db_helper.dart';
2 |
3 | ///数据库操作相关Dao抽象基类
4 | abstract class AbsDao {
5 | ///数据库辅助类
6 | late SqliteHelper helper;
7 |
8 | AbsDao() {
9 | helper = SqliteHelper();
10 | }
11 |
12 | ///使用完一定要关闭数据库
13 | void close() {
14 | helper.close();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PreviewsEnabled
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/.gitignore:
--------------------------------------------------------------------------------
1 | gradle-wrapper.jar
2 | /.gradle
3 | /captures/
4 | /gradlew
5 | /gradlew.bat
6 | /local.properties
7 | GeneratedPluginRegistrant.java
8 |
9 | # Remember to never publicly share your keystore.
10 | # See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
11 | key.properties
12 | **/*.keystore
13 | **/*.jks
14 |
--------------------------------------------------------------------------------
/lib/modules/knowledge/model/knowledge_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_wan_android/modules/knowledge/model/nav_entity.dart';
2 | import 'package:flutter_wan_android/modules/project/model/category_entity.dart';
3 |
4 | ///知识实体类
5 | class KnowledgeEntity {
6 | ///分类列表
7 | List categoryList = [];
8 |
9 | ///导航列表
10 | List navList = [];
11 | }
12 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md:
--------------------------------------------------------------------------------
1 | # Launch Screen Assets
2 |
3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory.
4 |
5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
--------------------------------------------------------------------------------
/lib/utils/toast_util.dart:
--------------------------------------------------------------------------------
1 | import 'dart:ui';
2 |
3 | import 'package:fluttertoast/fluttertoast.dart';
4 |
5 | ///吐司工具类
6 | class ToastUtil {
7 | ///显示吐司
8 | static showToast(
9 | {required String msg,
10 | double? fontSize,
11 | ToastGravity? gravity,
12 | Color? backgroundColor,
13 | Color? textColor}) {
14 | Fluttertoast.showToast(msg: msg);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/lib/core/net/cancel/cancel_manager.dart:
--------------------------------------------------------------------------------
1 | import 'canceler.dart';
2 |
3 | /// 取消管理类
4 | abstract class CancelManager {
5 | /// 添加/绑定取消器
6 | void bindCancel(Object object, Canceler canceler);
7 |
8 | /// 取消/移除cancel
9 | void cancel(Object object, [dynamic reason]);
10 |
11 | /// 取消/移除全部cancel
12 | void cancelAll();
13 |
14 | /// 是否已经取消
15 | bool isCanceled(Object object);
16 |
17 | /// 获取canceler
18 | Canceler? getCanceler(Object object);
19 | }
20 |
--------------------------------------------------------------------------------
/android/app/src/debug/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/android/app/src/profile/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ios/Runner/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import Flutter
3 |
4 | @UIApplicationMain
5 | @objc class AppDelegate: FlutterAppDelegate {
6 | override func application(
7 | _ application: UIApplication,
8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
9 | ) -> Bool {
10 | GeneratedPluginRegistrant.register(with: self)
11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions)
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/android/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
3 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
4 | def properties = new Properties()
5 |
6 | assert localPropertiesFile.exists()
7 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
8 |
9 | def flutterSdkPath = properties.getProperty("flutter.sdk")
10 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
11 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
12 |
--------------------------------------------------------------------------------
/lib/modules/book/model/study_entity.dart:
--------------------------------------------------------------------------------
1 | ///教程学习进度
2 | class StudyEntity {
3 | ///表ID
4 | int? id;
5 |
6 | ///教程ID
7 | late int bookId;
8 |
9 | ///文章ID:章节ID
10 | late int articleId;
11 |
12 | ///学习进度
13 | late double progress;
14 |
15 | ///学习时间
16 | late int time;
17 |
18 | StudyEntity(
19 | {this.id,
20 | required this.bookId,
21 | required this.articleId,
22 | required this.progress,
23 | required this.time});
24 |
25 | Map toJson() => {};
26 | }
27 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/android/app/src/main/res/drawable-v21/launch_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
--------------------------------------------------------------------------------
/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "LaunchImage.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "filename" : "LaunchImage@2x.png",
11 | "scale" : "2x"
12 | },
13 | {
14 | "idiom" : "universal",
15 | "filename" : "LaunchImage@3x.png",
16 | "scale" : "3x"
17 | }
18 | ],
19 | "info" : {
20 | "version" : 1,
21 | "author" : "xcode"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/lib/modules/home/model/banner_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_wan_android/generated/json/base/json_field.dart';
2 | import 'package:flutter_wan_android/generated/json/banner_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | @JsonSerializable()
6 | class BannerEntity {
7 |
8 | late int id;
9 | late String imagePath;
10 | late String title;
11 | late String url;
12 |
13 | BannerEntity();
14 |
15 | factory BannerEntity.fromJson(Map json) => $BannerEntityFromJson(json);
16 |
17 | Map toJson() => $BannerEntityToJson(this);
18 |
19 | @override
20 | String toString() {
21 | return jsonEncode(this);
22 | }
23 | }
--------------------------------------------------------------------------------
/lib/generated/json/base/json_field.dart:
--------------------------------------------------------------------------------
1 | // ignore_for_file: non_constant_identifier_names
2 | // ignore_for_file: camel_case_types
3 | // ignore_for_file: prefer_single_quotes
4 |
5 | // This file is automatically generated. DO NOT EDIT, all your changes would be lost.
6 |
7 | class JsonSerializable{
8 | const JsonSerializable();
9 | }
10 |
11 | class JSONField {
12 | //Specify the parse field name
13 | final String? name;
14 |
15 | //Whether to participate in toJson
16 | final bool? serialize;
17 |
18 | //Whether to participate in fromMap
19 | final bool? deserialize;
20 |
21 | const JSONField({this.name, this.serialize, this.deserialize});
22 | }
23 |
--------------------------------------------------------------------------------
/lib/widget/loading_dialog_helper.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_wan_android/widget/loading_dialog_widget.dart';
3 |
4 | class LoadingDialogHelper {
5 | ///展示loading弹窗
6 | static void showLoading(BuildContext context, {bool dismissible = false}) {
7 | showDialog(
8 | barrierDismissible: dismissible,
9 | context: context,
10 | builder: (context) {
11 | return LoadingDialogWidget(
12 | dismissible: dismissible,
13 | );
14 | });
15 | }
16 |
17 | ///关闭弹窗
18 | static void dismissLoading(BuildContext context) {
19 | Navigator.pop(context);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/modules/account/view_model/login_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 |
3 | import '../model/account_model.dart';
4 |
5 | class LoginViewModel extends ChangeNotifier {
6 | late AccountModel model;
7 |
8 | LoginViewModel() {
9 | model = AccountModel();
10 | }
11 |
12 | ///允许登录
13 | bool _canLogin = false;
14 |
15 | bool get canLogin => _canLogin;
16 |
17 | set canLogin(bool value) {
18 | _canLogin = value;
19 | notifyListeners();
20 | }
21 |
22 | ///密码模式
23 | bool _obscureText = true;
24 |
25 | bool get obscureText => _obscureText;
26 |
27 | set obscureText(bool value) {
28 | _obscureText = value;
29 | notifyListeners();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/ios/.gitignore:
--------------------------------------------------------------------------------
1 | **/dgph
2 | *.mode1v3
3 | *.mode2v3
4 | *.moved-aside
5 | *.pbxuser
6 | *.perspectivev3
7 | **/*sync/
8 | .sconsign.dblite
9 | .tags*
10 | **/.vagrant/
11 | **/DerivedData/
12 | Icon?
13 | **/Pods/
14 | **/.symlinks/
15 | profile
16 | xcuserdata
17 | **/.generated/
18 | Flutter/App.framework
19 | Flutter/Flutter.framework
20 | Flutter/Flutter.podspec
21 | Flutter/Generated.xcconfig
22 | Flutter/ephemeral/
23 | Flutter/app.flx
24 | Flutter/app.zip
25 | Flutter/flutter_assets/
26 | Flutter/flutter_export_environment.sh
27 | ServiceDefinitions.json
28 | Runner/GeneratedPluginRegistrant.*
29 |
30 | # Exceptions to above rules.
31 | !default.mode1v3
32 | !default.mode2v3
33 | !default.pbxuser
34 | !default.perspectivev3
35 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | ext.kotlin_version = '1.6.10'
3 | repositories {
4 | google()
5 | mavenCentral()
6 | }
7 |
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:7.1.2'
10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | mavenCentral()
18 | }
19 | }
20 |
21 | rootProject.buildDir = '../build'
22 | subprojects {
23 | project.buildDir = "${rootProject.buildDir}/${project.name}"
24 | }
25 | subprojects {
26 | project.evaluationDependsOn(':app')
27 | }
28 |
29 | task clean(type: Delete) {
30 | delete rootProject.buildDir
31 | }
32 |
--------------------------------------------------------------------------------
/lib/modules/article/view_model/article_details_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_wan_android/modules/article/model/article_entity.dart';
3 |
4 | ///ArticleDetailsViewModel
5 | class ArticleDetailsViewModel extends ChangeNotifier {
6 | ///加载进度
7 | double _loadProgress = 0;
8 |
9 | double get loadProgress => _loadProgress;
10 |
11 | set loadProgress(double value) {
12 | _loadProgress = value;
13 | notifyListeners();
14 | }
15 |
16 | ///文章实体类
17 | ArticleEntity? _articleEntity;
18 |
19 | ArticleEntity? get articleEntity => _articleEntity;
20 |
21 | set articleEntity(ArticleEntity? value) {
22 | _articleEntity = value;
23 | notifyListeners();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/lib/modules/search/model/search_entity.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter_wan_android/generated/json/base/json_field.dart';
4 | import 'package:flutter_wan_android/generated/json/search_entity.g.dart';
5 |
6 | @JsonSerializable()
7 | class SearchEntity {
8 | int? id;
9 | @JSONField(name: "name", serialize: true, deserialize: true)
10 | String? value = "";
11 | int? time = 0;
12 |
13 | SearchEntity({this.id, this.value, this.time});
14 |
15 | factory SearchEntity.fromJson(Map json) =>
16 | $SearchEntityFromJson(json);
17 |
18 | Map toJson() => $SearchEntityToJson(this);
19 |
20 | @override
21 | String toString() {
22 | return jsonEncode(this);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/lib/modules/project/model/category_entity.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter_wan_android/generated/json/base/json_field.dart';
4 |
5 | import '../../../generated/json/category_entity.g.dart';
6 |
7 | ///类别实体
8 | @JsonSerializable()
9 | class CategoryEntity {
10 | ///一级分类ID
11 | late int id;
12 | late String name;
13 |
14 | ///二级分类列表
15 | @JSONField(name: 'children')
16 | List? childList;
17 |
18 | CategoryEntity();
19 |
20 | factory CategoryEntity.fromJson(Map json) =>
21 | $CategoryEntityFromJson(json);
22 |
23 | Map toJson() => $CategoryEntityToJson(this);
24 |
25 | @override
26 | String toString() {
27 | return jsonEncode(this);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/lib/core/net/cancel/http_canceler.dart:
--------------------------------------------------------------------------------
1 | import 'package:dio/dio.dart';
2 | import 'package:flutter_lifecycle_aware/lifecycle_owner.dart';
3 | import 'package:flutter_lifecycle_aware/lifecycle_state.dart';
4 | import 'canceler.dart';
5 |
6 | /// Http 消除器/取消管理者
7 | class HttpCanceler implements Canceler {
8 | final LifecycleOwner lifecycleOwner; //生命周期感知对象
9 | final CancelToken cancelToken; //dio 取消Token
10 | final LifecycleState lifecycleState; //widget生命周期状态
11 |
12 | HttpCanceler(this.lifecycleOwner,
13 | {CancelToken? cancelToken, LifecycleState? lifecycleState})
14 | : cancelToken = cancelToken ?? CancelToken(),
15 | lifecycleState = lifecycleState ?? LifecycleState.onDestroy;
16 |
17 | @override
18 | void cancel({reason}) {
19 | cancelToken.cancel(reason);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/lib/modules/knowledge/model/nav_entity.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter_wan_android/generated/json/base/json_field.dart';
4 | import 'package:flutter_wan_android/generated/json/nav_entity.g.dart';
5 | import 'package:flutter_wan_android/modules/article/model/article_entity.dart';
6 |
7 | ///导航实体类
8 | @JsonSerializable()
9 | class NavEntity {
10 | ///导航列表(文章列表)
11 | late List articles;
12 |
13 | ///导航ID
14 | late int cid;
15 |
16 | ///导航名称
17 | late String name;
18 |
19 | NavEntity();
20 |
21 | factory NavEntity.fromJson(Map json) =>
22 | $NavEntityFromJson(json);
23 |
24 | Map toJson() => $NavEntityToJson(this);
25 |
26 | @override
27 | String toString() {
28 | return jsonEncode(this);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/lib/modules/main/view_model/locale_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | import '../../../common/global_value.dart';
4 |
5 | ///本地化ViewModel
6 | class LocaleViewModel extends ChangeNotifier {
7 | LocaleViewModel() {
8 | ///获取localIndex
9 | GlobalValue.getLocalIndex().then((value) {
10 | localIndex = value ?? 0;
11 | });
12 | }
13 |
14 | ///本地化列表
15 | final List localList = ['zh', 'en'];
16 |
17 | ///本地化下标
18 | int _localIndex = 0;
19 |
20 | int get localIndex => _localIndex;
21 |
22 | set localIndex(int value) {
23 | _localIndex = value;
24 | notifyListeners();
25 | }
26 |
27 | ///local
28 | Locale get locale => Locale(localList[localIndex]);
29 |
30 | ///存储local
31 | void setLocalIndex(int index) {
32 | GlobalValue.setLocalIndex(index);
33 | localIndex = index;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lib/utils/format_util.dart:
--------------------------------------------------------------------------------
1 | import 'package:intl/intl.dart';
2 |
3 | ///格式化工具类
4 | class FormatUtil {
5 | ///日期格式
6 | static const String ymdHms = "yyyy-MM-dd HH:mm:ss";
7 |
8 | /// 格式化数值
9 | /// var f = NumberFormat("###.0#", "en_US");
10 | /// print(f.format(12.345));
11 | /// ==> 12.34
12 | static String formatNumber(String pattern, dynamic number, {String? locale}) {
13 | return NumberFormat(pattern, locale).format(number);
14 | }
15 |
16 | /// 格式化日期
17 | /// "yyyy-MM-dd HH:mm:ss"
18 | static String formatDate(String pattern, DateTime date) {
19 | return DateFormat(pattern).format(date);
20 | }
21 |
22 | /// 格式化毫秒日期
23 | /// "yyyy-MM-dd HH:mm:ss"
24 | static String formatMilliseconds(String pattern, int milliseconds) {
25 | return formatDate(
26 | pattern, DateTime.fromMillisecondsSinceEpoch(milliseconds));
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ios/Flutter/AppFrameworkInfo.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | App
9 | CFBundleIdentifier
10 | io.flutter.flutter.app
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | App
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1.0
23 | MinimumOSVersion
24 | 9.0
25 |
26 |
27 |
--------------------------------------------------------------------------------
/lib/modules/account/view_model/register_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/cupertino.dart';
2 |
3 | import '../model/account_model.dart';
4 |
5 | class RegisterViewModel extends ChangeNotifier {
6 | late AccountModel model;
7 |
8 | RegisterViewModel() {
9 | model = AccountModel();
10 | }
11 |
12 | ///允许注册
13 | bool _canRegister = false;
14 |
15 | bool get canRegister => _canRegister;
16 |
17 | set canRegister(bool value) {
18 | _canRegister = value;
19 | notifyListeners();
20 | }
21 |
22 | ///密码模式
23 | bool _secretPsw = true;
24 |
25 | bool get secretPsw => _secretPsw;
26 |
27 | set secretPsw(bool value) {
28 | _secretPsw = value;
29 | notifyListeners();
30 | }
31 |
32 | ///确认密码模式
33 | bool _secretPswConfirm = true;
34 |
35 | bool get secretPswConfirm => _secretPswConfirm;
36 |
37 | set secretPswConfirm(bool value) {
38 | _secretPswConfirm = value;
39 | notifyListeners();
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/generated/json/search_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_wan_android/generated/json/base/json_convert_content.dart';
2 | import 'package:flutter_wan_android/modules/search/model/search_entity.dart';
3 |
4 | SearchEntity $SearchEntityFromJson(Map json) {
5 | final SearchEntity searchEntity = SearchEntity();
6 | final int? id = jsonConvert.convert(json['id']);
7 | if (id != null) {
8 | searchEntity.id = id;
9 | }
10 | final String? value = jsonConvert.convert(json['name']);
11 | if (value != null) {
12 | searchEntity.value = value;
13 | }
14 | final int? time = jsonConvert.convert(json['time']);
15 | if (time != null) {
16 | searchEntity.time = time;
17 | }
18 | return searchEntity;
19 | }
20 |
21 | Map $SearchEntityToJson(SearchEntity entity) {
22 | final Map data = {};
23 | data['id'] = entity.id;
24 | data['name'] = entity.value;
25 | data['time'] = entity.time;
26 | return data;
27 | }
--------------------------------------------------------------------------------
/lib/core/net/observer/http_lifecycle_observer.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_lifecycle_aware/lifecycle_observer.dart';
2 | import 'package:flutter_lifecycle_aware/lifecycle_owner.dart';
3 | import 'package:flutter_lifecycle_aware/lifecycle_state.dart';
4 |
5 | import '../cancel/http_cancel_manager.dart';
6 | import '../cancel/http_canceler.dart';
7 |
8 | class HttpLifecycleObserver implements LifecycleObserver {
9 | /// http取消管理类
10 | final HttpCancelManager httpCancelManager;
11 |
12 | /// http 取消器
13 | /// 可以从 HttpCancelManager 中获取,此处认为 onStateChanged 回调频繁,通过成员变量的方式更优
14 | final HttpCanceler httpCanceler;
15 |
16 | HttpLifecycleObserver(this.httpCancelManager, this.httpCanceler);
17 |
18 | @override
19 | void onLifecycleChanged(LifecycleOwner owner, LifecycleState state) {
20 | /// 目标组件,目标生命周期状态:取消网络请求
21 | if (httpCanceler.lifecycleOwner == owner &&
22 | httpCanceler.lifecycleState == state) {
23 | httpCancelManager.cancel(owner);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/lib/modules/account/model/user_entity.dart:
--------------------------------------------------------------------------------
1 | import 'dart:convert';
2 |
3 | import 'package:flutter_wan_android/generated/json/base/json_field.dart';
4 | import 'package:flutter_wan_android/generated/json/user_entity.g.dart';
5 | import 'package:flutter_wan_android/helper/image_helper.dart';
6 |
7 | @JsonSerializable()
8 | class UserEntity {
9 | @JSONField(name: "id")
10 | int? uid = 0;
11 | String? nickname = "";
12 |
13 | ///积分
14 | int? coinCount = 0;
15 | String? icon = "";
16 |
17 | UserEntity();
18 |
19 | factory UserEntity.fromJson(Map json) {
20 | ///手动添加头像
21 | if (!json.containsKey("icon")) {
22 | json["icon"] = ImageHelper.randomUrl();
23 | }
24 | String value = json["icon"];
25 | if (value.isEmpty) {
26 | json["icon"] = ImageHelper.randomUrl();
27 | }
28 | return $UserEntityFromJson(json);
29 | }
30 |
31 | Map toJson() => $UserEntityToJson(this);
32 |
33 | @override
34 | String toString() {
35 | return jsonEncode(this);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/lib/modules/book/model/book_entity.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_wan_android/generated/json/base/json_field.dart';
2 | import 'package:flutter_wan_android/generated/json/book_entity.g.dart';
3 | import 'dart:convert';
4 |
5 | ///教程实体类
6 | @JsonSerializable()
7 | class BookEntity {
8 | /*
9 | {
10 | "author": "阮一峰",
11 | "cover": "https://www.wanandroid.com/blogimgs/f1cb8d34-82c1-46f7-80fe-b899f56b69c1.png",
12 | "desc": "C 语言入门教程。",
13 | "id": 548,
14 | "lisense": "知识共享 署名-相同方式共享 3.0协议",
15 | "lisenseLink": "https://creativecommons.org/licenses/by-sa/3.0/deed.zh",
16 | "name": "C 语言入门教程_阮一峰"
17 | }*/
18 |
19 | late String author;
20 | late String cover;
21 | late String desc;
22 | late int id;
23 | late String lisense;
24 | late String lisenseLink;
25 | late String name;
26 |
27 | BookEntity();
28 |
29 | factory BookEntity.fromJson(Map json) => $BookEntityFromJson(json);
30 |
31 | Map toJson() => $BookEntityToJson(this);
32 |
33 | @override
34 | String toString() {
35 | return jsonEncode(this);
36 | }
37 | }
--------------------------------------------------------------------------------
/lib/modules/main/view/preview_page.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_wan_android/config/hero_config.dart';
3 | import 'package:flutter_wan_android/helper/image_helper.dart';
4 |
5 | import '../../../helper/router_helper.dart';
6 |
7 | ///预览界面
8 | class PreviewPage extends StatefulWidget {
9 | final String imageUrl;
10 |
11 | const PreviewPage(this.imageUrl, {Key? key}) : super(key: key);
12 |
13 | @override
14 | State createState() => _PreviewPageState();
15 | }
16 |
17 | class _PreviewPageState extends State {
18 | @override
19 | Widget build(BuildContext context) {
20 | return Hero(
21 | tag: HeroConfig.tagPreview,
22 | child: GestureDetector(
23 | onTap: () => RouterHelper.pop(context),
24 | child: Container(
25 | alignment: Alignment.center,
26 | color: Colors.black,
27 | child: ImageHelper.network(widget.imageUrl,
28 | width: double.infinity, fit: BoxFit.fitWidth),
29 | ),
30 | ),
31 | );
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/android/app/src/main/res/values-night/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
15 |
18 |
19 |
--------------------------------------------------------------------------------
/lib/generated/json/category_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_wan_android/generated/json/base/json_convert_content.dart';
2 | import 'package:flutter_wan_android/modules/project/model/category_entity.dart';
3 |
4 | CategoryEntity $CategoryEntityFromJson(Map json) {
5 | final CategoryEntity categoryEntity = CategoryEntity();
6 | final int? id = jsonConvert.convert(json['id']);
7 | if (id != null) {
8 | categoryEntity.id = id;
9 | }
10 | final String? name = jsonConvert.convert(json['name']);
11 | if (name != null) {
12 | categoryEntity.name = name;
13 | }
14 | final List? childList = jsonConvert.convertListNotNull(json['children']);
15 | if (childList != null) {
16 | categoryEntity.childList = childList;
17 | }
18 | return categoryEntity;
19 | }
20 |
21 | Map $CategoryEntityToJson(CategoryEntity entity) {
22 | final Map data = {};
23 | data['id'] = entity.id;
24 | data['name'] = entity.name;
25 | data['children'] = entity.childList?.map((v) => v.toJson()).toList();
26 | return data;
27 | }
--------------------------------------------------------------------------------
/lib/generated/json/nav_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_wan_android/generated/json/base/json_convert_content.dart';
2 | import 'package:flutter_wan_android/modules/knowledge/model/nav_entity.dart';
3 | import 'package:flutter_wan_android/modules/article/model/article_entity.dart';
4 |
5 |
6 | NavEntity $NavEntityFromJson(Map json) {
7 | final NavEntity navEntity = NavEntity();
8 | final List? articles = jsonConvert.convertListNotNull(json['articles']);
9 | if (articles != null) {
10 | navEntity.articles = articles;
11 | }
12 | final int? cid = jsonConvert.convert(json['cid']);
13 | if (cid != null) {
14 | navEntity.cid = cid;
15 | }
16 | final String? name = jsonConvert.convert(json['name']);
17 | if (name != null) {
18 | navEntity.name = name;
19 | }
20 | return navEntity;
21 | }
22 |
23 | Map $NavEntityToJson(NavEntity entity) {
24 | final Map data = {};
25 | data['articles'] = entity.articles.map((v) => v.toJson()).toList();
26 | data['cid'] = entity.cid;
27 | data['name'] = entity.name;
28 | return data;
29 | }
--------------------------------------------------------------------------------
/lib/widget/loading_dialog_widget.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 |
3 | ///Loading弹窗
4 | ///网络请求等场景使用
5 | class LoadingDialogWidget extends StatelessWidget {
6 | bool dismissible = false;
7 |
8 | LoadingDialogWidget({Key? key, required this.dismissible}) : super(key: key);
9 |
10 | @override
11 | Widget build(BuildContext context) {
12 | return Stack(
13 | alignment: Alignment.center,
14 | children: [
15 | ///拦截返回导航
16 | WillPopScope(
17 | child: Container(
18 | decoration: BoxDecoration(
19 | borderRadius: BorderRadius.circular(4),
20 | color: Colors.grey[200]),
21 | padding: const EdgeInsets.all(20),
22 | height: 80,
23 | width: 80,
24 | child: CircularProgressIndicator(
25 | color: Theme.of(context).primaryColor,
26 | backgroundColor: Colors.grey[300],
27 | ),
28 | ),
29 |
30 | ///拦截返回按钮:false = 不允许通过返回按钮关闭弹窗
31 | onWillPop: () => Future.value(dismissible))
32 | ],
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/lib/generated/json/banner_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_wan_android/generated/json/base/json_convert_content.dart';
2 | import 'package:flutter_wan_android/modules/home/model/banner_entity.dart';
3 |
4 | BannerEntity $BannerEntityFromJson(Map json) {
5 | final BannerEntity bannerEntity = BannerEntity();
6 | final int? id = jsonConvert.convert(json['id']);
7 | if (id != null) {
8 | bannerEntity.id = id;
9 | }
10 | final String? imagePath = jsonConvert.convert(json['imagePath']);
11 | if (imagePath != null) {
12 | bannerEntity.imagePath = imagePath;
13 | }
14 | final String? title = jsonConvert.convert(json['title']);
15 | if (title != null) {
16 | bannerEntity.title = title;
17 | }
18 | final String? url = jsonConvert.convert(json['url']);
19 | if (url != null) {
20 | bannerEntity.url = url;
21 | }
22 | return bannerEntity;
23 | }
24 |
25 | Map $BannerEntityToJson(BannerEntity entity) {
26 | final Map data = {};
27 | data['id'] = entity.id;
28 | data['imagePath'] = entity.imagePath;
29 | data['title'] = entity.title;
30 | data['url'] = entity.url;
31 | return data;
32 | }
--------------------------------------------------------------------------------
/test/widget_test.dart:
--------------------------------------------------------------------------------
1 | // This is a basic Flutter widget test.
2 | //
3 | // To perform an interaction with a widget in your test, use the WidgetTester
4 | // utility in the flutter_test package. For example, you can send tap and scroll
5 | // gestures. You can also use WidgetTester to find child widgets in the widget
6 | // tree, read text, and verify that the values of widget properties are correct.
7 |
8 | import 'package:flutter/material.dart';
9 | import 'package:flutter_test/flutter_test.dart';
10 |
11 | import 'package:flutter_wan_android/main.dart';
12 |
13 | void main() {
14 | testWidgets('Counter increments smoke test', (WidgetTester tester) async {
15 | // Build our app and trigger a frame.
16 | await tester.pumpWidget(const MyApp());
17 |
18 | // Verify that our counter starts at 0.
19 | expect(find.text('0'), findsOneWidget);
20 | expect(find.text('1'), findsNothing);
21 |
22 | // Tap the '+' icon and trigger a frame.
23 | await tester.tap(find.byIcon(Icons.add));
24 | await tester.pump();
25 |
26 | // Verify that our counter has incremented.
27 | expect(find.text('0'), findsNothing);
28 | expect(find.text('1'), findsOneWidget);
29 | });
30 | }
31 |
--------------------------------------------------------------------------------
/.metadata:
--------------------------------------------------------------------------------
1 | # This file tracks properties of this Flutter project.
2 | # Used by Flutter tool to assess capabilities and perform upgrades etc.
3 | #
4 | # This file should be version controlled.
5 |
6 | version:
7 | revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
8 | channel: stable
9 |
10 | project_type: app
11 |
12 | # Tracks metadata for the flutter migrate command
13 | migration:
14 | platforms:
15 | - platform: root
16 | create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
17 | base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
18 | - platform: android
19 | create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
20 | base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
21 | - platform: ios
22 | create_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
23 | base_revision: ee4e09cce01d6f2d7f4baebd247fde02e5008851
24 |
25 | # User provided section
26 |
27 | # List of Local paths (relative to this file) that should be
28 | # ignored by the migrate tool.
29 | #
30 | # Files that are not part of the templates will be ignored by default.
31 | unmanaged_files:
32 | - 'lib/main.dart'
33 | - 'ios/Runner.xcodeproj/project.pbxproj'
34 |
--------------------------------------------------------------------------------
/lib/generated/json/user_entity.g.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter_wan_android/generated/json/base/json_convert_content.dart';
2 | import 'package:flutter_wan_android/modules/account/model/user_entity.dart';
3 | import 'package:flutter_wan_android/helper/image_helper.dart';
4 |
5 |
6 | UserEntity $UserEntityFromJson(Map json) {
7 | final UserEntity userEntity = UserEntity();
8 | final int? uid = jsonConvert.convert(json['id']);
9 | if (uid != null) {
10 | userEntity.uid = uid;
11 | }
12 | final String? nickname = jsonConvert.convert(json['nickname']);
13 | if (nickname != null) {
14 | userEntity.nickname = nickname;
15 | }
16 | final int? coinCount = jsonConvert.convert(json['coinCount']);
17 | if (coinCount != null) {
18 | userEntity.coinCount = coinCount;
19 | }
20 | final String? icon = jsonConvert.convert(json['icon']);
21 | if (icon != null) {
22 | userEntity.icon = icon;
23 | }
24 | return userEntity;
25 | }
26 |
27 | Map $UserEntityToJson(UserEntity entity) {
28 | final Map data = {};
29 | data['id'] = entity.uid;
30 | data['nickname'] = entity.nickname;
31 | data['coinCount'] = entity.coinCount;
32 | data['icon'] = entity.icon;
33 | return data;
34 | }
--------------------------------------------------------------------------------
/lib/modules/collect/view_model/collection_list_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_wan_android/modules/article/model/article_entity.dart';
3 |
4 | import '../../../core/net/cancel/http_canceler.dart';
5 | import '../../../core/net/http_result.dart';
6 | import '../model/collect_model.dart';
7 |
8 | class CollectionListViewModel extends ChangeNotifier {
9 | CollectModel model = CollectModel();
10 |
11 | ///数据页面下标
12 | int pageIndex = 0;
13 |
14 | ///文章列表
15 | List _articleList = [];
16 |
17 | List get articleList => _articleList;
18 |
19 | set articleList(List value) {
20 | _articleList = value;
21 | notifyListeners();
22 | }
23 |
24 | ///获取内容列表
25 | Future> getArticleList(
26 | bool refresh, HttpCanceler canceler) async {
27 | ///下拉刷新,下标从0开始
28 | if (refresh) pageIndex = 0;
29 | HttpResult result =
30 | await model.getCollectList(pageIndex, canceler);
31 | if (result.success) {
32 | if (refresh) articleList.clear();
33 | articleList.addAll(result.list!);
34 | articleList = articleList;
35 | pageIndex++;
36 | }
37 | return result;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/modules/knowledge/view_model/knowledge_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_lifecycle_aware/lifecycle_owner.dart';
3 | import 'package:flutter_wan_android/core/net/cancel/http_canceler.dart';
4 | import 'package:flutter_wan_android/modules/knowledge/model/knowledge_entity.dart';
5 | import 'package:flutter_wan_android/modules/knowledge/model/knowledge_model.dart';
6 |
7 | class KnowledgeViewModel extends ChangeNotifier {
8 | KnowledgeModel model = KnowledgeModel();
9 |
10 | ///知识实体类
11 | KnowledgeEntity _entity = KnowledgeEntity();
12 |
13 | KnowledgeEntity get entity => _entity;
14 |
15 | set entity(KnowledgeEntity value) {
16 | _entity = value;
17 | notifyListeners();
18 | }
19 |
20 | ///获取分类列表
21 | void getCategoryList(HttpCanceler canceler) {
22 | model.getSystemList(canceler).then((value) {
23 | if (value.success) {
24 | entity.categoryList = value.list!;
25 | entity = entity;
26 | }
27 | });
28 | }
29 |
30 | ///获取导航列表
31 | void getNavList(HttpCanceler canceler) {
32 | model.getNavList(canceler).then((value) {
33 | if (value.success) {
34 | entity.navList = value.list!;
35 | entity = entity;
36 | }
37 | });
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/lib/modules/book/view_model/book_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_lifecycle_aware/lifecycle_observer.dart';
3 | import 'package:flutter_lifecycle_aware/lifecycle_owner.dart';
4 | import 'package:flutter_lifecycle_aware/lifecycle_state.dart';
5 |
6 | import '../../../core/net/cancel/http_canceler.dart';
7 | import '../../book/model/book_entity.dart';
8 | import '../../book/model/book_model.dart';
9 |
10 | class BookViewModel extends ChangeNotifier with LifecycleObserver {
11 | late HttpCanceler httpCanceler;
12 | BookModel model = BookModel();
13 |
14 | ///教程列表
15 | List _dataArray = [];
16 |
17 | List get dataArray => _dataArray;
18 |
19 | set dataArray(List value) {
20 | _dataArray = value;
21 | notifyListeners();
22 | }
23 |
24 | ///获取教程列表
25 | void getBookList() {
26 | model.getBookList(httpCanceler).then((value) {
27 | if (value.success) {
28 | dataArray = value.list!;
29 | }
30 | });
31 | }
32 |
33 | @override
34 | void onLifecycleChanged(LifecycleOwner owner, LifecycleState state) {
35 | if (state == LifecycleState.onInit) {
36 | httpCanceler = HttpCanceler(owner);
37 | } else if (state == LifecycleState.onCreate) {
38 | getBookList();
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/lib/modules/project/view_model/project_item_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_wan_android/core/net/cancel/zt_http_cancel.dart';
3 | import 'package:flutter_wan_android/core/net/http_result.dart';
4 | import 'package:flutter_wan_android/modules/article/model/article_entity.dart';
5 | import 'package:flutter_wan_android/modules/project/model/project_model.dart';
6 |
7 | class ProjectItemViewModel extends ChangeNotifier {
8 | ProjectModel model = ProjectModel();
9 |
10 | ///数据页面下标
11 | int pageIndex = 0;
12 |
13 | ///文章列表
14 | List _articleList = [];
15 |
16 | List get articleList => _articleList;
17 |
18 | set articleList(List value) {
19 | _articleList = value;
20 | notifyListeners();
21 | }
22 |
23 | ///获取内容列表
24 | Future> getArticleList(
25 | int projectId, bool refresh, HttpCanceler canceler) async {
26 | ///下拉刷新,下标从0开始
27 | if (refresh) pageIndex = 0;
28 | HttpResult result =
29 | await model.getProjectList(projectId, pageIndex, canceler);
30 | if (result.success) {
31 | if (refresh) articleList.clear();
32 | articleList.addAll(result.list!);
33 | articleList = articleList;
34 | pageIndex++;
35 | }
36 | return result;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/lib/core/net/http_result.dart:
--------------------------------------------------------------------------------
1 | import '../../generated/json/base/json_convert_content.dart';
2 |
3 | ///网络请求结果
4 | ///泛型是最终实体类型,如果想要 List 只需要指定 T 然后获取 list 对应的值即可
5 | class HttpResult {
6 | late int code;
7 | String? msg;
8 |
9 | ///解析成为实体类使用:与 list 互斥
10 | T? data;
11 |
12 | ///解析成为列表使用:与 data 互斥
13 | List? list;
14 |
15 | HttpResult();
16 |
17 | ///业务逻辑是否成功
18 | bool get success => code == 0;
19 |
20 | HttpResult convert(Map json) {
21 | HttpResult entity = HttpResult();
22 |
23 | /// 业务逻辑的 data
24 | dynamic data = json['data'];
25 |
26 | /// 业务逻辑的 code
27 | int code = json['errorCode'];
28 |
29 | /// 业务逻辑的 msg
30 | String? msg = json['errorMsg'];
31 |
32 | /// 解析成为 List
33 | if (data is List) {
34 | entity.list = convertList(data);
35 | } else {
36 | entity.data = convertData(data);
37 | }
38 |
39 | entity.code = code;
40 | entity.msg = msg;
41 | return entity;
42 | }
43 |
44 | ///转为List
45 | static List convertList(dynamic data) {
46 | List list = [];
47 | for (var item in data) {
48 | list.add(jsonConvert.convert(item) as M);
49 | }
50 | return list;
51 | }
52 |
53 | ///转为具体数据
54 | static M? convertData(dynamic data) {
55 | return jsonConvert.convert(data);
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/lib/l10n/intl_zh.arb:
--------------------------------------------------------------------------------
1 | {
2 | "tab_home": "首页",
3 | "tab_project": "项目",
4 | "tab_knowledge": "知识",
5 | "tab_book": "教程",
6 | "tab_me": "我的",
7 | "integral": "积分:{value}",
8 | "collect": "收藏",
9 | "dark_style": "暗黑模式",
10 | "color_theme": "彩色主题",
11 | "settings": "设置",
12 | "placeholder": "--",
13 | "login": "登录",
14 | "register": "注册",
15 | "register_now": "立即注册",
16 | "no_account": "还没账号?",
17 | "user_name": "用户名",
18 | "user_psw": "密码",
19 | "user_psw_confirm": "确认密码",
20 | "topping": "置顶",
21 | "label_group": "{main} - {sub}",
22 | "search_hint": "用空格分隔多个关键词",
23 | "search_hot_title": "热门搜索",
24 | "search_local_title": "历史搜索",
25 | "edit": "编辑",
26 | "clean_all": "清除全部",
27 | "done": "完成",
28 | "loading_content": "内容加载中...",
29 | "learn_progress": "已学{progress}%",
30 | "learn_no": "未学习",
31 | "multi_language": "多语言",
32 | "language_chinese": "中文",
33 | "language_english": "英文",
34 | "account_empty_tip": "请输入账号",
35 | "psw_empty_tip": "请输入密码",
36 | "psw_confirm_empty_tip": "请确认密码",
37 | "psw_confirm_tip": "两次密码不一致",
38 | "login_success": "登录成功",
39 | "register_success": "注册成功",
40 | "net_error": "网络错误",
41 | "tab_tree": "体系",
42 | "tab_nav": "导航",
43 | "tab_book_course": "书籍教程",
44 | "tips_msg": "提示",
45 | "cancel": "取消",
46 | "confirm": "确定",
47 | "collect_content": "您确定要移除收藏内容吗?"
48 | }
--------------------------------------------------------------------------------
/lib/modules/knowledge/view_model/knowledge_child_view_model.dart:
--------------------------------------------------------------------------------
1 | import 'package:flutter/material.dart';
2 | import 'package:flutter_wan_android/core/net/cancel/http_canceler.dart';
3 | import 'package:flutter_wan_android/core/net/http_result.dart';
4 | import 'package:flutter_wan_android/modules/article/model/article_entity.dart';
5 | import 'package:flutter_wan_android/modules/knowledge/model/knowledge_model.dart';
6 |
7 | class KnowledgeChildViewModel extends ChangeNotifier {
8 | KnowledgeModel model = KnowledgeModel();
9 |
10 | ///数据页面下标
11 | int pageIndex = 0;
12 |
13 | ///文章列表
14 | List _articleList = [];
15 |
16 | List get articleList => _articleList;
17 |
18 | set articleList(List value) {
19 | _articleList = value;
20 | notifyListeners();
21 | }
22 |
23 | ///获取内容列表
24 | Future> getArticleList(
25 | int projectId, bool refresh, HttpCanceler canceler) async {
26 | ///下拉刷新,下标从0开始
27 | if (refresh) pageIndex = 0;
28 | HttpResult result =
29 | await model.getCategoryArticleList(projectId, pageIndex, canceler);
30 | if (result.success) {
31 | if (refresh) articleList.clear();
32 | articleList.addAll(result.list!);
33 | articleList = articleList;
34 | pageIndex++;
35 | }
36 | return result;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/lib/core/net/cancel/http_cancel_manager.dart:
--------------------------------------------------------------------------------
1 | import 'cancel_manager.dart';
2 | import 'canceler.dart';
3 | import 'http_canceler.dart';
4 |
5 | /// Http 取消管理类
6 | class HttpCancelManager implements CancelManager {
7 | /// http 取消器集合
8 | Map