├── .gitignore ├── .metadata ├── .vscode └── launch.json ├── README.md ├── Untitled-1.json ├── android ├── app │ ├── build.gradle │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── kotlin │ │ │ └── com │ │ │ │ └── nsapp │ │ │ │ └── dmzj │ │ │ │ └── MainActivity.kt │ │ └── res │ │ │ ├── drawable │ │ │ └── launch_background.xml │ │ │ ├── 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 │ │ │ ├── values │ │ │ └── styles.xml │ │ │ └── xml │ │ │ └── network_security_config.xml │ │ └── profile │ │ └── AndroidManifest.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ └── gradle-wrapper.properties ├── settings.gradle └── settings_aar.gradle ├── api.md ├── assets ├── ic_launcher.png ├── img_ucenter_def_bac.jpg ├── qq.png ├── weibo.png └── weixin.png ├── ios ├── Flutter │ ├── AppFrameworkInfo.plist │ ├── Debug.xcconfig │ ├── Release.xcconfig │ └── flutter_export_environment.sh ├── Podfile ├── Podfile.lock ├── Runner.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Runner.xcscheme ├── Runner.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── WorkspaceSettings.xcsettings └── Runner │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-App-1024x1024@1x.png │ │ ├── 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-83.5x83.5@2x.png │ │ ├── icon-1024.png │ │ ├── icon-20-ipad.png │ │ ├── icon-20@2x-ipad.png │ │ ├── icon-20@2x.png │ │ ├── icon-20@3x.png │ │ ├── icon-29-ipad.png │ │ ├── icon-29.png │ │ ├── icon-29@2x-ipad.png │ │ ├── icon-29@2x.png │ │ ├── icon-29@3x.png │ │ ├── icon-40.png │ │ ├── icon-40@2x.png │ │ ├── icon-40@3x.png │ │ ├── icon-60@2x.png │ │ ├── icon-60@3x.png │ │ ├── icon-76.png │ │ ├── icon-76@2x.png │ │ └── icon-83.5@2x.png │ └── LaunchImage.imageset │ │ ├── Contents.json │ │ ├── LaunchImage.png │ │ ├── LaunchImage@2x.png │ │ ├── LaunchImage@3x.png │ │ └── README.md │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ └── Runner-Bridging-Header.h ├── lib ├── app │ ├── api.dart │ ├── api │ │ ├── api_util.dart │ │ ├── comic.dart │ │ ├── news.dart │ │ └── novel.dart │ ├── app_setting.dart │ ├── app_theme.dart │ ├── comic_download_helper.dart │ ├── commnet_helper.dart │ ├── config_helper.dart │ ├── http_util.dart │ ├── user_helper.dart │ ├── user_info.dart │ └── utils.dart ├── main.dart ├── models │ ├── comic │ │ ├── comic_author_model.dart │ │ ├── comic_category_detail_filter.dart │ │ ├── comic_category_detail_item.dart │ │ ├── comic_category_item.dart │ │ ├── comic_chapter_detail.dart │ │ ├── comic_chapter_view_point.dart │ │ ├── comic_detail_model.dart │ │ ├── comic_detail_v2_model.dart │ │ ├── comic_history_item.dart │ │ ├── comic_home_banner_item.dart │ │ ├── comic_home_comic_item.dart │ │ ├── comic_home_item.dart │ │ ├── comic_home_new_item.dart │ │ ├── comic_ns_search_item.dart │ │ ├── comic_rank_item.dart │ │ ├── comic_related_model.dart │ │ ├── comic_specia_datail_model.dart │ │ ├── comic_special_item.dart │ │ └── comic_web_chapter_detail.dart │ ├── comment_model.dart │ ├── news │ │ ├── new_list_item_model.dart │ │ ├── news_banner_model.dart │ │ ├── news_stat_detail.dart │ │ └── news_tag_model.dart │ ├── novel │ │ ├── novel_category_detail_item.dart │ │ ├── novel_detail_model.dart │ │ ├── novel_history_item.dart │ │ ├── novel_rank_item.dart │ │ ├── novel_search_result_item.dart │ │ ├── novel_update_item.dart │ │ └── novel_volume_item.dart │ ├── search_hot_word.dart │ ├── user │ │ ├── user_model.dart │ │ ├── user_profile.dart │ │ └── user_subscribe_item.dart │ ├── user_comment_model.dart │ └── version_info.dart ├── protobuf │ ├── comic │ │ ├── detail_response.pb.dart │ │ ├── detail_response.proto │ │ ├── rank_list_response.pb.dart │ │ ├── rank_list_response.proto │ │ ├── update_list_response.pb.dart │ │ └── update_list_response.proto │ ├── news │ │ ├── news_list_response.pb.dart │ │ └── news_list_response.proto │ └── novel │ │ ├── novel_chapter_response.pb.dart │ │ ├── novel_chapter_response.proto │ │ ├── novel_detail_response.pb.dart │ │ └── novel_detail_response.proto ├── sql │ ├── comic_down.dart │ ├── comic_history.dart │ ├── novel_history.dart │ └── test.dart ├── views │ ├── comic │ │ ├── comic_author.dart │ │ ├── comic_category.dart │ │ ├── comic_category_detail.dart │ │ ├── comic_detail.dart │ │ ├── comic_detail_v2.dart │ │ ├── comic_home.dart │ │ ├── comic_rank.dart │ │ ├── comic_recommend.dart │ │ ├── comic_search.dart │ │ ├── comic_special.dart │ │ ├── comic_special_detail.dart │ │ └── comic_update.dart │ ├── download │ │ └── comic_download.dart │ ├── news │ │ ├── news_detail.dart │ │ └── news_home.dart │ ├── novel │ │ ├── novel_category.dart │ │ ├── novel_category_detail.dart │ │ ├── novel_detail.dart │ │ ├── novel_home.dart │ │ ├── novel_rank.dart │ │ ├── novel_recommend.dart │ │ ├── novel_search.dart │ │ └── novel_update.dart │ ├── other │ │ ├── comment_detail_page.dart │ │ ├── comment_widget.dart │ │ └── web_page.dart │ ├── reader │ │ ├── comic_reader.dart │ │ ├── comic_tc.dart │ │ └── novel_reader.dart │ ├── setting_page.dart │ ├── settings │ │ ├── comic_reader_settings.dart │ │ └── novel_reader_settings.dart │ └── user │ │ ├── login_page.dart │ │ ├── my_comment_page.dart │ │ ├── personal_page.dart │ │ ├── user_bind_phone.dart │ │ ├── user_detail.dart │ │ ├── user_history.dart │ │ ├── user_page.dart │ │ └── user_subscribe.dart └── widgets │ ├── app_banner.dart │ ├── comic_view.dart │ ├── icon_text_button.dart │ ├── image_view.dart │ ├── user_comment_widget.dart │ └── user_subscribe_widget.dart ├── new_version.json ├── pubspec.yaml └── test └── widget_test.dart /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | *.jks 7 | *.p12 8 | .DS_Store 9 | .atom/ 10 | .buildlog/ 11 | .history 12 | .svn/ 13 | 14 | # IntelliJ related 15 | *.iml 16 | *.ipr 17 | *.iws 18 | .idea/ 19 | 20 | # The .vscode folder contains launch configuration and tasks you configure in 21 | # VS Code which you may wish to be included in version control, so this line 22 | # is commented out by default. 23 | #.vscode/ 24 | 25 | # Flutter/Dart/Pub related 26 | **/doc/api/ 27 | .dart_tool/ 28 | .flutter-plugins 29 | .packages 30 | .pub-cache/ 31 | .pub/ 32 | /build/ 33 | 34 | # Android related 35 | **/android/**/gradle-wrapper.jar 36 | **/android/.gradle 37 | **/android/captures/ 38 | **/android/gradlew 39 | **/android/gradlew.bat 40 | **/android/local.properties 41 | **/android/**/GeneratedPluginRegistrant.java 42 | 43 | # iOS/XCode related 44 | **/ios/**/*.mode1v3 45 | **/ios/**/*.mode2v3 46 | **/ios/**/*.moved-aside 47 | **/ios/**/*.pbxuser 48 | **/ios/**/*.perspectivev3 49 | **/ios/**/*sync/ 50 | **/ios/**/.sconsign.dblite 51 | **/ios/**/.tags* 52 | **/ios/**/.vagrant/ 53 | **/ios/**/DerivedData/ 54 | **/ios/**/Icon? 55 | **/ios/**/Pods/ 56 | **/ios/**/.symlinks/ 57 | **/ios/**/profile 58 | **/ios/**/xcuserdata 59 | **/ios/.generated/ 60 | **/ios/Flutter/App.framework 61 | **/ios/Flutter/Flutter.framework 62 | **/ios/Flutter/Generated.xcconfig 63 | **/ios/Flutter/app.flx 64 | **/ios/Flutter/app.zip 65 | **/ios/Flutter/flutter_assets/ 66 | **/ios/ServiceDefinitions.json 67 | **/ios/Runner/GeneratedPluginRegistrant.* 68 | 69 | # Exceptions to above rules. 70 | !**/ios/**/default.mode1v3 71 | !**/ios/**/default.mode2v3 72 | !**/ios/**/default.pbxuser 73 | !**/ios/**/default.perspectivev3 74 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 75 | # key.jks 76 | android/key.properties 77 | pubspec.lock 78 | .flutter-plugins-dependencies 79 | **/linux 80 | **/windows 81 | 82 | -------------------------------------------------------------------------------- /.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 and should not be manually edited. 5 | 6 | version: 7 | revision: 20e59316b8b8474554b38493b8ca888794b0234a 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Flutter", 9 | "request": "launch", 10 | "type": "dart" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 动漫之家 Flutter 2 | 3 | 使用Flutter编写的动漫之家第三方客户端 4 | 5 | ## 截图 6 | 7 | ![未标题-1.png](https://vip1.loli.net/2020/08/02/UrBtvZGVcEThqIY.png) 8 | 9 | -------------------------------------------------------------------------------- /Untitled-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "old_api":false, 3 | "comic_id":1, 4 | "title":"", 5 | "authors":[ { 6 | "author_name":"", 7 | "author_id":0 8 | }], 9 | "cover":"", 10 | "tags":[ 11 | { 12 | "tag_name":"", 13 | "tag_id":0 14 | } 15 | ], 16 | "click_num":0, 17 | "collection_num":0, 18 | "status":"连载中", 19 | "last_update":"", 20 | "description":"", 21 | "volume":[ 22 | { 23 | "volume_id":0, 24 | "volume_title":"", 25 | "reverse":false, 26 | "chapters":[ 27 | { 28 | "chpater_id":0, 29 | "chapter_title":"", 30 | "chapter_order":0, 31 | "updatetime":"", 32 | "comic_id":0, 33 | "volume_id":0, 34 | "volume_title":"" 35 | } 36 | 37 | ] 38 | } 39 | ], 40 | "similar":[ 41 | { 42 | "comic_id":0, 43 | "title":"", 44 | "last_update_chapter_name":"", 45 | "cover":"" 46 | } 47 | ] 48 | } -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | def keystoreProperties = new Properties() 29 | def keystorePropertiesFile = rootProject.file('key.properties') 30 | if (keystorePropertiesFile.exists()) { 31 | keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) 32 | } 33 | 34 | android { 35 | compileSdkVersion 31 36 | 37 | sourceSets { 38 | main.java.srcDirs += 'src/main/kotlin' 39 | } 40 | 41 | lintOptions { 42 | disable 'InvalidPackage' 43 | } 44 | 45 | defaultConfig { 46 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 47 | applicationId "com.nsapp.dmzj" 48 | minSdkVersion 19 49 | targetSdkVersion 28 50 | versionCode flutterVersionCode.toInteger() 51 | versionName flutterVersionName 52 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 53 | 54 | } 55 | 56 | signingConfigs { 57 | release { 58 | keyAlias keystoreProperties['keyAlias'] 59 | keyPassword keystoreProperties['keyPassword'] 60 | storeFile file(keystoreProperties['storeFile']) 61 | storePassword keystoreProperties['storePassword'] 62 | } 63 | } 64 | buildTypes { 65 | release { 66 | signingConfig signingConfigs.release 67 | ndk { 68 | //abiFilters 'armeabi-v7a','arm64-v8a' 69 | } 70 | } 71 | debug { 72 | ndk { 73 | //abiFilters 'armeabi-v7a','arm64-v8a','x86' 74 | } 75 | } 76 | } 77 | 78 | } 79 | 80 | flutter { 81 | source '../..' 82 | } 83 | 84 | dependencies { 85 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 86 | testImplementation 'junit:junit:4.12' 87 | androidTestImplementation 'androidx.test.ext:junit:1.1.1' 88 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' 89 | } 90 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 11 | 17 | 24 | 28 | 32 | 36 | 37 | 38 | 39 | 40 | 41 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /android/app/src/main/kotlin/com/nsapp/dmzj/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.nsapp.dmzj 2 | 3 | import dev.darttools.flutter_android_volume_keydown.FlutterAndroidVolumeKeydownActivity 4 | 5 | class MainActivity: FlutterAndroidVolumeKeydownActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /android/app/src/main/res/xml/network_security_config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.6.10' 3 | repositories { 4 | maven { url 'https://maven.aliyun.com/repository/public' } 5 | // maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'} 6 | maven { url 'https://maven.aliyun.com/repository/google' } 7 | // jcenter() 8 | } 9 | 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:7.1.0' // 3.5.0 12 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | maven { url 'https://maven.aliyun.com/repository/public' } 19 | // maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'} 20 | maven { url 'https://maven.aliyun.com/repository/google' } 21 | // google() 22 | // jcenter() 23 | } 24 | } 25 | 26 | rootProject.buildDir = '../build' 27 | subprojects { 28 | project.buildDir = "${rootProject.buildDir}/${project.name}" 29 | } 30 | subprojects { 31 | project.evaluationDependsOn(':app') 32 | } 33 | 34 | task clean(type: Delete) { 35 | delete rootProject.buildDir 36 | } 37 | -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | 3 | android.useAndroidX=true 4 | android.enableJetifier=true 5 | android.enableR8=true 6 | -------------------------------------------------------------------------------- /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.2-all.zip 7 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | 3 | def flutterProjectRoot = rootProject.projectDir.parentFile.toPath() 4 | 5 | def plugins = new Properties() 6 | def pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins') 7 | if (pluginsFile.exists()) { 8 | pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) } 9 | } 10 | 11 | plugins.each { name, path -> 12 | def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile() 13 | include ":$name" 14 | project(":$name").projectDir = pluginDirectory 15 | } 16 | -------------------------------------------------------------------------------- /android/settings_aar.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /api.md: -------------------------------------------------------------------------------- 1 | ### 是否绑定手机和设置密码 2 | 3 | http://v3api.dmzj.com/account/isbindtelpwd?dmzj_token=22fda9aea049c12011d5b581ad87880c&channel=Android&version=2.7.017×tamp=1568202740 4 | 5 | ``` 6 | {"code":0,"msg":"OK","data":{"is_bind_tel":0,"is_set_pwd":1}} 7 | ``` 8 | 9 | ### 消息未读 10 | 11 | http://v3api.dmzj.com/msg/unread/ 12 | 13 | ``` 14 | {"code":0,"msg":"OK","data":{"mess_unread_num":0,"reply_unread_num":"","system_unread_num":"","reply__unread_num":0,"system__unread_num":0}} 15 | ``` 16 | 17 | ## 漫画 18 | 19 | ### 漫画推荐 20 | 21 | http://v3api.dmzj.com/recommend_new.json?channel=Android&version=2.7.017×tamp=1568202741 22 | 23 | 24 | ### 漫画更新 25 | 26 | http://v3api.dmzj.com/latest/100/0.json?channel=Android&version=2.7.017×tamp=1568202741 27 | 28 | ### 首页-订阅 29 | http://v3api.dmzj.com/recommend/batchUpdate?uid=101484479&category_id=49&channel=Android&version=2.7.017×tamp=1568202743 30 | 31 | ### 猜你喜欢 32 | http://v3api.dmzj.com/recommend/batchUpdate?uid=101484479&category_id=50&channel=Android&version=2.7.017×tamp=1568202743 33 | 34 | ## 个人中心 35 | 36 | ### 个人信息 37 | http://v3api.dmzj.com/UCenter/comicsv2/101484479.json?channel=Android&dmzj_token=22fda9aea049c12011d5b581ad87880c&version=2.7.017×tamp=1568203263 38 | 39 | 40 | ### 登录 41 | 42 | POST https://user.dmzj.com/loginV2/m_confirm HTTP/1.1 43 | Content-Type: application/x-www-form-urlencoded 44 | Content-Length: 34 45 | Host: user.dmzj.com 46 | Connection: Keep-Alive 47 | Accept-Encoding: gzip 48 | User-Agent: okhttp/3.12.1 49 | 50 | passwd= &nickname= 51 | 52 | ## 新闻 53 | 54 | ### 新闻分类 55 | http://v3api.dmzj.com/article/category.json?channel=Android&version=2.7.017×tamp=1568204838 56 | 57 | ### 首页banner 58 | 59 | http://v3api.dmzj.com/v3/article/recommend/header.json?channel=Android&version=2.7.017×tamp=1568204838 60 | 61 | ### 最新 62 | http://v3api.dmzj.com/v3/article/list/0/2/0.json?channel=Android&version=2.7.017×tamp=1568204838 63 | 64 | http://v3api.dmzj.com/v3/article/list/1/3/0.json?channel=Android&version=2.7.017×tamp=1568204941 65 | http://v3api.dmzj.com/v3/article/list/分类ID/固定3/页数0开始.json?channel=Android&version=2.7.017×tamp=1568204983 -------------------------------------------------------------------------------- /assets/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/assets/ic_launcher.png -------------------------------------------------------------------------------- /assets/img_ucenter_def_bac.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/assets/img_ucenter_def_bac.jpg -------------------------------------------------------------------------------- /assets/qq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/assets/qq.png -------------------------------------------------------------------------------- /assets/weibo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/assets/weibo.png -------------------------------------------------------------------------------- /assets/weixin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/assets/weixin.png -------------------------------------------------------------------------------- /ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | 8.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" 2 | #include "Generated.xcconfig" 3 | -------------------------------------------------------------------------------- /ios/Flutter/flutter_export_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is a generated file; do not edit or check into version control. 3 | export "FLUTTER_ROOT=D:\workspace\dmzj_flutter\flutter" 4 | export "FLUTTER_APPLICATION_PATH=D:\workspace\dmzj_flutter\dmzj_flutter" 5 | export "COCOAPODS_PARALLEL_CODE_SIGN=true" 6 | export "FLUTTER_TARGET=lib\main.dart" 7 | export "FLUTTER_BUILD_DIR=build" 8 | export "FLUTTER_BUILD_NAME=1.2.0" 9 | export "FLUTTER_BUILD_NUMBER=210616" 10 | export "DART_OBFUSCATION=false" 11 | export "TRACK_WIDGET_CREATION=false" 12 | export "TREE_SHAKE_ICONS=false" 13 | export "PACKAGE_CONFIG=.packages" 14 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment this line to define a global platform for your project 2 | # platform :ios, '9.0' 3 | source 'https://github.com/CocoaPods/Specs.git' 4 | platform :ios, '8.0' #增加的内容 5 | # CocoaPods analytics sends network stats synchronously affecting flutter build latency. 6 | ENV['COCOAPODS_DISABLE_STATS'] = 'true' 7 | 8 | project 'Runner', { 9 | 'Debug' => :debug, 10 | 'Profile' => :release, 11 | 'Release' => :release, 12 | } 13 | 14 | def parse_KV_file(file, separator='=') 15 | file_abs_path = File.expand_path(file) 16 | if !File.exists? file_abs_path 17 | return []; 18 | end 19 | generated_key_values = {} 20 | skip_line_start_symbols = ["#", "/"] 21 | File.foreach(file_abs_path) do |line| 22 | next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ } 23 | plugin = line.split(pattern=separator) 24 | if plugin.length == 2 25 | podname = plugin[0].strip() 26 | path = plugin[1].strip() 27 | podpath = File.expand_path("#{path}", file_abs_path) 28 | generated_key_values[podname] = podpath 29 | else 30 | puts "Invalid plugin specification: #{line}" 31 | end 32 | end 33 | generated_key_values 34 | end 35 | 36 | target 'Runner' do 37 | use_frameworks! 38 | use_modular_headers! 39 | 40 | # Flutter Pod 41 | 42 | copied_flutter_dir = File.join(__dir__, 'Flutter') 43 | copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework') 44 | copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec') 45 | unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path) 46 | # Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet. 47 | # That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration. 48 | # CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist. 49 | 50 | generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig') 51 | unless File.exist?(generated_xcode_build_settings_path) 52 | raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first" 53 | end 54 | generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path) 55 | cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR']; 56 | 57 | unless File.exist?(copied_framework_path) 58 | FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir) 59 | end 60 | unless File.exist?(copied_podspec_path) 61 | FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir) 62 | end 63 | end 64 | 65 | # Keep pod path relative so it can be checked into Podfile.lock. 66 | pod 'Flutter', :path => 'Flutter' 67 | 68 | # Plugin Pods 69 | 70 | # Prepare symlinks folder. We use symlinks to avoid having Podfile.lock 71 | # referring to absolute paths on developers' machines. 72 | system('rm -rf .symlinks') 73 | system('mkdir -p .symlinks/plugins') 74 | plugin_pods = parse_KV_file('../.flutter-plugins') 75 | plugin_pods.each do |name, path| 76 | symlink = File.join('.symlinks', 'plugins', name) 77 | File.symlink(path, symlink) 78 | pod name, :path => File.join(symlink, 'ios') 79 | end 80 | end 81 | 82 | post_install do |installer| 83 | installer.pods_project.targets.each do |target| 84 | target.build_configurations.each do |config| 85 | config.build_settings['ENABLE_BITCODE'] = 'NO' 86 | end 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /ios/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - battery (0.0.1): 3 | - Flutter 4 | - connectivity (0.0.1): 5 | - Flutter 6 | - Reachability 7 | - connectivity_macos (0.0.1): 8 | - Flutter 9 | - Flutter (1.0.0) 10 | - fluttertoast (0.0.2): 11 | - Flutter 12 | - FMDB (2.7.5): 13 | - FMDB/standard (= 2.7.5) 14 | - FMDB/standard (2.7.5) 15 | - package_info (0.0.1): 16 | - Flutter 17 | - path_provider (0.0.1): 18 | - Flutter 19 | - path_provider_macos (0.0.1): 20 | - Flutter 21 | - Reachability (3.2) 22 | - screen (0.0.1): 23 | - Flutter 24 | - share (0.0.1): 25 | - Flutter 26 | - shared_preferences (0.0.1): 27 | - Flutter 28 | - shared_preferences_macos (0.0.1): 29 | - Flutter 30 | - shared_preferences_web (0.0.1): 31 | - Flutter 32 | - sqflite (0.0.1): 33 | - Flutter 34 | - FMDB (~> 2.7.2) 35 | - url_launcher (0.0.1): 36 | - Flutter 37 | - url_launcher_macos (0.0.1): 38 | - Flutter 39 | - url_launcher_web (0.0.1): 40 | - Flutter 41 | - webview_flutter (0.0.1): 42 | - Flutter 43 | 44 | DEPENDENCIES: 45 | - battery (from `.symlinks/plugins/battery/ios`) 46 | - connectivity (from `.symlinks/plugins/connectivity/ios`) 47 | - connectivity_macos (from `.symlinks/plugins/connectivity_macos/ios`) 48 | - Flutter (from `Flutter`) 49 | - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) 50 | - package_info (from `.symlinks/plugins/package_info/ios`) 51 | - path_provider (from `.symlinks/plugins/path_provider/ios`) 52 | - path_provider_macos (from `.symlinks/plugins/path_provider_macos/ios`) 53 | - screen (from `.symlinks/plugins/screen/ios`) 54 | - share (from `.symlinks/plugins/share/ios`) 55 | - shared_preferences (from `.symlinks/plugins/shared_preferences/ios`) 56 | - shared_preferences_macos (from `.symlinks/plugins/shared_preferences_macos/ios`) 57 | - shared_preferences_web (from `.symlinks/plugins/shared_preferences_web/ios`) 58 | - sqflite (from `.symlinks/plugins/sqflite/ios`) 59 | - url_launcher (from `.symlinks/plugins/url_launcher/ios`) 60 | - url_launcher_macos (from `.symlinks/plugins/url_launcher_macos/ios`) 61 | - url_launcher_web (from `.symlinks/plugins/url_launcher_web/ios`) 62 | - webview_flutter (from `.symlinks/plugins/webview_flutter/ios`) 63 | 64 | SPEC REPOS: 65 | https://github.com/CocoaPods/Specs.git: 66 | - FMDB 67 | - Reachability 68 | 69 | EXTERNAL SOURCES: 70 | battery: 71 | :path: ".symlinks/plugins/battery/ios" 72 | connectivity: 73 | :path: ".symlinks/plugins/connectivity/ios" 74 | connectivity_macos: 75 | :path: ".symlinks/plugins/connectivity_macos/ios" 76 | Flutter: 77 | :path: Flutter 78 | fluttertoast: 79 | :path: ".symlinks/plugins/fluttertoast/ios" 80 | package_info: 81 | :path: ".symlinks/plugins/package_info/ios" 82 | path_provider: 83 | :path: ".symlinks/plugins/path_provider/ios" 84 | path_provider_macos: 85 | :path: ".symlinks/plugins/path_provider_macos/ios" 86 | screen: 87 | :path: ".symlinks/plugins/screen/ios" 88 | share: 89 | :path: ".symlinks/plugins/share/ios" 90 | shared_preferences: 91 | :path: ".symlinks/plugins/shared_preferences/ios" 92 | shared_preferences_macos: 93 | :path: ".symlinks/plugins/shared_preferences_macos/ios" 94 | shared_preferences_web: 95 | :path: ".symlinks/plugins/shared_preferences_web/ios" 96 | sqflite: 97 | :path: ".symlinks/plugins/sqflite/ios" 98 | url_launcher: 99 | :path: ".symlinks/plugins/url_launcher/ios" 100 | url_launcher_macos: 101 | :path: ".symlinks/plugins/url_launcher_macos/ios" 102 | url_launcher_web: 103 | :path: ".symlinks/plugins/url_launcher_web/ios" 104 | webview_flutter: 105 | :path: ".symlinks/plugins/webview_flutter/ios" 106 | 107 | SPEC CHECKSUMS: 108 | battery: 42c3029d295615713120da60f48f2dc4ce98f030 109 | connectivity: 6e94255659cc86dcbef1d452ad3e0491bb1b3e75 110 | connectivity_macos: e2e9731b6b22dda39eb1b128f6969d574460e191 111 | Flutter: 0e3d915762c693b495b44d77113d4970485de6ec 112 | fluttertoast: b644586ef3b16f67fae9a1f8754cef6b2d6b634b 113 | FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a 114 | package_info: 48b108e75b8802c2d5e126f208ef540561c98aef 115 | path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c 116 | path_provider_macos: f760a3c5b04357c380e2fddb6f9db6f3015897e0 117 | Reachability: 33e18b67625424e47b6cde6d202dce689ad7af96 118 | screen: abd91ca7bf3426e1cc3646d27e9b2358d6bf07b0 119 | share: 0b2c3e82132f5888bccca3351c504d0003b3b410 120 | shared_preferences: 430726339841afefe5142b9c1f50cb6bd7793e01 121 | shared_preferences_macos: f3f29b71ccbb56bf40c9dd6396c9acf15e214087 122 | shared_preferences_web: 141cce0c3ed1a1c5bf2a0e44f52d31eeb66e5ea9 123 | sqflite: 4001a31ff81d210346b500c55b17f4d6c7589dd0 124 | url_launcher: a1c0cc845906122c4784c542523d8cacbded5626 125 | url_launcher_macos: fd7894421cd39320dce5f292fc99ea9270b2a313 126 | url_launcher_web: e5527357f037c87560776e36436bf2b0288b965c 127 | webview_flutter: d2b4d6c66968ad042ad94cbb791f5b72b4678a96 128 | 129 | PODFILE CHECKSUM: 674d384abf9b3cb11f0b41cce2ad9e7af22420e1 130 | 131 | COCOAPODS: 1.9.1 132 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 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: [UIApplicationLaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "size": "20x20", 5 | "idiom": "iphone", 6 | "filename": "icon-20@2x.png", 7 | "scale": "2x" 8 | }, 9 | { 10 | "size": "20x20", 11 | "idiom": "iphone", 12 | "filename": "icon-20@3x.png", 13 | "scale": "3x" 14 | }, 15 | { 16 | "size": "29x29", 17 | "idiom": "iphone", 18 | "filename": "icon-29.png", 19 | "scale": "1x" 20 | }, 21 | { 22 | "size": "29x29", 23 | "idiom": "iphone", 24 | "filename": "icon-29@2x.png", 25 | "scale": "2x" 26 | }, 27 | { 28 | "size": "29x29", 29 | "idiom": "iphone", 30 | "filename": "icon-29@3x.png", 31 | "scale": "3x" 32 | }, 33 | { 34 | "size": "40x40", 35 | "idiom": "iphone", 36 | "filename": "icon-40@2x.png", 37 | "scale": "2x" 38 | }, 39 | { 40 | "size": "40x40", 41 | "idiom": "iphone", 42 | "filename": "icon-40@3x.png", 43 | "scale": "3x" 44 | }, 45 | { 46 | "size": "60x60", 47 | "idiom": "iphone", 48 | "filename": "icon-60@2x.png", 49 | "scale": "2x" 50 | }, 51 | { 52 | "size": "60x60", 53 | "idiom": "iphone", 54 | "filename": "icon-60@3x.png", 55 | "scale": "3x" 56 | }, 57 | { 58 | "size": "20x20", 59 | "idiom": "ipad", 60 | "filename": "icon-20-ipad.png", 61 | "scale": "1x" 62 | }, 63 | { 64 | "size": "20x20", 65 | "idiom": "ipad", 66 | "filename": "icon-20@2x-ipad.png", 67 | "scale": "2x" 68 | }, 69 | { 70 | "size": "29x29", 71 | "idiom": "ipad", 72 | "filename": "icon-29-ipad.png", 73 | "scale": "1x" 74 | }, 75 | { 76 | "size": "29x29", 77 | "idiom": "ipad", 78 | "filename": "icon-29@2x-ipad.png", 79 | "scale": "2x" 80 | }, 81 | { 82 | "size": "40x40", 83 | "idiom": "ipad", 84 | "filename": "icon-40.png", 85 | "scale": "1x" 86 | }, 87 | { 88 | "size": "40x40", 89 | "idiom": "ipad", 90 | "filename": "icon-40@2x.png", 91 | "scale": "2x" 92 | }, 93 | { 94 | "size": "76x76", 95 | "idiom": "ipad", 96 | "filename": "icon-76.png", 97 | "scale": "1x" 98 | }, 99 | { 100 | "size": "76x76", 101 | "idiom": "ipad", 102 | "filename": "icon-76@2x.png", 103 | "scale": "2x" 104 | }, 105 | { 106 | "size": "83.5x83.5", 107 | "idiom": "ipad", 108 | "filename": "icon-83.5@2x.png", 109 | "scale": "2x" 110 | }, 111 | { 112 | "size": "1024x1024", 113 | "idiom": "ios-marketing", 114 | "filename": "icon-1024.png", 115 | "scale": "1x" 116 | } 117 | ], 118 | "info": { 119 | "version": 1, 120 | "author": "icon.wuruihong.com" 121 | } 122 | } -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/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/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-1024.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20-ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x-ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29-ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x-ipad.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brillgone/dmzj_flutter/3b8094df1a6b71aa4c312621f0713c139dc757a5/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /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. -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | 动漫之家 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(MARKETING_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | ITSAppUsesNonExemptEncryption 24 | 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSAllowsArbitraryLoads 30 | 31 | NSAllowsArbitraryLoadsInWebContent 32 | 33 | 34 | UILaunchStoryboardName 35 | LaunchScreen 36 | UIMainStoryboardFile 37 | Main 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | UIViewControllerBasedStatusBarAppearance 52 | 53 | io.flutter.embedded_views_preview 54 | YES 55 | 56 | 57 | -------------------------------------------------------------------------------- /ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" -------------------------------------------------------------------------------- /lib/app/api/api_util.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | import 'dart:io'; 3 | import 'dart:typed_data'; 4 | 5 | import 'package:crypton/crypton.dart'; 6 | import 'package:flutter_dmzj/app/config_helper.dart'; 7 | 8 | import '../http_util.dart'; 9 | 10 | class ApiUtil { 11 | static const PRIVATE_KEY = 12 | "MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAK8nNR1lTnIfIes6oRWJNj3mB6OssDGx0uGMpgpbVCpf6+VwnuI2stmhZNoQcM417Iz7WqlPzbUmu9R4dEKmLGEEqOhOdVaeh9Xk2IPPjqIu5TbkLZRxkY3dJM1htbz57d/roesJLkZXqssfG5EJauNc+RcABTfLb4IiFjSMlTsnAgMBAAECgYEAiz/pi2hKOJKlvcTL4jpHJGjn8+lL3wZX+LeAHkXDoTjHa47g0knYYQteCbv+YwMeAGupBWiLy5RyyhXFoGNKbbnvftMYK56hH+iqxjtDLnjSDKWnhcB7089sNKaEM9Ilil6uxWMrMMBH9v2PLdYsqMBHqPutKu/SigeGPeiB7VECQQDizVlNv67go99QAIv2n/ga4e0wLizVuaNBXE88AdOnaZ0LOTeniVEqvPtgUk63zbjl0P/pzQzyjitwe6HoCAIpAkEAxbOtnCm1uKEp5HsNaXEJTwE7WQf7PrLD4+BpGtNKkgja6f6F4ld4QZ2TQ6qvsCizSGJrjOpNdjVGJ7bgYMcczwJBALvJWPLmDi7ToFfGTB0EsNHZVKE66kZ/8Stx+ezueke4S556XplqOflQBjbnj2PigwBN/0afT+QZUOBOjWzoDJkCQClzo+oDQMvGVs9GEajS/32mJ3hiWQZrWvEzgzYRqSf3XVcEe7PaXSd8z3y3lACeeACsShqQoc8wGlaHXIJOHTcCQQCZw5127ZGs8ZDTSrogrH73Kw/HvX55wGAeirKYcv28eauveCG7iyFR0PFB/P/EDZnyb+ifvyEFlucPUI0+Y87F"; 13 | static Uint8List decrypt(String text) { 14 | try { 15 | RSAKeypair rsaKeypair = RSAKeypair(RSAPrivateKey.fromString(PRIVATE_KEY)); 16 | // print(rsaKeypair.privateKey.toPEM()); 17 | var decrypted = rsaKeypair.privateKey.decryptData(base64.decode(text)); 18 | return decrypted; 19 | } catch (e) { 20 | throw AppError('返回数据解密失败'); 21 | } 22 | } 23 | 24 | static const BASE_URL_V4 = "https://nnv4api.muwai.com"; 25 | static Map defaultParameter({bool needLogined = false}) { 26 | Map map = { 27 | "channel": Platform.operatingSystem, 28 | "version": "3.0.0", 29 | "timestamp": 30 | (DateTime.now().millisecondsSinceEpoch / 1000).toStringAsFixed(0) 31 | }; 32 | if (needLogined && ConfigHelper.getUserIsLogined()) { 33 | map.addAll({'uid': ConfigHelper.getUserInfo()?.uid ?? ""}); 34 | } 35 | return map; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /lib/app/api/comic.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_dmzj/app/http_util.dart'; 2 | import 'package:flutter_dmzj/protobuf/comic/detail_response.pb.dart'; 3 | import 'package:flutter_dmzj/protobuf/comic/rank_list_response.pb.dart'; 4 | import 'package:flutter_dmzj/protobuf/comic/update_list_response.pb.dart'; 5 | 6 | import 'api_util.dart'; 7 | 8 | class ComicApi { 9 | static ComicApi _comicApi; 10 | static ComicApi get instance { 11 | if (_comicApi == null) { 12 | _comicApi = ComicApi(); 13 | } 14 | return _comicApi; 15 | } 16 | 17 | /// 首页-更新 18 | Future> getUpdateList(String type, 19 | {int page = 1}) async { 20 | var path = "${ApiUtil.BASE_URL_V4}/comic/update/list/$type/$page"; 21 | var result = await HttpUtil.instance.httpGet( 22 | path, 23 | queryParameters: ApiUtil.defaultParameter(needLogined: true), 24 | ); 25 | var resultBytes = ApiUtil.decrypt(result); 26 | 27 | var data = ComicUpdateListResponse.fromBuffer(resultBytes); 28 | if (data.errno != 0) { 29 | throw AppError(data.errmsg); 30 | } 31 | return data.data; 32 | } 33 | 34 | /// 漫画详情 35 | Future getDetail(int comicId) async { 36 | var path = "${ApiUtil.BASE_URL_V4}/comic/detail/$comicId"; 37 | var result = await HttpUtil.instance.httpGet( 38 | path, 39 | queryParameters: ApiUtil.defaultParameter(needLogined: true), 40 | ); 41 | var resultBytes = ApiUtil.decrypt(result); 42 | 43 | var data = ComicDetailResponse.fromBuffer(resultBytes); 44 | if (data.errno != 0) { 45 | throw AppError(data.errmsg, code: data.errno); 46 | } 47 | return data.data; 48 | } 49 | 50 | /// 首页-排行榜 51 | Future> getRankList( 52 | {int tagId = 0, int byTime = 0, int rankType, int page = 0}) async { 53 | var path = "${ApiUtil.BASE_URL_V4}/comic/rank/list"; 54 | var par = ApiUtil.defaultParameter(needLogined: true); 55 | par.addAll({ 56 | 'tag_id': tagId, 57 | 'by_time': byTime, 58 | 'rank_type': rankType, 59 | 'page': page 60 | }); 61 | var result = await HttpUtil.instance.httpGet( 62 | path, 63 | queryParameters: par, 64 | ); 65 | var resultBytes = ApiUtil.decrypt(result); 66 | 67 | var data = ComicRankListResponse.fromBuffer(resultBytes); 68 | if (data.errno != 0) { 69 | throw AppError(data.errmsg); 70 | } 71 | return data.data; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /lib/app/api/news.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter_dmzj/app/http_util.dart'; 2 | import 'package:flutter_dmzj/protobuf/news/news_list_response.pb.dart'; 3 | 4 | import 'api_util.dart'; 5 | 6 | class NewsApi { 7 | static NewsApi _comicApi; 8 | static NewsApi get instance { 9 | if (_comicApi == null) { 10 | _comicApi = NewsApi(); 11 | } 12 | return _comicApi; 13 | } 14 | 15 | /// 新闻列表 16 | Future> getNewsList(int id, {int page = 1}) async { 17 | var path = "${ApiUtil.BASE_URL_V4}/news/list/$id/${id == 0 ? 2 : 3}/$page"; 18 | var result = await HttpUtil.instance.httpGet( 19 | path, 20 | queryParameters: ApiUtil.defaultParameter(), 21 | ); 22 | var resultBytes = ApiUtil.decrypt(result); 23 | 24 | var data = NewsListResponse.fromBuffer(resultBytes); 25 | if (data.errno != 0) { 26 | throw AppError(data.errmsg); 27 | } 28 | return data.data; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /lib/app/api/novel.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:crypto/crypto.dart'; 4 | import 'package:flutter_dmzj/app/http_util.dart'; 5 | import 'package:flutter_dmzj/protobuf/novel/novel_chapter_response.pb.dart'; 6 | import 'package:flutter_dmzj/protobuf/novel/novel_detail_response.pb.dart'; 7 | import 'api_util.dart'; 8 | 9 | class NovelApi { 10 | static NovelApi _novelApi; 11 | static NovelApi get instance { 12 | if (_novelApi == null) { 13 | _novelApi = NovelApi(); 14 | } 15 | return _novelApi; 16 | } 17 | 18 | /// 轻小说详情 19 | Future getDetail(int novelId) async { 20 | var path = "${ApiUtil.BASE_URL_V4}/novel/detail/$novelId"; 21 | var result = await HttpUtil.instance.httpGet( 22 | path, 23 | queryParameters: ApiUtil.defaultParameter(needLogined: true), 24 | ); 25 | var resultBytes = ApiUtil.decrypt(result); 26 | 27 | var data = NovelDetailResponse.fromBuffer(resultBytes); 28 | if (data.errno != 0) { 29 | throw AppError(data.errmsg); 30 | } 31 | return data.data; 32 | } 33 | 34 | /// 小说章节 35 | Future> getChapter(int novelId) async { 36 | var path = "${ApiUtil.BASE_URL_V4}/novel/chapter/$novelId"; 37 | var result = await HttpUtil.instance.httpGet( 38 | path, 39 | queryParameters: ApiUtil.defaultParameter(needLogined: true), 40 | ); 41 | var resultBytes = ApiUtil.decrypt(result); 42 | 43 | var data = NovelChapterResponse.fromBuffer(resultBytes); 44 | if (data.errno != 0) { 45 | throw AppError(data.errmsg); 46 | } 47 | return data.data; 48 | } 49 | 50 | /// 小说正文 51 | String getNovelContentUrl(int id, int volumeId, int chapterId) { 52 | var path = "/lnovel/${volumeId}_$chapterId.txt"; 53 | var ts = (DateTime.now().millisecondsSinceEpoch / 1000).toStringAsFixed(0); 54 | var key = 55 | "IBAAKCAQEAsUAdKtXNt8cdrcTXLsaFKj9bSK1nEOAROGn2KJXlEVekcPssKUxSN8dsfba51kmHM"; 56 | key += path; 57 | key += ts; 58 | key = md5.convert(utf8.encode(key)).toString().toLowerCase(); 59 | // var result = await HttpUtil.instance.httpGet( 60 | // "http://jurisdiction.muwai.com" + path, 61 | // queryParameters: {"t": ts, "k": key}, 62 | // ); 63 | 64 | // return "http://v2.api.dmzj.com/novel/download/$id\_$volumeId\_$chapterId.txt"; 65 | 66 | return "http://jurisdiction.dmzj.com" + path + "?t=$ts&k=$key"; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /lib/app/app_setting.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/app/config_helper.dart'; 3 | 4 | class AppSetting with ChangeNotifier { 5 | AppSetting() { 6 | changeComicWebApi(ConfigHelper.getComicWebApi()); 7 | changeComicVertical(ConfigHelper.getComicVertical()); 8 | changeComicWakelock(ConfigHelper.getComicWakelock()); 9 | changeReadReverse(ConfigHelper.getComicReadReverse()); 10 | changeComicReadShowState(ConfigHelper.getComicReadShowState()); 11 | changeComicReadShowStatusBar(ConfigHelper.getComicShowStatusBar()); 12 | changeBrightness(ConfigHelper.getComicBrightness()); 13 | changeComicSystemBrightness(ConfigHelper.getComicSystemBrightness()); 14 | changeNovelFontSize(ConfigHelper.getNovelFontSize()); 15 | changeNovelLineHeight(ConfigHelper.getNovelLineHeight()); 16 | changeNovelReadDirection(ConfigHelper.getNovelReadDirection()); 17 | changeNovelReadTheme(ConfigHelper.getNovelTheme()); 18 | } 19 | 20 | bool _comicVerticalMode; 21 | get comicVerticalMode => _comicVerticalMode; 22 | void changeComicVertical(bool value) { 23 | _comicVerticalMode = value; 24 | 25 | notifyListeners(); 26 | ConfigHelper.setComicVertical(value); 27 | if (value) { 28 | changeReadReverse(false); 29 | } 30 | } 31 | 32 | bool _comicWebApi; 33 | get comicWebApi => _comicWebApi; 34 | void changeComicWebApi(bool value) { 35 | _comicWebApi = value; 36 | notifyListeners(); 37 | ConfigHelper.setComicWebApi(value); 38 | } 39 | 40 | bool _comicWakelock; 41 | get comicWakelock => _comicWakelock; 42 | void changeComicWakelock(bool value) { 43 | _comicWakelock = value; 44 | notifyListeners(); 45 | ConfigHelper.setComicWakelock(value); 46 | } 47 | 48 | bool _comicReadReverse; 49 | get comicReadReverse => _comicReadReverse; 50 | void changeReadReverse(bool value) { 51 | _comicReadReverse = value; 52 | notifyListeners(); 53 | ConfigHelper.setComicReadReverse(value); 54 | if (value) { 55 | changeComicVertical(false); 56 | } 57 | } 58 | 59 | bool _comicReadShowstate; 60 | get comicReadShowstate => _comicReadShowstate; 61 | void changeComicReadShowState(bool value) { 62 | _comicReadShowstate = value; 63 | notifyListeners(); 64 | ConfigHelper.setComicReadShowState(value); 65 | } 66 | 67 | bool _comicReadShowStatusBar; 68 | get comicReadShowStatusBar => _comicReadShowStatusBar; 69 | void changeComicReadShowStatusBar(bool value) { 70 | _comicReadShowStatusBar = value; 71 | notifyListeners(); 72 | ConfigHelper.setComicShowStatusBar(value); 73 | } 74 | 75 | bool _comicSystemBrightness; 76 | get comicSystemBrightness => _comicSystemBrightness; 77 | void changeComicSystemBrightness(bool value) { 78 | _comicSystemBrightness = value; 79 | notifyListeners(); 80 | ConfigHelper.setComicSystemBrightness(value); 81 | } 82 | 83 | double _comicBrightness; 84 | get comicBrightness => _comicBrightness; 85 | void changeBrightness(double value) { 86 | _comicBrightness = value; 87 | notifyListeners(); 88 | ConfigHelper.setComicBrightness(value); 89 | } 90 | 91 | double _novelFontSize; 92 | double get novelFontSize => _novelFontSize; 93 | void changeNovelFontSize(double value) { 94 | _novelFontSize = value; 95 | notifyListeners(); 96 | ConfigHelper.setNovelFontSize(value); 97 | } 98 | 99 | double _novelLineHeight; 100 | double get novelLineHeight => _novelLineHeight; 101 | void changeNovelLineHeight(double value) { 102 | _novelLineHeight = value; 103 | notifyListeners(); 104 | ConfigHelper.setNovelLineHeight(value); 105 | } 106 | 107 | int _novelReadDirection; 108 | get novelReadDirection => _novelReadDirection; 109 | void changeNovelReadDirection(int value) { 110 | _novelReadDirection = value; 111 | notifyListeners(); 112 | ConfigHelper.setNovelReadDirection(value); 113 | } 114 | 115 | static List bgColors = [ 116 | Color.fromRGBO(245, 239, 217, 1), 117 | Color.fromRGBO(248, 247, 252, 1), 118 | Color.fromRGBO(192, 237, 198, 1), 119 | Colors.black 120 | ]; 121 | static List fontColors = [ 122 | Colors.black, 123 | Colors.black, 124 | Colors.black, 125 | Color.fromRGBO(200, 200, 200, 1), 126 | ]; 127 | 128 | int _novelReadTheme; 129 | get novelReadTheme => _novelReadTheme; 130 | void changeNovelReadTheme(int value) { 131 | _novelReadTheme = value; 132 | notifyListeners(); 133 | ConfigHelper.setNovelTheme(value); 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /lib/app/app_theme.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/app/config_helper.dart'; 3 | 4 | class AppTheme with ChangeNotifier { 5 | AppTheme() { 6 | changeThemeMode(ConfigHelper.getThemeMode()); 7 | changeThemeColor(ConfigHelper.getAppTheme()); 8 | } 9 | 10 | static Map themeModes = { 11 | "跟随系统": ThemeMode.system, 12 | "开启": ThemeMode.dark, 13 | "关闭": ThemeMode.light, 14 | }; 15 | 16 | static Map themeColors = { 17 | "胖次蓝": Colors.blue, 18 | "姨妈红": Colors.red, 19 | "咸蛋黄": Colors.yellow, 20 | "早苗绿": Colors.green, 21 | "少女粉": Colors.pink, 22 | "基佬紫": Colors.purple, 23 | "朴素灰": Colors.blueGrey 24 | }; 25 | 26 | ThemeMode _themeMode; 27 | String _themeModeName; 28 | get themeMode => _themeMode; 29 | get themeModeName => _themeModeName; 30 | void changeThemeMode(int index) { 31 | _themeMode = AppTheme.themeModes.values.toList()[index]; 32 | _themeModeName = AppTheme.themeModes.keys.toList()[index]; 33 | notifyListeners(); 34 | ConfigHelper.setAppTheme(index); 35 | } 36 | 37 | void showThemeModeDialog(BuildContext context) { 38 | showDialog( 39 | context: context, 40 | builder: (BuildContext context) { 41 | return new SimpleDialog( 42 | title: new Text('夜间模式'), 43 | children: _createThemeModeWidget(context), 44 | ); 45 | }, 46 | ); 47 | } 48 | 49 | List _createThemeModeWidget(BuildContext context) { 50 | List widgets = []; 51 | for (var item in AppTheme.themeModes.keys) { 52 | widgets.add(RadioListTile( 53 | groupValue: item, 54 | value: _themeModeName, 55 | title: new Text( 56 | item, 57 | ), 58 | onChanged: (value) { 59 | changeThemeMode(AppTheme.themeModes.keys.toList().indexOf(item)); 60 | Navigator.of(context).pop(); 61 | }, 62 | )); 63 | } 64 | return widgets; 65 | } 66 | 67 | Color _themeColor; 68 | String _themeColorName; 69 | get themeColor => _themeColor; 70 | get themeColorName => _themeColorName; 71 | void changeThemeColor(int index) { 72 | _themeColor = AppTheme.themeColors.values.toList()[index]; 73 | _themeColorName = AppTheme.themeColors.keys.toList()[index]; 74 | notifyListeners(); 75 | ConfigHelper.setAppTheme(index); 76 | } 77 | 78 | void showThemeDialog(BuildContext context) { 79 | showDialog( 80 | context: context, 81 | builder: (BuildContext context) { 82 | return new SimpleDialog( 83 | title: new Text('切换主题'), 84 | children: _createThemeWidget(context), 85 | ); 86 | }, 87 | ); 88 | } 89 | 90 | List _createThemeWidget(BuildContext context) { 91 | List widgets = []; 92 | for (var item in AppTheme.themeColors.keys) { 93 | widgets.add(RadioListTile( 94 | groupValue: item, 95 | value: _themeColorName, 96 | title: new Text( 97 | item, 98 | style: TextStyle(color: AppTheme.themeColors[item]), 99 | ), 100 | onChanged: (value) { 101 | changeThemeColor(AppTheme.themeColors.keys.toList().indexOf(item)); 102 | Navigator.of(context).pop(); 103 | }, 104 | )); 105 | } 106 | return widgets; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /lib/app/comic_download_helper.dart: -------------------------------------------------------------------------------- 1 | import 'package:event_bus/event_bus.dart'; 2 | import 'package:flutter_dmzj/sql/comic_down.dart'; 3 | // 章节ID 4 | // 漫画ID 5 | // 漫画名称 6 | // 当前页数 7 | // 总页数 8 | // 下载状态 是否下载完成 9 | // 文件夹 10 | 11 | // 队列 12 | // List 13 | // 当前下载 14 | // List Downloading 15 | 16 | // Status: 17 | // 等待下载 18 | // 下载中 19 | // 暂停中 20 | // 下载失败 21 | 22 | 23 | // 保存至数据库 24 | // 加入队列 25 | // 下载队列获取信息 26 | // 开始下载 27 | // 下载封面 28 | // 获取图片信息 29 | // 开始下载图片 30 | // 更新数据库 31 | 32 | 33 | class ComicDownloadHelper{ 34 | static EventBus downloadEvent=EventBus(); 35 | static List dwonloadQueues=[]; 36 | static ComicDownloadSqlItem currentDownload; 37 | static bool downloading; 38 | static void addDownload(ComicDownloadSqlItem info) async{ 39 | //保存数据库 40 | var item=await ComicDownloadProvider.getItem(info.chapterID); 41 | if(item==null){ 42 | await ComicDownloadProvider.insert(info); 43 | } 44 | //加入队列 45 | dwonloadQueues.add(info); 46 | 47 | 48 | } 49 | 50 | } 51 | 52 | 53 | -------------------------------------------------------------------------------- /lib/app/commnet_helper.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter_dmzj/app/api.dart'; 4 | import 'package:flutter_dmzj/app/config_helper.dart'; 5 | import 'package:fluttertoast/fluttertoast.dart'; 6 | import 'package:http/http.dart' as http; 7 | 8 | class CommentHelper { 9 | static Future likeComment(int objId, String commentId, int type) async { 10 | try { 11 | var result = ""; 12 | var response = 13 | await http.get(Uri.parse(Api.likeCommentV3(objId, commentId, type))); 14 | result = response.body; 15 | var jsonMap = jsonDecode(result); 16 | if (jsonMap["code"] == 0) { 17 | //TODO 添加到数据库中 18 | Fluttertoast.showToast(msg: "点赞成功"); 19 | return true; 20 | } else { 21 | Fluttertoast.showToast(msg: "点赞失败"); 22 | return false; 23 | } 24 | } catch (e) { 25 | print(e); 26 | Fluttertoast.showToast(msg: "点赞出现错误"); 27 | return false; 28 | } 29 | } 30 | 31 | static Future checkStatus() async { 32 | try { 33 | var uid = ConfigHelper.getUserInfo()?.uid ?? ""; 34 | 35 | var result = ""; 36 | var response = await http.get(Uri.parse(Api.checkCommentV3(uid))); 37 | result = response.body; 38 | var jsonMap = jsonDecode(result); 39 | if (jsonMap["msg"] == "") { 40 | return CommnetResult(true, ""); 41 | } else { 42 | return CommnetResult(false, jsonMap["msg"].toString()); 43 | } 44 | } catch (e) { 45 | return CommnetResult(true, ""); 46 | } 47 | } 48 | 49 | static Future addComment(int objId, int type, String content, 50 | {String toCommentId = "0", 51 | String originCommentId = "0", 52 | String toUid = "0"}) async { 53 | try { 54 | if (!ConfigHelper.getUserIsLogined() ?? false) { 55 | //TODO 跳转登录 56 | return CommnetResult(false, "没有登录"); 57 | } 58 | var token = ConfigHelper.getUserInfo()?.dmzj_token ?? ""; 59 | var response = await http.post(Uri.parse(Api.addCommentV3(type)), body: { 60 | "obj_id": objId, 61 | "to_comment_id": toCommentId, 62 | "origin_comment_id": originCommentId, 63 | "to_uid": toUid, 64 | "sender_terminal": 1, 65 | "content": content, 66 | "dmzj_token": token, 67 | "_debug": 0 68 | }); 69 | var jsonMap = jsonDecode(response.body); 70 | 71 | if (jsonMap["code"] == 0) { 72 | return CommnetResult(true, "发表评论失败"); 73 | } else { 74 | return CommnetResult(false, jsonMap["msg"].toString()); 75 | } 76 | } catch (e) { 77 | print(e); 78 | return CommnetResult(true, "发表评论出现错误"); 79 | } 80 | } 81 | } 82 | 83 | class CommnetResult { 84 | bool result; 85 | String msg; 86 | CommnetResult(this.result, this.msg); 87 | } 88 | -------------------------------------------------------------------------------- /lib/app/http_util.dart: -------------------------------------------------------------------------------- 1 | import 'package:dio/dio.dart'; 2 | 3 | class HttpUtil { 4 | static HttpUtil _httpUtil; 5 | static HttpUtil get instance { 6 | if (_httpUtil == null) { 7 | _httpUtil = HttpUtil(); 8 | } 9 | return _httpUtil; 10 | } 11 | 12 | Dio dio; 13 | HttpUtil() { 14 | dio = Dio( 15 | BaseOptions(), 16 | ); 17 | } 18 | Future httpGet( 19 | String url, { 20 | Map queryParameters, 21 | bool needLogin = false, 22 | }) async { 23 | try { 24 | var result = await dio.get( 25 | url, 26 | queryParameters: queryParameters, 27 | options: Options( 28 | responseType: ResponseType.plain, 29 | //headers: header, 30 | ), 31 | ); 32 | 33 | return result.data; 34 | } catch (e) { 35 | if (e is DioError) { 36 | dioErrorHandle(e); 37 | } else { 38 | throw AppError("网络请求失败"); 39 | } 40 | return null; 41 | } 42 | } 43 | 44 | void dioErrorHandle(DioError e) { 45 | switch (e.type) { 46 | case DioErrorType.cancel: 47 | throw AppError("请求被取消"); 48 | break; 49 | case DioErrorType.response: 50 | throw AppError("请求失败:${e.response.statusCode}"); 51 | break; 52 | case DioErrorType.connectTimeout: 53 | case DioErrorType.sendTimeout: 54 | case DioErrorType.receiveTimeout: 55 | throw AppError("网络连接超时,请稍后再试"); 56 | break; 57 | default: 58 | throw AppError("请求失败,无法连接至服务器"); 59 | break; 60 | } 61 | } 62 | } 63 | 64 | class AppError implements Exception { 65 | final int code; 66 | final String message; 67 | AppError( 68 | this.message, { 69 | this.code, 70 | }); 71 | 72 | @override 73 | String toString() { 74 | return message ?? "出现问题"; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/app/user_info.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_dmzj/app/api.dart'; 5 | import 'package:flutter_dmzj/app/config_helper.dart'; 6 | import 'package:flutter_dmzj/models/user/user_model.dart'; 7 | import 'package:flutter_dmzj/models/user/user_profile.dart'; 8 | import 'package:http/http.dart' as http; 9 | 10 | class AppUserInfo with ChangeNotifier { 11 | AppUserInfo() { 12 | changeIsLogin(ConfigHelper.getUserIsLogined()); 13 | changeBindTel(ConfigHelper.getUserIsBindTel()); 14 | changeLoginInfo(ConfigHelper.getUserInfo()); 15 | changeUserProfile(ConfigHelper.getUserProfile()); 16 | } 17 | 18 | bool _isLogin; 19 | get isLogin => _isLogin; 20 | void changeIsLogin(bool value) { 21 | _isLogin = value; 22 | 23 | notifyListeners(); 24 | ConfigHelper.setUserIsLogined(value); 25 | } 26 | 27 | //是否绑定手机号码,未绑定不能评论 28 | bool _isBindTel; 29 | get isBindTel => _isBindTel; 30 | void changeBindTel(bool value) { 31 | _isBindTel = value; 32 | 33 | notifyListeners(); 34 | ConfigHelper.setUserIsBindTel(value); 35 | } 36 | 37 | //登录获得的用户信息,含Token 38 | UserInfo _userInfo; 39 | UserInfo get loginInfo => _userInfo; 40 | void changeLoginInfo(UserInfo value) { 41 | _userInfo = value; 42 | notifyListeners(); 43 | ConfigHelper.setUserInfo(value); 44 | } 45 | 46 | //用户详细资料 47 | UserProfileModel _userProfile; 48 | UserProfileModel get userProfile => _userProfile; 49 | void changeUserProfile(UserProfileModel value) { 50 | _userProfile = value; 51 | notifyListeners(); 52 | ConfigHelper.setUserProfile(value); 53 | } 54 | 55 | Future getUserProfile(String uid, String token) async { 56 | try { 57 | var result = await http.get(Uri.parse(Api.userProfile(uid, token))); 58 | var body = result.body; 59 | var data = UserProfileModel.fromJson(jsonDecode(body)); 60 | if (data != null) { 61 | changeUserProfile(data); 62 | } 63 | } catch (e) {} 64 | } 65 | 66 | void logout() { 67 | changeIsLogin(false); 68 | changeLoginInfo(null); 69 | changeUserProfile(null); 70 | changeBindTel(false); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/models/comic/comic_author_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicAuthor { 4 | String _nickname; 5 | String get nickname => _nickname; 6 | String _description; 7 | String get description => _description; 8 | String _cover; 9 | String get cover => _cover; 10 | List _data; 11 | List get data => _data; 12 | 13 | ComicAuthor({ 14 | String nickname, 15 | String description, 16 | String cover, 17 | List data, 18 | }):_nickname=nickname,_description=description,_cover=cover,_data=data; 19 | factory ComicAuthor.fromJson(jsonRes){ if(jsonRes == null) return null; 20 | List data = jsonRes['data'] is List ? []: null; 21 | if(data!=null) { 22 | for (var item in jsonRes['data']) { if (item != null) { data.add(ComicAuthorItem.fromJson(item)); } 23 | } 24 | } 25 | 26 | 27 | return ComicAuthor( nickname : jsonRes['nickname'], 28 | description : jsonRes['description'], 29 | cover : jsonRes['cover'], 30 | data:data, 31 | );} 32 | Map toJson() => { 33 | 'nickname': _nickname, 34 | 'description': _description, 35 | 'cover': _cover, 36 | 'data': _data, 37 | }; 38 | 39 | @override 40 | String toString() { 41 | return json.encode(this); 42 | } 43 | } 44 | class ComicAuthorItem { 45 | int _id; 46 | int get id => _id; 47 | String _name; 48 | String get name => _name; 49 | String _cover; 50 | String get cover => _cover; 51 | String _status; 52 | String get status => _status; 53 | 54 | ComicAuthorItem({ 55 | int id, 56 | String name, 57 | String cover, 58 | String status, 59 | }):_id=id,_name=name,_cover=cover,_status=status; 60 | factory ComicAuthorItem.fromJson(jsonRes)=>jsonRes == null? null:ComicAuthorItem( id : jsonRes['id'], 61 | name : jsonRes['name'], 62 | cover : jsonRes['cover'], 63 | status : jsonRes['status'], 64 | ); 65 | Map toJson() => { 66 | 'id': _id, 67 | 'name': _name, 68 | 'cover': _cover, 69 | 'status': _status, 70 | }; 71 | 72 | @override 73 | String toString() { 74 | return json.encode(this); 75 | } 76 | } 77 | 78 | 79 | -------------------------------------------------------------------------------- /lib/models/comic/comic_category_detail_filter.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicCategoryDetailFilter { 4 | String _title; 5 | String get title => _title; 6 | List _items; 7 | List get items => _items; 8 | 9 | ComicCategoryDetailFilterItem _item; 10 | ComicCategoryDetailFilterItem get item => _item; 11 | set item(value) { 12 | _item = value; 13 | } 14 | 15 | ComicCategoryDetailFilter({ 16 | String title, 17 | List items, 18 | }):_title=title,_items=items; 19 | factory ComicCategoryDetailFilter.fromJson(jsonRes){ if(jsonRes == null) return null; 20 | List items = jsonRes['items'] is List ? []: null; 21 | if(items!=null) { 22 | for (var item in jsonRes['items']) { if (item != null) { items.add(ComicCategoryDetailFilterItem.fromJson(item)); } 23 | } 24 | } 25 | 26 | 27 | return ComicCategoryDetailFilter( title : jsonRes['title'], 28 | items:items, 29 | );} 30 | Map toJson() => { 31 | 'title': _title, 32 | 'items': _items, 33 | }; 34 | 35 | @override 36 | String toString() { 37 | return json.encode(this); 38 | } 39 | } 40 | class ComicCategoryDetailFilterItem { 41 | int _tag_id; 42 | int get tag_id => _tag_id; 43 | String _tag_name; 44 | String get tag_name => _tag_name; 45 | 46 | ComicCategoryDetailFilterItem({ 47 | int tag_id, 48 | String tag_name, 49 | }):_tag_id=tag_id,_tag_name=tag_name; 50 | factory ComicCategoryDetailFilterItem.fromJson(jsonRes)=>jsonRes == null? null:ComicCategoryDetailFilterItem( tag_id : jsonRes['tag_id'], 51 | tag_name : jsonRes['tag_name'], 52 | ); 53 | Map toJson() => { 54 | 'tag_id': _tag_id, 55 | 'tag_name': _tag_name, 56 | }; 57 | 58 | @override 59 | String toString() { 60 | return json.encode(this); 61 | } 62 | } 63 | 64 | 65 | -------------------------------------------------------------------------------- /lib/models/comic/comic_category_detail_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicCategoryDetailItem { 4 | int _id; 5 | int get id => _id; 6 | String _title; 7 | String get title => _title; 8 | String _authors; 9 | String get authors => _authors; 10 | String _status; 11 | String get status => _status; 12 | String _cover; 13 | String get cover => _cover; 14 | String _types; 15 | String get types => _types; 16 | int _last_updatetime; 17 | int get last_updatetime => _last_updatetime; 18 | int _num; 19 | int get num => _num; 20 | 21 | ComicCategoryDetailItem({ 22 | int id, 23 | String title, 24 | String authors, 25 | String status, 26 | String cover, 27 | String types, 28 | int last_updatetime, 29 | int num, 30 | }):_id=id,_title=title,_authors=authors,_status=status,_cover=cover,_types=types,_last_updatetime=last_updatetime,_num=num; 31 | factory ComicCategoryDetailItem.fromJson(jsonRes)=>jsonRes == null? null:ComicCategoryDetailItem( id : jsonRes['id'], 32 | title : jsonRes['title'], 33 | authors : jsonRes['authors'], 34 | status : jsonRes['status'], 35 | cover : jsonRes['cover'], 36 | types : jsonRes['types'], 37 | last_updatetime : jsonRes['last_updatetime'], 38 | num : jsonRes['num'], 39 | ); 40 | Map toJson() => { 41 | 'id': _id, 42 | 'title': _title, 43 | 'authors': _authors, 44 | 'status': _status, 45 | 'cover': _cover, 46 | 'types': _types, 47 | 'last_updatetime': _last_updatetime, 48 | 'num': _num, 49 | }; 50 | 51 | @override 52 | String toString() { 53 | return json.encode(this); 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /lib/models/comic/comic_category_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicCategoryItem { 4 | int _tag_id; 5 | int get tag_id => _tag_id; 6 | String _title; 7 | String get title => _title; 8 | String _cover; 9 | String get cover => _cover; 10 | 11 | ComicCategoryItem({ 12 | int tag_id, 13 | String title, 14 | String cover, 15 | }):_tag_id=tag_id,_title=title,_cover=cover; 16 | factory ComicCategoryItem.fromJson(jsonRes)=>jsonRes == null? null:ComicCategoryItem( tag_id : jsonRes['tag_id'], 17 | title : jsonRes['title'], 18 | cover : jsonRes['cover'], 19 | ); 20 | Map toJson() => { 21 | 'tag_id': _tag_id, 22 | 'title': _title, 23 | 'cover': _cover, 24 | }; 25 | 26 | @override 27 | String toString() { 28 | return json.encode(this); 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /lib/models/comic/comic_chapter_detail.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicChapterDetail { 4 | int _chapter_id; 5 | int get chapter_id => _chapter_id; 6 | int _comic_id; 7 | int get comic_id => _comic_id; 8 | String _title; 9 | String get title => _title; 10 | int _chapter_order; 11 | int get chapter_order => _chapter_order; 12 | int _direction; 13 | int get direction => _direction; 14 | List _page_url; 15 | List get page_url => _page_url; 16 | int _picnum; 17 | int get picnum => _picnum; 18 | int _comment_count; 19 | int get comment_count => _comment_count; 20 | 21 | ComicChapterDetail({ 22 | int chapter_id, 23 | int comic_id, 24 | String title, 25 | int chapter_order, 26 | int direction, 27 | List page_url, 28 | int picnum, 29 | int comment_count, 30 | }):_chapter_id=chapter_id,_comic_id=comic_id,_title=title,_chapter_order=chapter_order,_direction=direction,_page_url=page_url,_picnum=picnum,_comment_count=comment_count; 31 | factory ComicChapterDetail.fromJson(jsonRes){ if(jsonRes == null) return null; 32 | List page_url = jsonRes['page_url'] is List ? []: null; 33 | if(page_url!=null) { 34 | for (var item in jsonRes['page_url']) { if (item != null) { page_url.add(item); } 35 | } 36 | } 37 | 38 | 39 | return ComicChapterDetail( chapter_id : jsonRes['chapter_id'], 40 | comic_id : jsonRes['comic_id'], 41 | title : jsonRes['title'], 42 | chapter_order : jsonRes['chapter_order'], 43 | direction : jsonRes['direction'], 44 | page_url:page_url, 45 | picnum : jsonRes['picnum'], 46 | comment_count : jsonRes['comment_count'], 47 | );} 48 | Map toJson() => { 49 | 'chapter_id': _chapter_id, 50 | 'comic_id': _comic_id, 51 | 'title': _title, 52 | 'chapter_order': _chapter_order, 53 | 'direction': _direction, 54 | 'page_url': _page_url, 55 | 'picnum': _picnum, 56 | 'comment_count': _comment_count, 57 | }; 58 | 59 | @override 60 | String toString() { 61 | return json.encode(this); 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /lib/models/comic/comic_chapter_view_point.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicChapterViewPoint { 4 | int _id; 5 | int get id => _id; 6 | int _uid; 7 | int get uid => _uid; 8 | String _content; 9 | String get content => _content; 10 | int _num; 11 | int get num => _num; 12 | set num(value) { 13 | _num = value; 14 | } 15 | 16 | int _page; 17 | int get page => _page; 18 | 19 | ComicChapterViewPoint({ 20 | int id, 21 | int uid, 22 | String content, 23 | int num, 24 | int page, 25 | }):_id=id,_uid=uid,_content=content,_num=num,_page=page; 26 | factory ComicChapterViewPoint.fromJson(jsonRes)=>jsonRes == null? null:ComicChapterViewPoint( id : jsonRes['id'], 27 | uid : jsonRes['uid'], 28 | content : jsonRes['content'], 29 | num : jsonRes['num'], 30 | page : jsonRes['page'], 31 | ); 32 | Map toJson() => { 33 | 'id': _id, 34 | 'uid': _uid, 35 | 'content': _content, 36 | 'num': _num, 37 | 'page': _page, 38 | }; 39 | 40 | @override 41 | String toString() { 42 | return json.encode(this); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /lib/models/comic/comic_history_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicHistoryItem { 4 | int _uid; 5 | int get uid => _uid; 6 | int _type; 7 | int get type => _type; 8 | int _comic_id; 9 | int get comic_id => _comic_id; 10 | int _chapter_id; 11 | int get chapter_id => _chapter_id??0; 12 | int _record; 13 | int get record => _record; 14 | int _viewing_time; 15 | int get viewing_time => _viewing_time??946656001; 16 | String _comic_name; 17 | String get comic_name => _comic_name; 18 | String _cover; 19 | String get cover => _cover; 20 | String _chapter_name=""; 21 | String get chapter_name => _chapter_name??""; 22 | int _progress; 23 | int get progress => _progress; 24 | set progress(value) { 25 | _progress = value; 26 | } 27 | 28 | 29 | ComicHistoryItem({ 30 | int uid, 31 | int type, 32 | int comic_id, 33 | int chapter_id, 34 | int record, 35 | int viewing_time, 36 | String comic_name, 37 | String cover, 38 | String chapter_name, 39 | int progress, 40 | }):_uid=uid,_type=type,_comic_id=comic_id,_chapter_id=chapter_id,_record=record,_viewing_time=viewing_time,_comic_name=comic_name,_cover=cover,_chapter_name=chapter_name,_progress=progress; 41 | factory ComicHistoryItem.fromJson(jsonRes)=>jsonRes == null? null:ComicHistoryItem( uid : jsonRes['uid'], 42 | type : jsonRes['type'], 43 | comic_id : jsonRes['comic_id'], 44 | chapter_id : jsonRes['chapter_id'], 45 | record : jsonRes['record'], 46 | viewing_time : jsonRes['viewing_time'], 47 | comic_name : jsonRes['comic_name'], 48 | cover : jsonRes['cover'], 49 | chapter_name : jsonRes['chapter_name'], 50 | progress : jsonRes['progress'], 51 | ); 52 | Map toJson() => { 53 | 'uid': _uid, 54 | 'type': _type, 55 | 'comic_id': _comic_id, 56 | 'chapter_id': _chapter_id, 57 | 'record': _record, 58 | 'viewing_time': _viewing_time, 59 | 'comic_name': _comic_name, 60 | 'cover': _cover, 61 | 'chapter_name': _chapter_name, 62 | 'progress': _progress, 63 | }; 64 | 65 | @override 66 | String toString() { 67 | return json.encode(this); 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /lib/models/comic/comic_home_banner_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicHomeBannerItem { 4 | String cover; 5 | String title; 6 | String sub_title; 7 | int type; 8 | String url; 9 | int obj_id; 10 | String status; 11 | 12 | int get id => obj_id; 13 | 14 | 15 | ComicHomeBannerItem({ 16 | this.cover, 17 | this.title, 18 | this.sub_title, 19 | this.type, 20 | this.url, 21 | this.obj_id, 22 | this.status, 23 | }); 24 | 25 | 26 | factory ComicHomeBannerItem.fromJson(jsonRes)=>jsonRes == null? null:ComicHomeBannerItem( cover : jsonRes['cover'], 27 | title : jsonRes['title'], 28 | sub_title : jsonRes['sub_title'], 29 | type : jsonRes['type'], 30 | url : jsonRes['url'], 31 | obj_id : jsonRes['obj_id'], 32 | status : jsonRes['status'], 33 | ); 34 | Map toJson() => { 35 | 'cover': cover, 36 | 'title': title, 37 | 'sub_title': sub_title, 38 | 'type': type, 39 | 'url': url, 40 | 'obj_id': obj_id, 41 | 'status': status, 42 | }; 43 | 44 | @override 45 | String toString() { 46 | return json.encode(this); 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /lib/models/comic/comic_home_comic_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicHomeComicItem { 4 | String cover; 5 | String title; 6 | String sub_title; 7 | int type; 8 | String url; 9 | int obj_id; 10 | String status; 11 | int get id => obj_id; 12 | ComicHomeComicItem({ 13 | this.cover, 14 | this.title, 15 | this.sub_title, 16 | this.type, 17 | this.url, 18 | this.obj_id, 19 | this.status, 20 | }); 21 | 22 | 23 | factory ComicHomeComicItem.fromJson(jsonRes)=>jsonRes == null? null:ComicHomeComicItem( cover : jsonRes['cover'], 24 | title : jsonRes['title'], 25 | sub_title : jsonRes['sub_title'], 26 | type : jsonRes['type'], 27 | url : jsonRes['url'], 28 | obj_id : jsonRes['obj_id'], 29 | status : jsonRes['status'], 30 | ); 31 | Map toJson() => { 32 | 'cover': cover, 33 | 'title': title, 34 | 'sub_title': sub_title, 35 | 'type': type, 36 | 'url': url, 37 | 'obj_id': obj_id, 38 | 'status': status, 39 | }; 40 | 41 | @override 42 | String toString() { 43 | return json.encode(this); 44 | } 45 | } 46 | 47 | -------------------------------------------------------------------------------- /lib/models/comic/comic_home_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicHomeItem { 4 | int category_id; 5 | String title; 6 | int sort; 7 | List data; 8 | 9 | ComicHomeItem({ 10 | this.category_id, 11 | this.title, 12 | this.sort, 13 | this.data, 14 | }); 15 | 16 | 17 | factory ComicHomeItem.fromJson(jsonRes){ if(jsonRes == null) return null; 18 | List data = jsonRes['data'] is List ? []: null; 19 | if(data!=null) { 20 | for (var item in jsonRes['data']) { if (item != null) { data.add(item); } 21 | } 22 | } 23 | 24 | 25 | return ComicHomeItem( category_id : jsonRes['category_id'], 26 | title : jsonRes['title'], 27 | sort : jsonRes['sort'], 28 | data:data, 29 | );} 30 | Map toJson() => { 31 | 'category_id': category_id, 32 | 'title': title, 33 | 'sort': sort, 34 | 'data': data, 35 | }; 36 | 37 | @override 38 | String toString() { 39 | return json.encode(this); 40 | } 41 | } 42 | 43 | -------------------------------------------------------------------------------- /lib/models/comic/comic_home_new_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicHomeNewItem { 4 | int id; 5 | String title; 6 | String authors; 7 | String status; 8 | String cover; 9 | int get type => 1; 10 | String get url => ""; 11 | ComicHomeNewItem({ 12 | this.id, 13 | this.title, 14 | this.authors, 15 | this.status, 16 | this.cover, 17 | }); 18 | 19 | 20 | factory ComicHomeNewItem.fromJson(jsonRes)=>jsonRes == null? null:ComicHomeNewItem( id : jsonRes['id'], 21 | title : jsonRes['title'], 22 | authors : jsonRes['authors'], 23 | status : jsonRes['status'], 24 | cover : jsonRes['cover'], 25 | ); 26 | Map toJson() => { 27 | 'id': id, 28 | 'title': title, 29 | 'authors': authors, 30 | 'status': status, 31 | 'cover': cover, 32 | }; 33 | 34 | @override 35 | String toString() { 36 | return json.encode(this); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /lib/models/comic/comic_ns_search_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicNSSearchItem { 4 | int _id; 5 | int get id => _id; 6 | String _title; 7 | String get title => _title; 8 | String _desc; 9 | String get desc => _desc; 10 | String _author; 11 | String get author => _author; 12 | String _cover; 13 | String get cover => _cover; 14 | String _status; 15 | String get status => _status; 16 | String _web; 17 | String get web => _web; 18 | String _ios; 19 | String get ios => _ios; 20 | String _android; 21 | String get android => _android; 22 | String _uwp; 23 | String get uwp => _uwp; 24 | 25 | ComicNSSearchItem({ 26 | int id, 27 | String title, 28 | String desc, 29 | String author, 30 | String cover, 31 | String status, 32 | String web, 33 | String ios, 34 | String android, 35 | String uwp, 36 | }):_id=id,_title=title,_desc=desc,_author=author,_cover=cover,_status=status,_web=web,_ios=ios,_android=android,_uwp=uwp; 37 | ComicNSSearchItem.sacg({ 38 | int id, 39 | String cover, 40 | String title, 41 | String author, 42 | String status, 43 | }) : _id = id, 44 | _cover = cover, 45 | _title = title, 46 | _author = author, 47 | _status = status; 48 | factory ComicNSSearchItem.fromJson(jsonRes)=>jsonRes == null? null:ComicNSSearchItem( id : jsonRes['id'], 49 | title : jsonRes['title'], 50 | desc : jsonRes['desc'], 51 | author : jsonRes['author'], 52 | cover : jsonRes['cover'], 53 | status : jsonRes['status'], 54 | web : jsonRes['web'], 55 | ios : jsonRes['ios'], 56 | android : jsonRes['android'], 57 | uwp : jsonRes['uwp'], 58 | ); 59 | factory ComicNSSearchItem.fromJson2(jsonRes) { 60 | if (jsonRes == null) return null; 61 | String status = jsonRes['status']; 62 | if (status.isEmpty) 63 | status = "连载中"; 64 | else 65 | status = "已完结"; 66 | return ComicNSSearchItem.sacg( 67 | id: jsonRes['id'], 68 | title: jsonRes['comic_name'], 69 | author: jsonRes['comic_author'], 70 | cover: jsonRes['comic_cover'], 71 | status: status, 72 | ); 73 | } 74 | Map toJson() => { 75 | 'id': _id, 76 | 'title': _title, 77 | 'desc': _desc, 78 | 'author': _author, 79 | 'cover': _cover, 80 | 'status': _status, 81 | 'web': _web, 82 | 'ios': _ios, 83 | 'android': _android, 84 | 'uwp': _uwp, 85 | }; 86 | 87 | @override 88 | String toString() { 89 | return json.encode(this); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /lib/models/comic/comic_rank_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicRankItem { 4 | String _comic_id; 5 | String get comic_id => _comic_id; 6 | set comic_id(value) { 7 | _comic_id = value; 8 | } 9 | 10 | String _title; 11 | String get title => _title; 12 | set title(value) { 13 | _title = value; 14 | } 15 | 16 | String _authors; 17 | String get authors => _authors; 18 | set authors(value) { 19 | _authors = value; 20 | } 21 | 22 | String _status; 23 | String get status => _status; 24 | set status(value) { 25 | _status = value; 26 | } 27 | 28 | String _cover; 29 | String get cover => _cover; 30 | set cover(value) { 31 | _cover = value; 32 | } 33 | 34 | String _types; 35 | String get types => _types; 36 | set types(value) { 37 | _types = value; 38 | } 39 | 40 | String _last_updatetime; 41 | String get last_updatetime => _last_updatetime; 42 | set last_updatetime(value) { 43 | _last_updatetime = value; 44 | } 45 | 46 | String _last_update_chapter_name; 47 | String get last_update_chapter_name => _last_update_chapter_name; 48 | set last_update_chapter_name(value) { 49 | _last_update_chapter_name = value; 50 | } 51 | 52 | String _comic_py; 53 | String get comic_py => _comic_py; 54 | set comic_py(value) { 55 | _comic_py = value; 56 | } 57 | 58 | String _num; 59 | String get num => _num; 60 | set num(value) { 61 | _num = value; 62 | } 63 | 64 | String _tag_id; 65 | String get tag_id => _tag_id; 66 | set tag_id(value) { 67 | _tag_id = value; 68 | } 69 | 70 | 71 | ComicRankItem({ 72 | String comic_id, 73 | String title, 74 | String authors, 75 | String status, 76 | String cover, 77 | String types, 78 | String last_updatetime, 79 | String last_update_chapter_name, 80 | String comic_py, 81 | String num, 82 | String tag_id, 83 | }):_comic_id=comic_id,_title=title,_authors=authors,_status=status,_cover=cover,_types=types,_last_updatetime=last_updatetime,_last_update_chapter_name=last_update_chapter_name,_comic_py=comic_py,_num=num,_tag_id=tag_id; 84 | factory ComicRankItem.fromJson(jsonRes)=>jsonRes == null? null:ComicRankItem( comic_id : jsonRes['comic_id'], 85 | title : jsonRes['title'], 86 | authors : jsonRes['authors'], 87 | status : jsonRes['status'], 88 | cover : jsonRes['cover'], 89 | types : jsonRes['types'], 90 | last_updatetime : jsonRes['last_updatetime'], 91 | last_update_chapter_name : jsonRes['last_update_chapter_name'], 92 | comic_py : jsonRes['comic_py'], 93 | num : jsonRes['num'].toString(), 94 | tag_id : jsonRes['tag_id'], 95 | ); 96 | Map toJson() => { 97 | 'comic_id': _comic_id, 98 | 'title': _title, 99 | 'authors': _authors, 100 | 'status': _status, 101 | 'cover': _cover, 102 | 'types': _types, 103 | 'last_updatetime': _last_updatetime, 104 | 'last_update_chapter_name': _last_update_chapter_name, 105 | 'comic_py': _comic_py, 106 | 'num': _num, 107 | 'tag_id': _tag_id, 108 | }; 109 | 110 | @override 111 | String toString() { 112 | return json.encode(this); 113 | } 114 | } 115 | 116 | -------------------------------------------------------------------------------- /lib/models/comic/comic_related_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicRelated { 4 | List _author_comics; 5 | List get author_comics => _author_comics; 6 | List _theme_comics; 7 | List get theme_comics => _theme_comics; 8 | List _novels; 9 | List get novels => _novels; 10 | 11 | ComicRelated({ 12 | List author_comics, 13 | List theme_comics, 14 | List novels, 15 | }):_author_comics=author_comics,_theme_comics=theme_comics,_novels=novels; 16 | factory ComicRelated.fromJson(jsonRes){ if(jsonRes == null) return null; 17 | List author_comics = jsonRes['author_comics'] is List ? []: null; 18 | if(author_comics!=null) { 19 | for (var item in jsonRes['author_comics']) { if (item != null) { author_comics.add(ComicRelatedAuthorComics.fromJson(item)); } 20 | } 21 | } 22 | 23 | 24 | List theme_comics = jsonRes['theme_comics'] is List ? []: null; 25 | if(theme_comics!=null) { 26 | for (var item in jsonRes['theme_comics']) { if (item != null) { theme_comics.add(ComicRelatedItem.fromJson(item)); } 27 | } 28 | } 29 | 30 | 31 | List novels = jsonRes['novels'] is List ? []: null; 32 | if(novels!=null) { 33 | for (var item in jsonRes['novels']) { if (item != null) { novels.add(ComicRelatedItem.fromJson(item)); } 34 | } 35 | } 36 | 37 | 38 | return ComicRelated( author_comics:author_comics, 39 | theme_comics:theme_comics, 40 | novels:novels, 41 | );} 42 | Map toJson() => { 43 | 'author_comics': _author_comics, 44 | 'theme_comics': _theme_comics, 45 | 'novels': _novels, 46 | }; 47 | 48 | @override 49 | String toString() { 50 | return json.encode(this); 51 | } 52 | } 53 | class ComicRelatedAuthorComics { 54 | String _author_name; 55 | String get author_name => _author_name; 56 | int _author_id; 57 | int get author_id => _author_id; 58 | List _data; 59 | List get data => _data; 60 | 61 | ComicRelatedAuthorComics({ 62 | String author_name, 63 | int author_id, 64 | List data, 65 | }):_author_name=author_name,_author_id=author_id,_data=data; 66 | factory ComicRelatedAuthorComics.fromJson(jsonRes){ if(jsonRes == null) return null; 67 | List data = jsonRes['data'] is List ? []: null; 68 | if(data!=null) { 69 | for (var item in jsonRes['data']) { if (item != null) { data.add(ComicRelatedItem.fromJson(item)); } 70 | } 71 | } 72 | 73 | 74 | return ComicRelatedAuthorComics( author_name : jsonRes['author_name'], 75 | author_id : jsonRes['author_id'], 76 | data:data, 77 | );} 78 | Map toJson() => { 79 | 'author_name': _author_name, 80 | 'author_id': _author_id, 81 | 'data': _data, 82 | }; 83 | 84 | @override 85 | String toString() { 86 | return json.encode(this); 87 | } 88 | } 89 | class ComicRelatedItem { 90 | int _id; 91 | int get id => _id; 92 | String _name; 93 | String get name => _name; 94 | String _cover; 95 | String get cover => _cover; 96 | String _status; 97 | String get status => _status; 98 | 99 | ComicRelatedItem({ 100 | int id, 101 | String name, 102 | String cover, 103 | String status, 104 | }):_id=id,_name=name,_cover=cover,_status=status; 105 | factory ComicRelatedItem.fromJson(jsonRes)=>jsonRes == null? null:ComicRelatedItem( id : jsonRes['id'], 106 | name : jsonRes['name'], 107 | cover : jsonRes['cover'], 108 | status : jsonRes['status'], 109 | ); 110 | Map toJson() => { 111 | 'id': _id, 112 | 'name': _name, 113 | 'cover': _cover, 114 | 'status': _status, 115 | }; 116 | 117 | @override 118 | String toString() { 119 | return json.encode(this); 120 | } 121 | } 122 | 123 | -------------------------------------------------------------------------------- /lib/models/comic/comic_specia_datail_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicSpecia { 4 | String _mobile_header_pic; 5 | String get mobile_header_pic => _mobile_header_pic; 6 | String _title; 7 | String get title => _title; 8 | String _page_url; 9 | String get page_url => _page_url; 10 | String _description; 11 | String get description => _description; 12 | List _comics; 13 | List get comics => _comics; 14 | int _comment_amount; 15 | int get comment_amount => _comment_amount; 16 | 17 | ComicSpecia({ 18 | String mobile_header_pic, 19 | String title, 20 | String page_url, 21 | String description, 22 | List comics, 23 | int comment_amount, 24 | }):_mobile_header_pic=mobile_header_pic,_title=title,_page_url=page_url,_description=description,_comics=comics,_comment_amount=comment_amount; 25 | factory ComicSpecia.fromJson(jsonRes){ if(jsonRes == null) return null; 26 | List comics = jsonRes['comics'] is List ? []: null; 27 | if(comics!=null) { 28 | for (var item in jsonRes['comics']) { if (item != null) { comics.add(ComicSpeciaItem.fromJson(item)); } 29 | } 30 | } 31 | 32 | 33 | return ComicSpecia( mobile_header_pic : jsonRes['mobile_header_pic'], 34 | title : jsonRes['title'], 35 | page_url : jsonRes['page_url'], 36 | description : jsonRes['description'], 37 | comics:comics, 38 | comment_amount : jsonRes['comment_amount'], 39 | );} 40 | Map toJson() => { 41 | 'mobile_header_pic': _mobile_header_pic, 42 | 'title': _title, 43 | 'page_url': _page_url, 44 | 'description': _description, 45 | 'comics': _comics, 46 | 'comment_amount': _comment_amount, 47 | }; 48 | 49 | @override 50 | String toString() { 51 | return json.encode(this); 52 | } 53 | } 54 | class ComicSpeciaItem { 55 | String _cover; 56 | String get cover => _cover; 57 | String _recommend_brief; 58 | String get recommend_brief => _recommend_brief; 59 | String _recommend_reason; 60 | String get recommend_reason => _recommend_reason; 61 | int _id; 62 | int get id => _id; 63 | String _name; 64 | String get name => _name; 65 | String _alias_name; 66 | String get alias_name => _alias_name; 67 | 68 | ComicSpeciaItem({ 69 | String cover, 70 | String recommend_brief, 71 | String recommend_reason, 72 | int id, 73 | String name, 74 | String alias_name, 75 | }):_cover=cover,_recommend_brief=recommend_brief,_recommend_reason=recommend_reason,_id=id,_name=name,_alias_name=alias_name; 76 | factory ComicSpeciaItem.fromJson(jsonRes)=>jsonRes == null? null:ComicSpeciaItem( cover : jsonRes['cover'], 77 | recommend_brief : jsonRes['recommend_brief'], 78 | recommend_reason : jsonRes['recommend_reason'], 79 | id : jsonRes['id'], 80 | name : jsonRes['name'], 81 | alias_name : jsonRes['alias_name'], 82 | ); 83 | Map toJson() => { 84 | 'cover': _cover, 85 | 'recommend_brief': _recommend_brief, 86 | 'recommend_reason': _recommend_reason, 87 | 'id': _id, 88 | 'name': _name, 89 | 'alias_name': _alias_name, 90 | }; 91 | 92 | @override 93 | String toString() { 94 | return json.encode(this); 95 | } 96 | } 97 | 98 | 99 | -------------------------------------------------------------------------------- /lib/models/comic/comic_special_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class ComicSpecialItem { 4 | int _id; 5 | int get id => _id; 6 | String _title; 7 | String get title => _title; 8 | String _short_title; 9 | String get short_title => _short_title; 10 | int _create_time; 11 | int get create_time => _create_time; 12 | String _small_cover; 13 | String get small_cover => _small_cover; 14 | int _page_type; 15 | int get page_type => _page_type; 16 | int _sort; 17 | int get sort => _sort; 18 | String _page_url; 19 | String get page_url => _page_url; 20 | 21 | ComicSpecialItem({ 22 | int id, 23 | String title, 24 | String short_title, 25 | int create_time, 26 | String small_cover, 27 | int page_type, 28 | int sort, 29 | String page_url, 30 | }):_id=id,_title=title,_short_title=short_title,_create_time=create_time,_small_cover=small_cover,_page_type=page_type,_sort=sort,_page_url=page_url; 31 | factory ComicSpecialItem.fromJson(jsonRes)=>jsonRes == null? null:ComicSpecialItem( id : jsonRes['id'], 32 | title : jsonRes['title'], 33 | short_title : jsonRes['short_title'], 34 | create_time : jsonRes['create_time'], 35 | small_cover : jsonRes['small_cover'], 36 | page_type : jsonRes['page_type'], 37 | sort : jsonRes['sort'], 38 | page_url : jsonRes['page_url'], 39 | ); 40 | Map toJson() => { 41 | 'id': _id, 42 | 'title': _title, 43 | 'short_title': _short_title, 44 | 'create_time': _create_time, 45 | 'small_cover': _small_cover, 46 | 'page_type': _page_type, 47 | 'sort': _sort, 48 | 'page_url': _page_url, 49 | }; 50 | 51 | @override 52 | String toString() { 53 | return json.encode(this); 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /lib/models/news/new_list_item_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NewsListItemModel { 4 | String title; 5 | String from_name; 6 | String from_url; 7 | int create_time; 8 | int is_foreign; 9 | String foreign_url; 10 | String intro; 11 | int author_id; 12 | int status; 13 | String row_pic_url; 14 | String col_pic_url; 15 | int article_id; 16 | String page_url; 17 | int comment_amount; 18 | int author_uid; 19 | String cover; 20 | String nickname; 21 | int mood_amount; 22 | get time=>DateTime.fromMillisecondsSinceEpoch(create_time*1000); 23 | NewsListItemModel({ 24 | this.title, 25 | this.from_name, 26 | this.from_url, 27 | this.create_time, 28 | this.is_foreign, 29 | this.foreign_url, 30 | this.intro, 31 | this.author_id, 32 | this.status, 33 | this.row_pic_url, 34 | this.col_pic_url, 35 | this.article_id, 36 | this.page_url, 37 | this.comment_amount, 38 | this.author_uid, 39 | this.cover, 40 | this.nickname, 41 | this.mood_amount, 42 | }); 43 | 44 | 45 | factory NewsListItemModel.fromJson(jsonRes)=>jsonRes == null? null:NewsListItemModel( title : jsonRes['title'], 46 | from_name : jsonRes['from_name'], 47 | from_url : jsonRes['from_url'], 48 | create_time : jsonRes['create_time'], 49 | is_foreign : jsonRes['is_foreign'], 50 | foreign_url : jsonRes['foreign_url'], 51 | intro : jsonRes['intro'], 52 | author_id : jsonRes['author_id'], 53 | status : jsonRes['status'], 54 | row_pic_url : jsonRes['row_pic_url'], 55 | col_pic_url : jsonRes['col_pic_url'], 56 | article_id : jsonRes['article_id'], 57 | page_url : jsonRes['page_url'], 58 | //动漫之家后端,随机返回String或者Int,简直牛批,必须判断类型 59 | comment_amount : (jsonRes['comment_amount'] is String)?int.parse(jsonRes['comment_amount']):jsonRes['comment_amount'], 60 | author_uid : jsonRes['author_uid'], 61 | cover : jsonRes['cover'], 62 | nickname : jsonRes['nickname'], 63 | mood_amount : jsonRes['mood_amount'], 64 | ); 65 | Map toJson() => { 66 | 'title': title, 67 | 'from_name': from_name, 68 | 'from_url': from_url, 69 | 'create_time': create_time, 70 | 'is_foreign': is_foreign, 71 | 'foreign_url': foreign_url, 72 | 'intro': intro, 73 | 'author_id': author_id, 74 | 'status': status, 75 | 'row_pic_url': row_pic_url, 76 | 'col_pic_url': col_pic_url, 77 | 'article_id': article_id, 78 | 'page_url': page_url, 79 | 'comment_amount': comment_amount, 80 | 'author_uid': author_uid, 81 | 'cover': cover, 82 | 'nickname': nickname, 83 | 'mood_amount': mood_amount, 84 | }; 85 | 86 | @override 87 | String toString() { 88 | return json.encode(this); 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /lib/models/news/news_banner_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NewsBannerModel { 4 | int code; 5 | String msg; 6 | List data; 7 | 8 | NewsBannerModel({ 9 | this.code, 10 | this.msg, 11 | this.data, 12 | }); 13 | 14 | 15 | factory NewsBannerModel.fromJson(jsonRes){ if(jsonRes == null) return null; 16 | List data = jsonRes['data'] is List ? []: null; 17 | if(data!=null) { 18 | for (var item in jsonRes['data']) { if (item != null) { data.add(NewsBannerItemModel.fromJson(item)); } 19 | } 20 | } 21 | 22 | 23 | return NewsBannerModel( code : jsonRes['code'], 24 | msg : jsonRes['msg'], 25 | data:data, 26 | );} 27 | Map toJson() => { 28 | 'code': code, 29 | 'msg': msg, 30 | 'data': data, 31 | }; 32 | 33 | @override 34 | String toString() { 35 | return json.encode(this); 36 | } 37 | } 38 | class NewsBannerItemModel { 39 | int id; 40 | String title; 41 | String pic_url; 42 | int object_id; 43 | String object_url; 44 | 45 | NewsBannerItemModel({ 46 | this.id, 47 | this.title, 48 | this.pic_url, 49 | this.object_id, 50 | this.object_url, 51 | }); 52 | 53 | 54 | factory NewsBannerItemModel.fromJson(jsonRes)=>jsonRes == null? null:NewsBannerItemModel( id : jsonRes['id'], 55 | title : jsonRes['title'], 56 | pic_url : jsonRes['pic_url'], 57 | object_id : jsonRes['object_id'], 58 | object_url : jsonRes['object_url'], 59 | ); 60 | Map toJson() => { 61 | 'id': id, 62 | 'title': title, 63 | 'pic_url': pic_url, 64 | 'object_id': object_id, 65 | 'object_url': object_url, 66 | }; 67 | 68 | @override 69 | String toString() { 70 | return json.encode(this); 71 | } 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /lib/models/news/news_stat_detail.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NewsStatDetail { 4 | String _comment_amount="0"; 5 | String get comment_amount => _comment_amount; 6 | set comment_amount(value) { 7 | var v= int.tryParse(value,radix: 0); 8 | _comment_amount = v.toString(); 9 | } 10 | 11 | int _mood_amount=0; 12 | int get mood_amount => _mood_amount; 13 | set mood_amount(value) { 14 | _mood_amount = value; 15 | } 16 | 17 | String _row_pic_url; 18 | String get row_pic_url => _row_pic_url; 19 | set row_pic_url(value) { 20 | _row_pic_url = value; 21 | } 22 | 23 | String _title; 24 | String get title => _title; 25 | set title(value) { 26 | _title = value; 27 | } 28 | 29 | 30 | NewsStatDetail({ 31 | String comment_amount, 32 | int mood_amount, 33 | String row_pic_url, 34 | String title, 35 | }):_comment_amount=comment_amount,_mood_amount=mood_amount,_row_pic_url=row_pic_url,_title=title; 36 | factory NewsStatDetail.fromJson(jsonRes)=>jsonRes == null? null:NewsStatDetail( comment_amount : jsonRes['comment_amount'], 37 | mood_amount : jsonRes['mood_amount'], 38 | row_pic_url : jsonRes['row_pic_url'], 39 | title : jsonRes['title'], 40 | ); 41 | Map toJson() => { 42 | 'comment_amount': _comment_amount, 43 | 'mood_amount': _mood_amount, 44 | 'row_pic_url': _row_pic_url, 45 | 'title': _title, 46 | }; 47 | 48 | @override 49 | String toString() { 50 | return json.encode(this); 51 | } 52 | } 53 | 54 | -------------------------------------------------------------------------------- /lib/models/news/news_tag_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NewsTagItemModel { 4 | int tag_id; 5 | String tag_name; 6 | 7 | NewsTagItemModel({ 8 | this.tag_id, 9 | this.tag_name, 10 | }); 11 | 12 | 13 | factory NewsTagItemModel.fromJson(jsonRes)=>jsonRes == null? null:NewsTagItemModel( tag_id : jsonRes['tag_id'], 14 | tag_name : jsonRes['tag_name'], 15 | ); 16 | Map toJson() => { 17 | 'tag_id': tag_id, 18 | 'tag_name': tag_name, 19 | }; 20 | 21 | @override 22 | String toString() { 23 | return json.encode(this); 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /lib/models/novel/novel_category_detail_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NovelCategoryDetailItem { 4 | String _cover; 5 | String get cover => _cover; 6 | String _name; 7 | String get name => _name; 8 | String _authors; 9 | String get authors => _authors; 10 | int _id; 11 | int get id => _id; 12 | 13 | NovelCategoryDetailItem({ 14 | String cover, 15 | String name, 16 | String authors, 17 | int id, 18 | }):_cover=cover,_name=name,_authors=authors,_id=id; 19 | factory NovelCategoryDetailItem.fromJson(jsonRes)=>jsonRes == null? null:NovelCategoryDetailItem( cover : jsonRes['cover'], 20 | name : jsonRes['name'], 21 | authors : jsonRes['authors'], 22 | id : jsonRes['id'], 23 | ); 24 | Map toJson() => { 25 | 'cover': _cover, 26 | 'name': _name, 27 | 'authors': _authors, 28 | 'id': _id, 29 | }; 30 | 31 | @override 32 | String toString() { 33 | return json.encode(this); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /lib/models/novel/novel_history_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NovelHistoryItem { 4 | int uid; 5 | int type; 6 | String lnovel_id; 7 | int volume_id; 8 | int chapter_id; 9 | int record; 10 | int viewing_time; 11 | int total_num; 12 | String cover; 13 | String novel_name; 14 | String volume_name; 15 | String chapter_name; 16 | 17 | NovelHistoryItem({ 18 | this.uid, 19 | this.type, 20 | this.lnovel_id, 21 | this.volume_id, 22 | this.chapter_id, 23 | this.record, 24 | this.viewing_time, 25 | this.total_num, 26 | this.cover, 27 | this.novel_name, 28 | this.volume_name, 29 | this.chapter_name, 30 | }); 31 | 32 | 33 | factory NovelHistoryItem.fromJson(jsonRes)=>jsonRes == null? null:NovelHistoryItem( uid : jsonRes['uid'], 34 | type : jsonRes['type'], 35 | lnovel_id : jsonRes['lnovel_id'], 36 | volume_id : jsonRes['volume_id'], 37 | chapter_id : jsonRes['chapter_id'], 38 | record : jsonRes['record'], 39 | viewing_time : jsonRes['viewing_time'], 40 | total_num : jsonRes['total_num'], 41 | cover : jsonRes['cover'], 42 | novel_name : jsonRes['novel_name'], 43 | volume_name : jsonRes['volume_name'], 44 | chapter_name : jsonRes['chapter_name'], 45 | ); 46 | Map toJson() => { 47 | 'uid': uid, 48 | 'type': type, 49 | 'lnovel_id': lnovel_id, 50 | 'volume_id': volume_id, 51 | 'chapter_id': chapter_id, 52 | 'record': record, 53 | 'viewing_time': viewing_time, 54 | 'total_num': total_num, 55 | 'cover': cover, 56 | 'novel_name': novel_name, 57 | 'volume_name': volume_name, 58 | 'chapter_name': chapter_name, 59 | }; 60 | 61 | @override 62 | String toString() { 63 | return json.encode(this); 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /lib/models/novel/novel_rank_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NovelRankItem { 4 | int _id; 5 | int get id => _id; 6 | int _last_update_time; 7 | int get last_update_time => _last_update_time; 8 | String _name; 9 | String get name => _name; 10 | List _types; 11 | List get types => _types; 12 | String get type{ 13 | if(_types==null||_types.length==0){ 14 | return ""; 15 | } 16 | var str=""; 17 | for (var item in _types) { 18 | str+=item+" "; 19 | } 20 | return str; 21 | } 22 | String _cover; 23 | String get cover => _cover; 24 | String _authors; 25 | String get authors => _authors; 26 | String _last_update_chapter_name; 27 | String get last_update_chapter_name => _last_update_chapter_name; 28 | int _top; 29 | int get top => _top; 30 | int _subscribe_amount; 31 | int get subscribe_amount => _subscribe_amount; 32 | 33 | NovelRankItem({ 34 | int id, 35 | int last_update_time, 36 | String name, 37 | List types, 38 | String cover, 39 | String authors, 40 | String last_update_chapter_name, 41 | int top, 42 | int subscribe_amount, 43 | }):_id=id,_last_update_time=last_update_time,_name=name,_types=types,_cover=cover,_authors=authors,_last_update_chapter_name=last_update_chapter_name,_top=top,_subscribe_amount=subscribe_amount; 44 | factory NovelRankItem.fromJson(jsonRes){ if(jsonRes == null) return null; 45 | List types = jsonRes['types'] is List ? []: null; 46 | if(types!=null) { 47 | for (var item in jsonRes['types']) { if (item != null) { types.add(item); } 48 | } 49 | } 50 | 51 | 52 | return NovelRankItem( id : jsonRes['id'], 53 | last_update_time : jsonRes['last_update_time'], 54 | name : jsonRes['name'], 55 | types:types, 56 | cover : jsonRes['cover'], 57 | authors : jsonRes['authors'], 58 | last_update_chapter_name : jsonRes['last_update_chapter_name'], 59 | top : jsonRes['top'], 60 | subscribe_amount : jsonRes['subscribe_amount'], 61 | );} 62 | Map toJson() => { 63 | 'id': _id, 64 | 'last_update_time': _last_update_time, 65 | 'name': _name, 66 | 'types': _types, 67 | 'cover': _cover, 68 | 'authors': _authors, 69 | 'last_update_chapter_name': _last_update_chapter_name, 70 | 'top': _top, 71 | 'subscribe_amount': _subscribe_amount, 72 | }; 73 | 74 | @override 75 | String toString() { 76 | return json.encode(this); 77 | } 78 | } 79 | 80 | -------------------------------------------------------------------------------- /lib/models/novel/novel_search_result_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NovelSearchResultItem { 4 | 5 | int _addtime; 6 | int get addtime => _addtime; 7 | String _authors; 8 | String get authors => _authors; 9 | int _copyright; 10 | int get copyright => _copyright; 11 | String _cover; 12 | String get cover => _cover; 13 | int _hot_hits; 14 | int get hot_hits => _hot_hits; 15 | String _last_name; 16 | String get last_name => _last_name; 17 | int _status; 18 | int get status => _status; 19 | String _title; 20 | String get title => _title; 21 | String _types; 22 | String get types => _types; 23 | int _id; 24 | int get id => _id; 25 | 26 | NovelSearchResultItem({ 27 | 28 | int addtime, 29 | String authors, 30 | int copyright, 31 | String cover, 32 | int hot_hits, 33 | String last_name, 34 | int status, 35 | String title, 36 | String types, 37 | int id, 38 | }):_addtime=addtime,_authors=authors,_copyright=copyright,_cover=cover,_hot_hits=hot_hits,_last_name=last_name,_status=status,_title=title,_types=types,_id=id; 39 | factory NovelSearchResultItem.fromJson(jsonRes)=>jsonRes == null? null:NovelSearchResultItem( 40 | addtime : jsonRes['addtime'], 41 | authors : jsonRes['authors'], 42 | copyright : jsonRes['copyright'], 43 | cover : jsonRes['cover'], 44 | hot_hits : jsonRes['hot_hits'], 45 | last_name : jsonRes['last_name'], 46 | status : jsonRes['status'], 47 | title : jsonRes['title'], 48 | types : jsonRes['types'], 49 | id : jsonRes['id'], 50 | ); 51 | Map toJson() => { 52 | 'addtime': _addtime, 53 | 'authors': _authors, 54 | 'copyright': _copyright, 55 | 'cover': _cover, 56 | 'hot_hits': _hot_hits, 57 | 'last_name': _last_name, 58 | 'status': _status, 59 | 'title': _title, 60 | 'types': _types, 61 | 'id': _id, 62 | }; 63 | 64 | @override 65 | String toString() { 66 | return json.encode(this); 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /lib/models/novel/novel_update_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NovelUpdateItem { 4 | int _id; 5 | int get id => _id; 6 | String _status; 7 | String get status => _status; 8 | String _name; 9 | String get name => _name; 10 | String _authors; 11 | String get authors => _authors; 12 | String _cover; 13 | String get cover => _cover; 14 | List _types; 15 | List get types => _types; 16 | 17 | String get type{ 18 | if(_types==null||_types.length==0){ 19 | return ""; 20 | } 21 | var str=""; 22 | for (var item in _types) { 23 | str+=item+" "; 24 | } 25 | return str; 26 | } 27 | 28 | int _last_update_chapter_id; 29 | int get last_update_chapter_id => _last_update_chapter_id; 30 | int _last_update_volume_id; 31 | int get last_update_volume_id => _last_update_volume_id; 32 | String _last_update_volume_name; 33 | String get last_update_volume_name => _last_update_volume_name; 34 | String _last_update_chapter_name; 35 | String get last_update_chapter_name => _last_update_chapter_name; 36 | int _last_update_time; 37 | int get last_update_time => _last_update_time; 38 | 39 | NovelUpdateItem({ 40 | int id, 41 | String status, 42 | String name, 43 | String authors, 44 | String cover, 45 | List types, 46 | int last_update_chapter_id, 47 | int last_update_volume_id, 48 | String last_update_volume_name, 49 | String last_update_chapter_name, 50 | int last_update_time, 51 | }):_id=id,_status=status,_name=name,_authors=authors,_cover=cover,_types=types,_last_update_chapter_id=last_update_chapter_id,_last_update_volume_id=last_update_volume_id,_last_update_volume_name=last_update_volume_name,_last_update_chapter_name=last_update_chapter_name,_last_update_time=last_update_time; 52 | factory NovelUpdateItem.fromJson(jsonRes){ if(jsonRes == null) return null; 53 | List types = jsonRes['types'] is List ? []: null; 54 | if(types!=null) { 55 | for (var item in jsonRes['types']) { if (item != null) { types.add(item); } 56 | } 57 | } 58 | 59 | 60 | return NovelUpdateItem( id : jsonRes['id'], 61 | status : jsonRes['status'], 62 | name : jsonRes['name'], 63 | authors : jsonRes['authors'], 64 | cover : jsonRes['cover'], 65 | types:types, 66 | last_update_chapter_id : jsonRes['last_update_chapter_id'], 67 | last_update_volume_id : jsonRes['last_update_volume_id'], 68 | last_update_volume_name : jsonRes['last_update_volume_name'], 69 | last_update_chapter_name : jsonRes['last_update_chapter_name'], 70 | last_update_time : jsonRes['last_update_time'], 71 | );} 72 | Map toJson() => { 73 | 'id': _id, 74 | 'status': _status, 75 | 'name': _name, 76 | 'authors': _authors, 77 | 'cover': _cover, 78 | 'types': _types, 79 | 'last_update_chapter_id': _last_update_chapter_id, 80 | 'last_update_volume_id': _last_update_volume_id, 81 | 'last_update_volume_name': _last_update_volume_name, 82 | 'last_update_chapter_name': _last_update_chapter_name, 83 | 'last_update_time': _last_update_time, 84 | }; 85 | 86 | @override 87 | String toString() { 88 | return json.encode(this); 89 | } 90 | } 91 | 92 | -------------------------------------------------------------------------------- /lib/models/novel/novel_volume_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class NovelVolumeItem { 4 | int _volume_id; 5 | int get volume_id => _volume_id; 6 | int _id; 7 | int get id => _id; 8 | String _volume_name; 9 | String get volume_name => _volume_name; 10 | int _volume_order; 11 | int get volume_order => _volume_order; 12 | List _chapters; 13 | List get chapters => _chapters; 14 | 15 | NovelVolumeItem({ 16 | int volume_id, 17 | int id, 18 | String volume_name, 19 | int volume_order, 20 | List chapters, 21 | }):_volume_id=volume_id,_id=id,_volume_name=volume_name,_volume_order=volume_order,_chapters=chapters; 22 | factory NovelVolumeItem.fromJson(jsonRes){ if(jsonRes == null) return null; 23 | List chapters = jsonRes['chapters'] is List ? []: null; 24 | if(chapters!=null) { 25 | for (var item in jsonRes['chapters']) { if (item != null) { chapters.add(NovelVolumeChapterItem.fromJson(item)); } 26 | } 27 | } 28 | 29 | 30 | return NovelVolumeItem( volume_id : jsonRes['volume_id'], 31 | id : jsonRes['id'], 32 | volume_name : jsonRes['volume_name'], 33 | volume_order : jsonRes['volume_order'], 34 | chapters:chapters, 35 | );} 36 | Map toJson() => { 37 | 'volume_id': _volume_id, 38 | 'id': _id, 39 | 'volume_name': _volume_name, 40 | 'volume_order': _volume_order, 41 | 'chapters': _chapters, 42 | }; 43 | 44 | @override 45 | String toString() { 46 | return json.encode(this); 47 | } 48 | } 49 | class NovelVolumeChapterItem { 50 | int _chapter_id; 51 | int get chapter_id => _chapter_id; 52 | String _chapter_name; 53 | String get chapter_name => _chapter_name; 54 | int _chapter_order; 55 | int get chapter_order => _chapter_order; 56 | 57 | int _volume_id; 58 | int get volume_id => _volume_id; 59 | set volume_id(e){ 60 | _volume_id=e; 61 | } 62 | 63 | String _volume_name; 64 | String get volume_name => _volume_name; 65 | set volume_name(e){ 66 | _volume_name=e; 67 | } 68 | 69 | NovelVolumeChapterItem({ 70 | int chapter_id, 71 | String chapter_name, 72 | int chapter_order, 73 | }):_chapter_id=chapter_id,_chapter_name=chapter_name,_chapter_order=chapter_order; 74 | factory NovelVolumeChapterItem.fromJson(jsonRes)=>jsonRes == null? null:NovelVolumeChapterItem( chapter_id : jsonRes['chapter_id'], 75 | chapter_name : jsonRes['chapter_name'], 76 | chapter_order : jsonRes['chapter_order'], 77 | ); 78 | Map toJson() => { 79 | 'chapter_id': _chapter_id, 80 | 'chapter_name': _chapter_name, 81 | 'chapter_order': _chapter_order, 82 | }; 83 | 84 | @override 85 | String toString() { 86 | return json.encode(this); 87 | } 88 | } 89 | 90 | 91 | -------------------------------------------------------------------------------- /lib/models/search_hot_word.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class SearchHotWord { 4 | int _id; 5 | int get id => _id; 6 | String _name; 7 | String get name => _name; 8 | 9 | SearchHotWord({ 10 | int id, 11 | String name, 12 | }):_id=id,_name=name; 13 | factory SearchHotWord.fromJson(jsonRes)=>jsonRes == null? null:SearchHotWord( id : jsonRes['id'], 14 | name : jsonRes['name'], 15 | ); 16 | Map toJson() => { 17 | 'id': _id, 18 | 'name': _name, 19 | }; 20 | 21 | @override 22 | String toString() { 23 | return json.encode(this); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /lib/models/user/user_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class UserLgoinModel { 4 | final int result; 5 | final String msg; 6 | final UserInfo data; 7 | 8 | UserLgoinModel({ 9 | this.result, 10 | this.msg, 11 | this.data, 12 | }); 13 | 14 | 15 | factory UserLgoinModel.fromJson(jsonRes)=>jsonRes == null? null:UserLgoinModel( result : jsonRes['result'], 16 | msg : jsonRes['msg'], 17 | data : UserInfo.fromJson(jsonRes['data']), 18 | ); 19 | Map toJson() => { 20 | 'result': result, 21 | 'msg': msg, 22 | 'data': data, 23 | }; 24 | 25 | @override 26 | String toString() { 27 | return json.encode(this); 28 | } 29 | } 30 | class UserInfo { 31 | final String uid; 32 | final String nickname; 33 | final String dmzj_token; 34 | final String photo; 35 | final String bind_phone; 36 | final String email; 37 | final String passwd; 38 | 39 | UserInfo({ 40 | this.uid, 41 | this.nickname, 42 | this.dmzj_token, 43 | this.photo, 44 | this.bind_phone, 45 | this.email, 46 | this.passwd, 47 | }); 48 | 49 | 50 | factory UserInfo.fromJson(jsonRes)=>jsonRes == null? null:UserInfo( uid : jsonRes['uid'], 51 | nickname : jsonRes['nickname'], 52 | dmzj_token : jsonRes['dmzj_token'], 53 | photo : jsonRes['photo'], 54 | bind_phone : jsonRes['bind_phone'], 55 | email : jsonRes['email'], 56 | passwd : jsonRes['passwd'], 57 | ); 58 | Map toJson() => { 59 | 'uid': uid, 60 | 'nickname': nickname, 61 | 'dmzj_token': dmzj_token, 62 | 'photo': photo, 63 | 'bind_phone': bind_phone, 64 | 'email': email, 65 | 'passwd': passwd, 66 | }; 67 | 68 | @override 69 | String toString() { 70 | return json.encode(this); 71 | } 72 | } 73 | 74 | 75 | -------------------------------------------------------------------------------- /lib/models/user/user_profile.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class UserProfileModel { 4 | final String nickname; 5 | final String description; 6 | final String birthday; 7 | final int sex; 8 | final String cover; 9 | final int blood; 10 | final String constellation; 11 | final String bind_phone; 12 | final String email; 13 | final String channel; 14 | final int is_verify; 15 | final int is_modify_name; 16 | final List data; 17 | final int amount; 18 | final int is_set_pwd; 19 | final List bind; 20 | 21 | UserProfileModel({ 22 | this.nickname, 23 | this.description, 24 | this.birthday, 25 | this.sex, 26 | this.cover, 27 | this.blood, 28 | this.constellation, 29 | this.bind_phone, 30 | this.email, 31 | this.channel, 32 | this.is_verify, 33 | this.is_modify_name, 34 | this.data, 35 | this.amount, 36 | this.is_set_pwd, 37 | this.bind, 38 | }); 39 | 40 | 41 | factory UserProfileModel.fromJson(jsonRes){ if(jsonRes == null) return null; 42 | List data = jsonRes['data'] is List ? []: null; 43 | if(data!=null) { 44 | for (var item in jsonRes['data']) { if (item != null) { data.add(item); } 45 | } 46 | } 47 | 48 | 49 | List bind = jsonRes['bind'] is List ? []: null; 50 | if(bind!=null) { 51 | for (var item in jsonRes['bind']) { if (item != null) { bind.add(UserBindModel.fromJson(item)); } 52 | } 53 | } 54 | 55 | 56 | return UserProfileModel( nickname : jsonRes['nickname'], 57 | description : jsonRes['description'], 58 | birthday : jsonRes['birthday'], 59 | sex : jsonRes['sex'], 60 | cover : jsonRes['cover'], 61 | blood : jsonRes['blood'], 62 | constellation : jsonRes['constellation'], 63 | bind_phone : jsonRes['bind_phone'].toString(), 64 | email : jsonRes['email'], 65 | channel : jsonRes['channel'], 66 | is_verify : jsonRes['is_verify'], 67 | is_modify_name : jsonRes['is_modify_name'], 68 | data:data, 69 | amount : jsonRes['amount'], 70 | is_set_pwd : jsonRes['is_set_pwd'], 71 | bind:bind, 72 | );} 73 | Map toJson() => { 74 | 'nickname': nickname, 75 | 'description': description, 76 | 'birthday': birthday, 77 | 'sex': sex, 78 | 'cover': cover, 79 | 'blood': blood, 80 | 'constellation': constellation, 81 | 'bind_phone': bind_phone, 82 | 'email': email, 83 | 'channel': channel, 84 | 'is_verify': is_verify, 85 | 'is_modify_name': is_modify_name, 86 | 'data': data, 87 | 'amount': amount, 88 | 'is_set_pwd': is_set_pwd, 89 | 'bind': bind, 90 | }; 91 | 92 | @override 93 | String toString() { 94 | return json.encode(this); 95 | } 96 | } 97 | class UserBindModel { 98 | final String type; 99 | final String name; 100 | 101 | UserBindModel({ 102 | this.type, 103 | this.name, 104 | }); 105 | 106 | 107 | factory UserBindModel.fromJson(jsonRes)=>jsonRes == null? null:UserBindModel( type : jsonRes['type'], 108 | name : jsonRes['name'].toString(), 109 | ); 110 | Map toJson() => { 111 | 'type': type, 112 | 'name': name, 113 | }; 114 | 115 | @override 116 | String toString() { 117 | return json.encode(this); 118 | } 119 | } 120 | 121 | 122 | -------------------------------------------------------------------------------- /lib/models/user/user_subscribe_item.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class SubscribeItem { 4 | String _name; 5 | String get name => _name; 6 | String _sub_update; 7 | String get sub_update => _sub_update; 8 | String _sub_img; 9 | String get sub_img => _sub_img; 10 | int _sub_uptime; 11 | int get sub_uptime => _sub_uptime; 12 | String _sub_first_letter; 13 | String get sub_first_letter => _sub_first_letter; 14 | int _sub_readed; 15 | int get sub_readed => _sub_readed; 16 | int _id; 17 | int get id => _id; 18 | String _status; 19 | String get status => _status; 20 | 21 | SubscribeItem({ 22 | String name, 23 | String sub_update, 24 | String sub_img, 25 | int sub_uptime, 26 | String sub_first_letter, 27 | int sub_readed, 28 | int id, 29 | String status, 30 | }):_name=name,_sub_update=sub_update,_sub_img=sub_img,_sub_uptime=sub_uptime,_sub_first_letter=sub_first_letter,_sub_readed=sub_readed,_id=id,_status=status; 31 | factory SubscribeItem.fromJson(jsonRes)=>jsonRes == null? null:SubscribeItem( name : jsonRes['name'], 32 | sub_update : jsonRes['sub_update'], 33 | sub_img : jsonRes['sub_img'], 34 | sub_uptime : jsonRes['sub_uptime'], 35 | sub_first_letter : jsonRes['sub_first_letter'], 36 | sub_readed : jsonRes['sub_readed'], 37 | id : jsonRes['id'], 38 | status : jsonRes['status'], 39 | ); 40 | Map toJson() => { 41 | 'name': _name, 42 | 'sub_update': _sub_update, 43 | 'sub_img': _sub_img, 44 | 'sub_uptime': _sub_uptime, 45 | 'sub_first_letter': _sub_first_letter, 46 | 'sub_readed': _sub_readed, 47 | 'id': _id, 48 | 'status': _status, 49 | }; 50 | 51 | @override 52 | String toString() { 53 | return json.encode(this); 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /lib/models/user_comment_model.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class UserCommentItem { 4 | int _comment_id; 5 | int get comment_id => _comment_id; 6 | String _content; 7 | String get content => _content; 8 | int _reply_amount; 9 | int get reply_amount => _reply_amount; 10 | set reply_amount(value) { 11 | _reply_amount = value; 12 | } 13 | 14 | int _like_amount; 15 | int get like_amount => _like_amount; 16 | set like_amount(value) { 17 | _like_amount = value; 18 | } 19 | 20 | int _origin_comment_id; 21 | int get origin_comment_id => _origin_comment_id; 22 | int _obj_id; 23 | int get obj_id => _obj_id; 24 | int _create_time; 25 | int get create_time => _create_time; 26 | int _to_comment_id; 27 | int get to_comment_id => _to_comment_id; 28 | String _obj_cover; 29 | String get obj_cover => _obj_cover; 30 | String _obj_name; 31 | String get obj_name => _obj_name; 32 | String _page_url; 33 | String get page_url => _page_url; 34 | UserMasterComment _masterComment; 35 | UserMasterComment get masterComment => _masterComment; 36 | 37 | UserCommentItem({ 38 | int comment_id, 39 | String content, 40 | int reply_amount, 41 | int like_amount, 42 | int origin_comment_id, 43 | int obj_id, 44 | int create_time, 45 | int to_comment_id, 46 | String obj_cover, 47 | String obj_name, 48 | String page_url, 49 | UserMasterComment masterComment, 50 | }):_comment_id=comment_id,_content=content,_reply_amount=reply_amount,_like_amount=like_amount,_origin_comment_id=origin_comment_id,_obj_id=obj_id,_create_time=create_time,_to_comment_id=to_comment_id,_obj_cover=obj_cover,_obj_name=obj_name,_page_url=page_url,_masterComment=masterComment; 51 | factory UserCommentItem.fromJson(jsonRes)=>jsonRes == null? null:UserCommentItem( comment_id : jsonRes['comment_id'], 52 | content : jsonRes['content'], 53 | reply_amount : jsonRes['reply_amount'], 54 | like_amount : jsonRes['like_amount'], 55 | origin_comment_id : jsonRes['origin_comment_id'], 56 | obj_id : jsonRes['obj_id'], 57 | create_time : jsonRes['create_time'], 58 | to_comment_id : jsonRes['to_comment_id'], 59 | obj_cover : jsonRes['obj_cover'], 60 | obj_name : jsonRes['obj_name'], 61 | page_url : jsonRes['page_url'], 62 | masterComment : UserMasterComment.fromJson(jsonRes['masterComment']), 63 | ); 64 | Map toJson() => { 65 | 'comment_id': _comment_id, 66 | 'content': _content, 67 | 'reply_amount': _reply_amount, 68 | 'like_amount': _like_amount, 69 | 'origin_comment_id': _origin_comment_id, 70 | 'obj_id': _obj_id, 71 | 'create_time': _create_time, 72 | 'to_comment_id': _to_comment_id, 73 | 'obj_cover': _obj_cover, 74 | 'obj_name': _obj_name, 75 | 'page_url': _page_url, 76 | 'masterComment': _masterComment, 77 | }; 78 | 79 | @override 80 | String toString() { 81 | return json.encode(this); 82 | } 83 | } 84 | class UserMasterComment { 85 | int _id; 86 | int get id => _id; 87 | String _content; 88 | String get content => _content; 89 | int _sender_uid; 90 | int get sender_uid => _sender_uid; 91 | int _like_amount; 92 | int get like_amount => _like_amount; 93 | set like_amount(value) { 94 | _like_amount = value; 95 | } 96 | 97 | int _create_time; 98 | int get create_time => _create_time; 99 | int _reply_amount; 100 | int get reply_amount => _reply_amount; 101 | set reply_amount(value) { 102 | _reply_amount = value; 103 | } 104 | 105 | String _nickname; 106 | String get nickname => _nickname; 107 | 108 | UserMasterComment({ 109 | int id, 110 | String content, 111 | int sender_uid, 112 | int like_amount, 113 | int create_time, 114 | int reply_amount, 115 | String nickname, 116 | }):_id=id,_content=content,_sender_uid=sender_uid,_like_amount=like_amount,_create_time=create_time,_reply_amount=reply_amount,_nickname=nickname; 117 | factory UserMasterComment.fromJson(jsonRes)=>jsonRes == null? null:UserMasterComment( id : jsonRes['id'], 118 | content : jsonRes['content'], 119 | sender_uid : jsonRes['sender_uid'], 120 | like_amount : jsonRes['like_amount'], 121 | create_time : jsonRes['create_time'], 122 | reply_amount : jsonRes['reply_amount'], 123 | nickname : jsonRes['nickname'], 124 | ); 125 | Map toJson() => { 126 | 'id': _id, 127 | 'content': _content, 128 | 'sender_uid': _sender_uid, 129 | 'like_amount': _like_amount, 130 | 'create_time': _create_time, 131 | 'reply_amount': _reply_amount, 132 | 'nickname': _nickname, 133 | }; 134 | 135 | @override 136 | String toString() { 137 | return json.encode(this); 138 | } 139 | } 140 | 141 | 142 | -------------------------------------------------------------------------------- /lib/models/version_info.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert' show json; 2 | 3 | class VersionInfo { 4 | String version; 5 | String version_code; 6 | String message; 7 | String android_url; 8 | String ios_url; 9 | bool hide_banner; 10 | 11 | VersionInfo({ 12 | this.version, 13 | this.version_code, 14 | this.message, 15 | this.android_url, 16 | this.ios_url, 17 | this.hide_banner, 18 | }); 19 | 20 | factory VersionInfo.fromJson(jsonRes) => jsonRes == null 21 | ? null 22 | : VersionInfo( 23 | version: jsonRes['version'], 24 | version_code: jsonRes['version_code'], 25 | message: jsonRes['message'], 26 | android_url: jsonRes['android_url'], 27 | ios_url: jsonRes['ios_url'], 28 | hide_banner: jsonRes['hide_banner'], 29 | ); 30 | Map toJson() => { 31 | 'version': version, 32 | 'version_code': version_code, 33 | 'message': message, 34 | 'android_url': android_url, 35 | 'ios_url': ios_url, 36 | 'hide_banner': hide_banner, 37 | }; 38 | 39 | @override 40 | String toString() { 41 | return json.encode(this); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /lib/protobuf/comic/detail_response.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package dmzj.comic; 4 | 5 | 6 | message ComicDetailResponse { 7 | int32 Errno = 1; 8 | string Errmsg = 2; 9 | ComicDetailInfoResponse Data= 3; 10 | } 11 | 12 | message ComicDetailInfoResponse { 13 | int32 Id = 1; 14 | string Title = 2; 15 | int32 Direction=3; 16 | int32 Islong=4; 17 | int32 IsDmzj=5; 18 | string Cover=6; 19 | string Description=7; 20 | int64 LastUpdatetime=8; 21 | string LastUpdateChapterName=9; 22 | int32 Copyright=10; 23 | string FirstLetter=11; 24 | string ComicPy=12; 25 | int32 Hidden=13; 26 | int32 HotNum=14; 27 | int32 HitNum=15; 28 | int32 Uid=16; 29 | int32 IsLock=17; 30 | int32 LastUpdateChapterId=18; 31 | repeated ComicDetailTypeItemResponse Types=19; 32 | repeated ComicDetailTypeItemResponse Status=20; 33 | repeated ComicDetailTypeItemResponse Authors=21; 34 | int32 SubscribeNum=22; 35 | repeated ComicDetailChapterResponse Chapters=23; 36 | int32 IsNeedLogin=24; 37 | //object UrlLinks=25; 38 | int32 IsHideChapter=26; 39 | //object DhUrlLinks=27; 40 | 41 | } 42 | 43 | message ComicDetailTypeItemResponse { 44 | int32 TagId = 1; 45 | string TagName = 2; 46 | } 47 | 48 | message ComicDetailChapterResponse { 49 | string Title = 1; 50 | repeated ComicDetailChapterInfoResponse Data=2; 51 | } 52 | message ComicDetailChapterInfoResponse { 53 | int32 ChapterId = 1; 54 | string ChapterTitle = 2; 55 | int64 Updatetime=3; 56 | int32 Filesize=4; 57 | int32 ChapterOrder=5; 58 | } 59 | -------------------------------------------------------------------------------- /lib/protobuf/comic/rank_list_response.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package dmzj.comic; 4 | 5 | 6 | message ComicRankListResponse { 7 | int32 Errno = 1; 8 | string Errmsg = 2; 9 | repeated ComicRankListItemResponse Data= 3; 10 | } 11 | 12 | message ComicRankListItemResponse { 13 | int32 ComicId = 1; 14 | string Title = 2; 15 | string Authors=3; 16 | string Status=4; 17 | string Cover=5; 18 | string Types=6; 19 | int64 LastUpdatetime=7; 20 | string LastUpdateChapterName=8; 21 | string ComicPy=9; 22 | int32 Num=10; 23 | int32 TagId=11; 24 | string ChapterName=12; 25 | int32 ChapterId=13; 26 | } 27 | -------------------------------------------------------------------------------- /lib/protobuf/comic/update_list_response.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package dmzj.comic; 4 | 5 | 6 | message ComicUpdateListResponse { 7 | int32 Errno = 1; 8 | string Errmsg = 2; 9 | repeated ComicUpdateListItemResponse Data= 3; 10 | } 11 | 12 | message ComicUpdateListItemResponse { 13 | int32 ComicId = 1; 14 | string Title = 2; 15 | bool Islong = 3; 16 | string Authors=4; 17 | string Types=5; 18 | string Cover=6; 19 | string Status=7; 20 | string LastUpdateChapterName=8; 21 | int32 LastUpdateChapterId=9; 22 | int64 LastUpdatetime=10; 23 | } 24 | -------------------------------------------------------------------------------- /lib/protobuf/news/news_list_response.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package dmzj.news; 4 | 5 | 6 | message NewsListResponse { 7 | int32 Errno = 1; 8 | string Errmsg = 2; 9 | repeated NewsListItemResponse Data= 3; 10 | } 11 | 12 | message NewsListItemResponse { 13 | int32 ArticleId = 1; 14 | string Title = 2; 15 | string FromName = 3; 16 | string FromUrl=4; 17 | int64 CreateTime=5; 18 | int32 IsForeign=6; 19 | string ForeignUrl=7; 20 | string Intro=8; 21 | int32 AuthorId=9; 22 | int32 Status=10; 23 | string RowPicUrl=11; 24 | string ColPicUrl=12; 25 | int32 QchatShow=13; 26 | string PageUrl=14; 27 | int32 CommentAmount=15; 28 | int32 AuthorUid=16; 29 | string Cover=17; 30 | string Nickname=18; 31 | int32 MoodAmount=19; 32 | } -------------------------------------------------------------------------------- /lib/protobuf/novel/novel_chapter_response.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package dmzj.novel; 4 | 5 | 6 | message NovelChapterResponse { 7 | int32 Errno = 1; 8 | string Errmsg = 2; 9 | repeated NovelChapterVolumeResponse Data= 3; 10 | } 11 | 12 | message NovelChapterVolumeResponse { 13 | int32 VolumeId = 1; 14 | string VolumeName = 2; 15 | int32 VolumeOrder=3; 16 | repeated NovelChapterItemResponse Chapters=4; 17 | } 18 | 19 | message NovelChapterItemResponse { 20 | int32 ChapterId = 1; 21 | string ChapterName=2; 22 | int32 ChapterOrder = 3; 23 | } 24 | -------------------------------------------------------------------------------- /lib/protobuf/novel/novel_detail_response.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package dmzj.novel; 4 | 5 | 6 | message NovelDetailResponse { 7 | int32 Errno = 1; 8 | string Errmsg = 2; 9 | NovelDetailInfoResponse Data= 3; 10 | } 11 | 12 | message NovelDetailInfoResponse { 13 | int32 NovelId = 1; 14 | string Name = 2; 15 | string Zone=3; 16 | string Status=4; 17 | string LastUpdateVolumeName=5; 18 | string LastUpdateChapterName=6; 19 | int32 LastUpdateVolumeId=7; 20 | int32 LastUpdateChapterId=8; 21 | int64 LastUpdateTime=9; 22 | string Cover=10; 23 | int32 HotHits=11; 24 | string Introduction=12; 25 | repeated string Types=13; 26 | string Authors=14; 27 | string FirstLetter=15; 28 | int32 SubscribeNum=16; 29 | int64 RedisUpdateTime=17; 30 | repeated NovelDetailInfoVolumeResponse Volume=18; 31 | } 32 | 33 | message NovelDetailInfoVolumeResponse { 34 | int32 VolumeId = 1; 35 | int32 LnovelId = 2; 36 | string VolumeName=3; 37 | int32 VolumeOrder=4; 38 | int64 Addtime=5; 39 | int32 SumChapters=6; 40 | } 41 | -------------------------------------------------------------------------------- /lib/sql/comic_down.dart: -------------------------------------------------------------------------------- 1 | import 'package:sqflite/sqflite.dart'; 2 | 3 | final String comicDownloadTableName = 'ComicDownload'; 4 | final String comicDownloadColumnChapterID = 'ChapterID'; 5 | final String comicDownloadColumnChapterName = 'ChapterName'; 6 | final String comicDownloadColumnComicID = 'ComicID'; 7 | final String comicDownloadColumnComicName = 'ComicName'; 8 | final String comicDownloadColumnStatus = 'Status'; 9 | final String comicDownloadColumnVolume = 'Volume'; 10 | final String comicDownloadColumnPage = 'Page'; 11 | final String comicDownloadColumnCount = 'Count'; 12 | final String comicDownloadColumnSavePath = 'SavePath'; 13 | final String comicDownloadColumnUrls = 'Urls'; 14 | 15 | class ComicDownloadSqlItem { 16 | int chapterID; 17 | String chapterName; 18 | int comicID; 19 | String comicName; 20 | int status; 21 | String volume; 22 | int page; 23 | int count; 24 | String savePath; 25 | String urls; 26 | 27 | ComicDownloadSqlItem(this.chapterID, this.chapterName, this.comicID, 28 | this.comicName, this.status, this.volume, 29 | {this.page, this.count, this.savePath, this.urls}); 30 | 31 | Map toMap() { 32 | var map = { 33 | comicDownloadColumnChapterID: chapterID, 34 | comicDownloadColumnChapterName: chapterName, 35 | comicDownloadColumnComicID: comicID, 36 | comicDownloadColumnComicName: comicName, 37 | comicDownloadColumnStatus: status, 38 | comicDownloadColumnVolume: volume, 39 | comicDownloadColumnPage: page, 40 | comicDownloadColumnCount: count, 41 | comicDownloadColumnSavePath: savePath, 42 | comicDownloadColumnUrls: urls, 43 | }; 44 | return map; 45 | } 46 | 47 | ComicDownloadSqlItem.fromMap(Map map) { 48 | chapterID = map[comicDownloadColumnChapterID]; 49 | chapterName = map[comicDownloadColumnChapterName]; 50 | comicID = map[comicDownloadColumnComicID]; 51 | comicName = map[comicDownloadColumnComicName]; 52 | status = map[comicDownloadColumnStatus]; 53 | volume = map[comicDownloadColumnVolume]; 54 | page = map[comicDownloadColumnPage]; 55 | count = map[comicDownloadColumnCount]; 56 | savePath = map[comicDownloadColumnSavePath]; 57 | urls = map[comicDownloadColumnUrls]; 58 | } 59 | } 60 | 61 | class ComicDownloadProvider { 62 | static Database db; 63 | static Future insert(ComicDownloadSqlItem item) async { 64 | await db.insert(comicDownloadTableName, item.toMap()); 65 | return item; 66 | } 67 | 68 | static Future getItem(int id) async { 69 | List maps = await db.query(comicDownloadTableName, 70 | columns: [ 71 | comicDownloadColumnChapterID, 72 | comicDownloadColumnChapterName, 73 | comicDownloadColumnComicID, 74 | comicDownloadColumnComicName, 75 | comicDownloadColumnStatus, 76 | comicDownloadColumnVolume, 77 | comicDownloadColumnPage, 78 | comicDownloadColumnCount, 79 | comicDownloadColumnSavePath, 80 | comicDownloadColumnUrls, 81 | ], 82 | where: '$comicDownloadColumnChapterID = ?', 83 | whereArgs: [id]); 84 | 85 | if (maps.length > 0) { 86 | return ComicDownloadSqlItem.fromMap(maps.first); 87 | } 88 | return null; 89 | } 90 | 91 | static Future clear() async { 92 | return await db.delete(comicDownloadTableName); 93 | } 94 | 95 | static Future updateOrInsert( 96 | ComicDownloadSqlItem item) async { 97 | var data = await getItem(item.chapterID); 98 | if (data != null) { 99 | await update(item); 100 | return item; 101 | } else { 102 | return await insert(item); 103 | } 104 | } 105 | 106 | static Future> getItems() async { 107 | List maps = (await db.query(comicDownloadTableName)) 108 | .map((x) => ComicDownloadSqlItem.fromMap(x)) 109 | .toList(); 110 | return maps; 111 | } 112 | 113 | static Future delete(int id) async { 114 | return await db.delete(comicDownloadTableName, 115 | where: '$comicDownloadColumnChapterID = ?', whereArgs: [id]); 116 | } 117 | 118 | static Future update(ComicDownloadSqlItem item) async { 119 | return await db.update(comicDownloadTableName, item.toMap(), 120 | where: '$comicDownloadColumnChapterID = ?', 121 | whereArgs: [item.chapterID]); 122 | } 123 | 124 | static Future close() async => db.close(); 125 | } 126 | -------------------------------------------------------------------------------- /lib/sql/comic_history.dart: -------------------------------------------------------------------------------- 1 | import 'package:sqflite/sqflite.dart'; 2 | 3 | final String comicHistoryTable = 'comic_history'; 4 | //主键 5 | final String comicHistoryColumnComicID = 'comic_id'; 6 | final String comicHistoryColumnChapterID = 'chapter_id'; 7 | final String comicHistoryColumnPage = 'page'; 8 | //1为横向,2为纵向阅读百分比 9 | final String comicHistoryMode = 'mode'; 10 | 11 | class ComicHistory { 12 | int comic_id; 13 | int chapter_id; 14 | double page; 15 | int mode; 16 | 17 | Map toMap() { 18 | var map = { 19 | comicHistoryColumnComicID: comic_id, 20 | comicHistoryColumnChapterID: chapter_id, 21 | comicHistoryColumnPage: page, 22 | comicHistoryMode:mode, 23 | }; 24 | return map; 25 | } 26 | 27 | ComicHistory(this.comic_id,this.chapter_id,this.page,this.mode); 28 | 29 | ComicHistory.fromMap(Map map) { 30 | comic_id = map[comicHistoryColumnComicID]; 31 | chapter_id = map[comicHistoryColumnChapterID]; 32 | page = map[comicHistoryColumnPage]; 33 | mode= map[comicHistoryMode]; 34 | } 35 | } 36 | 37 | class ComicHistoryProvider { 38 | static Database db; 39 | 40 | 41 | static Future insert(ComicHistory item) async { 42 | await db.insert(comicHistoryTable, item.toMap()); 43 | 44 | return item; 45 | } 46 | 47 | static Future getItem(int id) async { 48 | 49 | List maps = await db.query(comicHistoryTable, 50 | columns: [comicHistoryColumnComicID, comicHistoryColumnChapterID, comicHistoryColumnPage,comicHistoryMode], 51 | where: '$comicHistoryColumnComicID = ?', 52 | whereArgs: [id]); 53 | if (maps.length > 0) { 54 | return ComicHistory.fromMap(maps.first); 55 | } 56 | return null; 57 | } 58 | 59 | static Future clear() async { 60 | return await db.delete(comicHistoryTable); 61 | } 62 | 63 | static Future> getItems() async { 64 | List maps = (await db.query(comicHistoryTable)).map((x)=>ComicHistory.fromMap(x)).toList(); 65 | return maps; 66 | } 67 | 68 | 69 | static Future delete(String id) async { 70 | return await db.delete(comicHistoryTable, where: '$comicHistoryColumnComicID = ?', whereArgs: [id]); 71 | } 72 | 73 | static Future update(ComicHistory item) async { 74 | return await db.update(comicHistoryTable, item.toMap(), 75 | where: '$comicHistoryColumnComicID = ?', whereArgs: [item.comic_id]); 76 | } 77 | 78 | static Future close() async => db.close(); 79 | } -------------------------------------------------------------------------------- /lib/sql/novel_history.dart: -------------------------------------------------------------------------------- 1 | import 'package:sqflite/sqflite.dart'; 2 | 3 | final String tableName = 'novel_history'; 4 | //主键 5 | final String columnNovelID = 'novel_id'; 6 | final String columnChapterID = 'chapter_id'; 7 | final String columnPage = 'page'; 8 | //1为横向,2为纵向阅读百分比 9 | final String columnReadingMode = 'mode'; 10 | 11 | class NovelHistory { 12 | int novelId; 13 | int chapterId; 14 | double page; 15 | int mode; 16 | 17 | Map toMap() { 18 | var map = { 19 | columnNovelID: novelId, 20 | columnChapterID: chapterId, 21 | columnPage: page, 22 | columnReadingMode: mode, 23 | }; 24 | return map; 25 | } 26 | 27 | NovelHistory(this.novelId, this.chapterId, this.page, this.mode); 28 | 29 | NovelHistory.fromMap(Map map) { 30 | novelId = map[columnNovelID]; 31 | chapterId = map[columnChapterID]; 32 | page = map[columnPage]; 33 | mode = map[columnReadingMode]; 34 | } 35 | } 36 | 37 | class NovelHistoryProvider { 38 | static Database db; 39 | 40 | static void create(Database _db) { 41 | var batch = _db.batch(); 42 | batch.execute(''' 43 | create table $tableName ( 44 | $columnNovelID integer primary key not null, 45 | $columnChapterID integer not null, 46 | $columnPage double not null, 47 | $columnReadingMode integer not null) 48 | '''); 49 | 50 | batch.commit(); 51 | return; 52 | } 53 | 54 | static Future insert(NovelHistory item) async { 55 | await db.insert(tableName, item.toMap()); 56 | 57 | return item; 58 | } 59 | 60 | static Future getItem(int id) async { 61 | List maps = await db.query(tableName, 62 | columns: [ 63 | columnNovelID, 64 | columnChapterID, 65 | columnPage, 66 | columnReadingMode 67 | ], 68 | where: '$columnNovelID = ?', 69 | whereArgs: [id]); 70 | if (maps.length > 0) { 71 | return NovelHistory.fromMap(maps.first); 72 | } 73 | return null; 74 | } 75 | 76 | static Future clear() async { 77 | return await db.delete(tableName); 78 | } 79 | 80 | static Future> getItems() async { 81 | List maps = (await db.query(tableName)) 82 | .map((x) => NovelHistory.fromMap(x)) 83 | .toList(); 84 | return maps; 85 | } 86 | 87 | static Future delete(String id) async { 88 | return await db 89 | .delete(tableName, where: '$columnNovelID = ?', whereArgs: [id]); 90 | } 91 | 92 | static Future update(NovelHistory item) async { 93 | return await db.update(tableName, item.toMap(), 94 | where: '$columnNovelID = ?', whereArgs: [item.novelId]); 95 | } 96 | 97 | static Future updateOrCreate(NovelHistory item) async { 98 | var isDone = false; 99 | getItem(item.novelId).then((historyItem) async { 100 | if (historyItem != null) { 101 | historyItem.chapterId = item.chapterId; 102 | historyItem.page = item.page.toDouble(); 103 | var ret = await update(historyItem); 104 | 105 | if (ret > 0) { 106 | isDone = true; 107 | } 108 | } else { 109 | var ret = await insert(NovelHistory( 110 | item.novelId, item.chapterId, item.page.toDouble(), 1)); 111 | 112 | if (ret != null) { 113 | isDone = true; 114 | } 115 | } 116 | // Utils.changHistory.fire(widget.novelId); 117 | }); 118 | 119 | return isDone; 120 | } 121 | 122 | static Future close() async => db.close(); 123 | 124 | static Future getPage(int id) async => (await getItem(id)).page; 125 | } 126 | -------------------------------------------------------------------------------- /lib/sql/test.dart: -------------------------------------------------------------------------------- 1 | import 'package:sqflite/sqflite.dart'; 2 | 3 | final String testTableName = 'Test'; 4 | final String testColumnId = 'Id'; 5 | final String testColumnName = 'Name'; 6 | final String testColumnDesc = 'Desc'; 7 | 8 | 9 | class TestSqlItem { 10 | String id; 11 | String name; 12 | String desc; 13 | 14 | 15 | Map toMap() { 16 | var map = { 17 | testColumnId: id, 18 | testColumnName: name, 19 | testColumnDesc: desc, 20 | 21 | }; 22 | return map; 23 | } 24 | 25 | TestSqlItem.fromMap(Map map) { 26 | id = map[testColumnId]; 27 | name = map[testColumnName]; 28 | desc = map[testColumnDesc]; 29 | 30 | } 31 | 32 | 33 | } 34 | 35 | class TestProvider { 36 | static Database db; 37 | static Future insert(TestSqlItem item) async { 38 | await db.insert(testTableName, item.toMap()); 39 | return item; 40 | } 41 | 42 | static Future getItem(String id) async { 43 | 44 | List maps = await db.query(testTableName, 45 | columns: [testColumnId, 46 | testColumnName, 47 | testColumnDesc, 48 | ], 49 | where: '$testColumnId = ?', 50 | whereArgs: [id]); 51 | 52 | if (maps.length > 0) { 53 | return TestSqlItem.fromMap(maps.first); 54 | } 55 | return null; 56 | } 57 | 58 | static Future clear() async { 59 | return await db.delete(testTableName); 60 | } 61 | 62 | static Future> getItems() async { 63 | List maps = (await db.query(testTableName)).map((x)=>TestSqlItem.fromMap(x)).toList(); 64 | return maps; 65 | } 66 | 67 | static Future delete(String id) async { 68 | return await db.delete(testTableName, where: '$testColumnId = ?', whereArgs: [id]); 69 | } 70 | 71 | static Future update(TestSqlItem item) async { 72 | return await db.update(testTableName, item.toMap(), 73 | where: '$testColumnId = ?', whereArgs: [item.id]); 74 | } 75 | 76 | static Future close() async => db.close(); 77 | 78 | } -------------------------------------------------------------------------------- /lib/views/comic/comic_author.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_dmzj/app/api.dart'; 5 | import 'package:flutter_dmzj/app/user_helper.dart'; 6 | import 'package:flutter_dmzj/app/utils.dart'; 7 | import 'package:flutter_dmzj/models/comic/comic_author_model.dart'; 8 | import 'package:flutter_easyrefresh/easy_refresh.dart'; 9 | import 'package:flutter_easyrefresh/material_header.dart'; 10 | import 'package:http/http.dart' as http; 11 | 12 | class ComicAuthorPage extends StatefulWidget { 13 | final int auhtoId; 14 | ComicAuthorPage(this.auhtoId, {Key key}) : super(key: key); 15 | 16 | @override 17 | _ComicAuthorPageState createState() => _ComicAuthorPageState(); 18 | } 19 | 20 | class _ComicAuthorPageState extends State { 21 | @override 22 | void initState() { 23 | super.initState(); 24 | loadData(); 25 | } 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | appBar: AppBar( 31 | title: Text(_detail == null ? "作者" : _detail.nickname + "的作品"), 32 | ), 33 | body: EasyRefresh( 34 | enableControlFinishLoad: false, 35 | header: MaterialHeader(), 36 | onRefresh: loadData, 37 | child: ListView( 38 | children: _detail != null 39 | ? _detail.data.map((f) => createItem(f)).toList() 40 | : [], 41 | ), 42 | ), 43 | ); 44 | } 45 | 46 | ComicAuthor _detail; 47 | Widget createItem(ComicAuthorItem item) { 48 | return InkWell( 49 | onTap: () { 50 | Utils.openPage(context, item.id, 1); 51 | }, 52 | child: Container( 53 | padding: EdgeInsets.all(8), 54 | height: 120, 55 | child: Row( 56 | crossAxisAlignment: CrossAxisAlignment.start, 57 | children: [ 58 | Container( 59 | height: 100, 60 | child: Utils.createCacheImage(item.cover, 270, 360), 61 | ), 62 | SizedBox( 63 | width: 12, 64 | ), 65 | Expanded( 66 | child: Column( 67 | crossAxisAlignment: CrossAxisAlignment.start, 68 | children: [ 69 | Text( 70 | item.name, 71 | maxLines: 1, 72 | ), 73 | SizedBox( 74 | height: 4, 75 | ), 76 | Text(item.status, 77 | style: TextStyle(color: Colors.grey, fontSize: 14), 78 | maxLines: 1), 79 | ], 80 | ), 81 | ), 82 | Center( 83 | child: IconButton( 84 | icon: Icon(Icons.favorite_border), 85 | onPressed: () { 86 | UserHelper.comicSubscribe(item.id); 87 | }), 88 | ) 89 | ], 90 | ), 91 | ), 92 | ); 93 | } 94 | 95 | bool _loading = false; 96 | 97 | Future loadData() async { 98 | try { 99 | if (_loading) { 100 | return; 101 | } 102 | setState(() { 103 | _loading = true; 104 | }); 105 | var response = 106 | await http.get(Uri.parse(Api.comicAuthorDetail(widget.auhtoId))); 107 | 108 | var jsonMap = jsonDecode(response.body); 109 | 110 | ComicAuthor detail = ComicAuthor.fromJson(jsonMap); 111 | 112 | setState(() { 113 | _detail = detail; 114 | }); 115 | } catch (e) { 116 | print(e); 117 | } finally { 118 | setState(() { 119 | _loading = false; 120 | }); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /lib/views/comic/comic_category.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_dmzj/app/api.dart'; 5 | import 'package:flutter_dmzj/app/utils.dart'; 6 | import 'package:flutter_dmzj/models/comic/comic_category_item.dart'; 7 | import 'package:http/http.dart' as http; 8 | 9 | class ComicCategoryPage extends StatefulWidget { 10 | ComicCategoryPage({Key key}) : super(key: key); 11 | 12 | @override 13 | _ComicCategoryPageState createState() => _ComicCategoryPageState(); 14 | } 15 | 16 | class _ComicCategoryPageState extends State 17 | with AutomaticKeepAliveClientMixin { 18 | @override 19 | bool get wantKeepAlive => true; 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | loadData(); 25 | } 26 | 27 | @override 28 | void setState(fn) { 29 | if (mounted) { 30 | super.setState(fn); 31 | } 32 | } 33 | 34 | double getWidth() { 35 | var count = MediaQuery.of(context).size.width ~/ 160; 36 | if (count < 3) count = 3; 37 | return (MediaQuery.of(context).size.width - count * 8) / count - 8; 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | super.build(context); 43 | return RefreshIndicator( 44 | onRefresh: loadData, 45 | child: GridView.builder( 46 | padding: EdgeInsets.all(8), 47 | shrinkWrap: true, 48 | physics: ScrollPhysics(), 49 | itemCount: _list.length, 50 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 51 | crossAxisCount: MediaQuery.of(context).size.width ~/ 160 < 3 52 | ? 3 53 | : MediaQuery.of(context).size.width ~/ 160, 54 | crossAxisSpacing: 4.0, 55 | mainAxisSpacing: 4.0, 56 | childAspectRatio: getWidth() / (getWidth() + 32)), 57 | itemBuilder: (context, i) => Container( 58 | child: Card( 59 | child: InkWell( 60 | onTap: () { 61 | Utils.openPage(context, _list[i].tag_id, 11, 62 | title: _list[i].title); 63 | }, 64 | child: Column( 65 | children: [ 66 | ClipRRect( 67 | borderRadius: BorderRadius.circular(4), 68 | child: Utils.createCacheImage(_list[i].cover, 200, 200)), 69 | SizedBox(height: 4), 70 | Flexible( 71 | child: Text(_list[i].title), 72 | ), 73 | ], 74 | ), 75 | ), 76 | ), 77 | ), 78 | ), 79 | ); 80 | } 81 | 82 | List _list = []; 83 | bool _loading = false; 84 | Future loadData() async { 85 | try { 86 | if (_loading) { 87 | return; 88 | } 89 | setState(() { 90 | _loading = true; 91 | }); 92 | var response = await http.get(Uri.parse(Api.comicCategory())); 93 | List jsonMap = jsonDecode(response.body)["data"]; 94 | List detail = 95 | jsonMap.map((i) => ComicCategoryItem.fromJson(i)).toList(); 96 | if (detail != null) { 97 | setState(() { 98 | _list = detail; 99 | }); 100 | } 101 | } catch (e) { 102 | print(e); 103 | } finally { 104 | setState(() { 105 | _loading = false; 106 | }); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/views/comic/comic_home.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/app/utils.dart'; 3 | import 'package:flutter_dmzj/views/comic/comic_category.dart'; 4 | import 'package:flutter_dmzj/views/comic/comic_rank.dart'; 5 | import 'package:flutter_dmzj/views/comic/comic_recommend.dart'; 6 | import 'package:flutter_dmzj/views/comic/comic_search.dart'; 7 | import 'package:flutter_dmzj/views/comic/comic_special.dart'; 8 | import 'package:flutter_dmzj/views/comic/comic_update.dart'; 9 | 10 | class ComicHomePage extends StatefulWidget { 11 | @override 12 | _ComicHomePageState createState() => _ComicHomePageState(); 13 | } 14 | 15 | class _ComicHomePageState extends State 16 | with TickerProviderStateMixin { 17 | TabController _tabController; 18 | 19 | @override 20 | void initState() { 21 | super.initState(); 22 | _tabController = TabController(length: 5, vsync: this); 23 | Utils.changeComicHomeTabIndex.on().listen((e) { 24 | _tabController.animateTo(e); 25 | }); 26 | } 27 | 28 | @override 29 | Widget build(BuildContext context) { 30 | return Scaffold( 31 | appBar: AppBar( 32 | title: TabBar( 33 | controller: _tabController, 34 | tabs: [ 35 | Tab(child: Text("推荐")), 36 | Tab(child: Text("更新")), 37 | Tab(child: Text("分类")), 38 | Tab(child: Text("排行")), 39 | Tab(child: Text("专题")), 40 | ], 41 | indicatorSize: TabBarIndicatorSize.label, 42 | isScrollable: true, 43 | //labelPadding: EdgeInsets.all(8), 44 | ), 45 | actions: [ 46 | IconButton( 47 | icon: Icon(Icons.search), 48 | tooltip: "搜索", 49 | onPressed: () { 50 | showSearch( 51 | context: context, delegate: ComicSearchBarDelegate()); 52 | //Utils.openPage(context, 1798, 1); 53 | }) //18417 54 | ], 55 | ), 56 | body: TabBarView( 57 | controller: _tabController, 58 | children: [ 59 | ComicRecommend(), 60 | ComicUpdatePage(), 61 | ComicCategoryPage(), 62 | ComicRankPage(), 63 | ComicSpecialPage(), 64 | ], 65 | )); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /lib/views/comic/comic_special.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:common_utils/common_utils.dart'; 4 | import 'package:flutter/material.dart'; 5 | import 'package:flutter_dmzj/app/api.dart'; 6 | import 'package:flutter_dmzj/app/utils.dart'; 7 | import 'package:flutter_dmzj/models/comic/comic_special_item.dart'; 8 | import 'package:flutter_easyrefresh/easy_refresh.dart'; 9 | import 'package:flutter_easyrefresh/material_footer.dart'; 10 | import 'package:flutter_easyrefresh/material_header.dart'; 11 | import 'package:fluttertoast/fluttertoast.dart'; 12 | import 'package:http/http.dart' as http; 13 | 14 | class ComicSpecialPage extends StatefulWidget { 15 | ComicSpecialPage({Key key}) : super(key: key); 16 | 17 | @override 18 | _ComicSpecialPageState createState() => _ComicSpecialPageState(); 19 | } 20 | 21 | class _ComicSpecialPageState extends State 22 | with AutomaticKeepAliveClientMixin { 23 | @override 24 | bool get wantKeepAlive => true; 25 | @override 26 | void initState() { 27 | super.initState(); 28 | loadData(); 29 | } 30 | 31 | @override 32 | void setState(fn) { 33 | if (mounted) { 34 | super.setState(fn); 35 | } 36 | } 37 | 38 | double getWidth() { 39 | var count = MediaQuery.of(context).size.width ~/ 400; 40 | if (count < 1) count = 1; 41 | return (MediaQuery.of(context).size.width - count * 8) / count - 8; 42 | } 43 | 44 | List _list = []; 45 | bool _loading = false; 46 | int _page = 0; 47 | @override 48 | Widget build(BuildContext context) { 49 | super.build(context); 50 | return EasyRefresh( 51 | onRefresh: () async { 52 | _page = 0; 53 | await loadData(); 54 | }, 55 | header: MaterialHeader(), 56 | footer: MaterialFooter(), 57 | onLoad: loadData, 58 | child: GridView.builder( 59 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 60 | crossAxisCount: MediaQuery.of(context).size.width ~/ 400 < 1 61 | ? 1 62 | : MediaQuery.of(context).size.width ~/ 400, 63 | crossAxisSpacing: 4.0, 64 | mainAxisSpacing: 4.0, 65 | childAspectRatio: getWidth() / ((getWidth() * (280 / 710)) + 44)), 66 | itemCount: _list.length, 67 | itemBuilder: (cxt, i) { 68 | var f = _list[i]; 69 | return Padding( 70 | padding: EdgeInsets.only(bottom: 4), 71 | child: Card( 72 | child: RawMaterialButton( 73 | onPressed: () { 74 | Utils.openPage(context, f.id, 5); 75 | }, 76 | child: Container( 77 | padding: EdgeInsets.all(4), 78 | child: Column( 79 | crossAxisAlignment: CrossAxisAlignment.stretch, 80 | children: [ 81 | Utils.createCacheImage(f.small_cover, 710, 280), 82 | SizedBox(height: 4), 83 | Flexible( 84 | child: Row( 85 | children: [ 86 | Expanded(child: Text(f.title)), 87 | Text( 88 | DateUtil.formatDate( 89 | DateTime.fromMillisecondsSinceEpoch( 90 | f.create_time * 1000), 91 | format: "yyyy-MM-dd"), 92 | style: TextStyle( 93 | color: Colors.grey, fontSize: 12), 94 | ), 95 | ], 96 | ), 97 | ), 98 | ], 99 | )), 100 | ), 101 | )); 102 | }), 103 | ); 104 | } 105 | 106 | Future loadData() async { 107 | try { 108 | if (_loading) { 109 | return; 110 | } 111 | setState(() { 112 | _loading = true; 113 | }); 114 | var response = await http.get(Uri.parse(Api.comicSpecial(page: _page))); 115 | List jsonMap = jsonDecode(response.body)["data"]; 116 | List detail = 117 | jsonMap.map((i) => ComicSpecialItem.fromJson(i)).toList(); 118 | if (detail != null) { 119 | setState(() { 120 | if (_page == 0) { 121 | _list = detail; 122 | } else { 123 | _list.addAll(detail); 124 | } 125 | }); 126 | if (detail.length != 0) { 127 | _page++; 128 | } else { 129 | Fluttertoast.showToast(msg: "加载完毕"); 130 | } 131 | } 132 | } catch (e) { 133 | print(e); 134 | } finally { 135 | setState(() { 136 | _loading = false; 137 | }); 138 | } 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /lib/views/download/comic_download.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/models/comic/comic_detail_model.dart'; 3 | import 'package:fluttertoast/fluttertoast.dart'; 4 | 5 | class ComicDownloadPage extends StatefulWidget { 6 | final ComicDetail detail; 7 | ComicDownloadPage(this.detail, {Key key}) : super(key: key); 8 | 9 | @override 10 | _ComicDownloadPageState createState() => _ComicDownloadPageState(); 11 | } 12 | 13 | class _ComicDownloadPageState extends State { 14 | bool _selectAll = false; 15 | List _ls = []; 16 | 17 | @override 18 | void initState() { 19 | super.initState(); 20 | _ls = []; 21 | for (var item in widget.detail.chapters) { 22 | for (var item2 in item.data) { 23 | item2.volume_name = item.title; 24 | } 25 | _ls.addAll(item.data); 26 | } 27 | } 28 | 29 | @override 30 | Widget build(BuildContext context) { 31 | return Scaffold( 32 | appBar: AppBar( 33 | title: Text('选择章节'), 34 | actions: [ 35 | IconButton( 36 | icon: Icon(Icons.select_all), 37 | onPressed: () { 38 | _selectAll = !_selectAll; 39 | for (var item in _ls.where((x) => !x.downloaded)) { 40 | setState(() { 41 | item.selected = _selectAll; 42 | }); 43 | } 44 | }) 45 | ], 46 | ), 47 | body: ListView.builder( 48 | itemCount: _ls.length, 49 | itemBuilder: (ctx, i) => CheckboxListTile( 50 | value: _ls[i].selected, 51 | title: Text( 52 | _ls[i].volume_name + ' - ' + _ls[i].chapter_title, 53 | style: TextStyle( 54 | color: _ls[i].downloaded 55 | ? Colors.grey 56 | : Theme.of(context).textTheme.bodyText1.color), 57 | ), 58 | subtitle: Text(_ls[i].downloaded ? '已下载' : '未下载'), 59 | onChanged: (e) { 60 | setState(() { 61 | if (!_ls[i].downloaded) { 62 | _ls[i].selected = e; 63 | } 64 | }); 65 | }, 66 | ), 67 | ), 68 | floatingActionButton: FloatingActionButton( 69 | heroTag: 'ComicDownload', 70 | child: Icon(Icons.file_download), 71 | onPressed: () { 72 | Fluttertoast.showToast(msg: '就快写好了'); 73 | }, 74 | ), 75 | ); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /lib/views/novel/novel_category.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:flutter/material.dart'; 4 | import 'package:flutter_dmzj/app/api.dart'; 5 | import 'package:flutter_dmzj/app/utils.dart'; 6 | import 'package:flutter_dmzj/models/comic/comic_category_item.dart'; 7 | import 'package:http/http.dart' as http; 8 | 9 | class NovelCategoryPage extends StatefulWidget { 10 | NovelCategoryPage({Key key}) : super(key: key); 11 | 12 | @override 13 | _NovelCategoryPageState createState() => _NovelCategoryPageState(); 14 | } 15 | 16 | class _NovelCategoryPageState extends State 17 | with AutomaticKeepAliveClientMixin { 18 | @override 19 | bool get wantKeepAlive => true; 20 | 21 | @override 22 | void initState() { 23 | super.initState(); 24 | loadData(); 25 | } 26 | 27 | @override 28 | void setState(fn) { 29 | if (mounted) { 30 | super.setState(fn); 31 | } 32 | } 33 | 34 | double getWidth() { 35 | var count = MediaQuery.of(context).size.width ~/ 160; 36 | if (count < 3) count = 3; 37 | return (MediaQuery.of(context).size.width - count * 8) / count - 8; 38 | } 39 | 40 | @override 41 | Widget build(BuildContext context) { 42 | super.build(context); 43 | return RefreshIndicator( 44 | onRefresh: loadData, 45 | child: GridView.builder( 46 | padding: EdgeInsets.all(8), 47 | shrinkWrap: true, 48 | physics: ScrollPhysics(), 49 | itemCount: _list.length, 50 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 51 | crossAxisCount: MediaQuery.of(context).size.width ~/ 160 < 3 52 | ? 3 53 | : MediaQuery.of(context).size.width ~/ 160, 54 | crossAxisSpacing: 4.0, 55 | mainAxisSpacing: 4.0, 56 | childAspectRatio: getWidth() / (getWidth() + 32)), 57 | itemBuilder: (context, i) => Container( 58 | child: Card( 59 | child: InkWell( 60 | onTap: () { 61 | Utils.openPage(context, _list[i].tag_id, 13, 62 | title: _list[i].title); 63 | }, 64 | child: Column( 65 | children: [ 66 | ClipRRect( 67 | borderRadius: BorderRadius.circular(4), 68 | child: Utils.createCacheImage(_list[i].cover, 200, 200)), 69 | SizedBox(height: 4), 70 | Flexible( 71 | child: Text(_list[i].title), 72 | ), 73 | ], 74 | ), 75 | ), 76 | ), 77 | ), 78 | ), 79 | ); 80 | } 81 | 82 | List _list = []; 83 | bool _loading = false; 84 | Future loadData() async { 85 | try { 86 | if (_loading) { 87 | return; 88 | } 89 | setState(() { 90 | _loading = true; 91 | }); 92 | var response = await http.get(Uri.parse(Api.novelCategory)); 93 | List jsonMap = jsonDecode(response.body); 94 | List detail = 95 | jsonMap.map((i) => ComicCategoryItem.fromJson(i)).toList(); 96 | if (detail != null) { 97 | setState(() { 98 | _list = detail; 99 | }); 100 | } 101 | } catch (e) { 102 | print(e); 103 | } finally { 104 | setState(() { 105 | _loading = false; 106 | }); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /lib/views/novel/novel_home.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/app/utils.dart'; 3 | import 'package:flutter_dmzj/views/novel/novel_category.dart'; 4 | import 'package:flutter_dmzj/views/novel/novel_rank.dart'; 5 | import 'package:flutter_dmzj/views/novel/novel_recommend.dart'; 6 | import 'package:flutter_dmzj/views/novel/novel_search.dart'; 7 | import 'package:flutter_dmzj/views/novel/novel_update.dart'; 8 | 9 | class NovelHomePage extends StatefulWidget { 10 | @override 11 | _NovelHomePageState createState() => _NovelHomePageState(); 12 | } 13 | 14 | class _NovelHomePageState extends State 15 | with TickerProviderStateMixin { 16 | TabController _tabController; 17 | 18 | @override 19 | void initState() { 20 | super.initState(); 21 | _tabController = TabController(length: 4, vsync: this); 22 | Utils.changeNovelHomeTabIndex.on().listen((e) { 23 | _tabController.animateTo(e); 24 | }); 25 | } 26 | 27 | @override 28 | Widget build(BuildContext context) { 29 | return Scaffold( 30 | appBar: AppBar( 31 | title: TabBar( 32 | controller: _tabController, 33 | tabs: [ 34 | Tab(child: Text("推荐")), 35 | Tab(child: Text("更新")), 36 | Tab(child: Text("分类")), 37 | Tab(child: Text("排行")) 38 | ], 39 | indicatorSize: TabBarIndicatorSize.label, 40 | //labelPadding: EdgeInsets.all(8), 41 | ), 42 | actions: [ 43 | IconButton( 44 | icon: Icon(Icons.search), 45 | tooltip: "搜索", 46 | onPressed: () { 47 | showSearch( 48 | context: context, delegate: NovelSearchBarDelegate()); 49 | }, 50 | ) 51 | ], 52 | ), 53 | body: TabBarView( 54 | controller: _tabController, 55 | children: [ 56 | NovelRecommend(), 57 | NovelUpdatePage(), 58 | NovelCategoryPage(), 59 | NovelRankPage(), 60 | ], 61 | )); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /lib/views/other/comment_detail_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class CommnetDetailPage extends StatefulWidget { 4 | final int commentId; 5 | 6 | CommnetDetailPage(this.commentId, {Key key}) : super(key: key); 7 | 8 | @override 9 | _CommnetDetailPageState createState() => _CommnetDetailPageState(); 10 | } 11 | 12 | class _CommnetDetailPageState extends State { 13 | @override 14 | Widget build(BuildContext context) { 15 | return Scaffold( 16 | appBar: AppBar( 17 | title: Text('评论详情'), 18 | ), 19 | body: Text(widget.commentId.toString()), 20 | ); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/views/other/web_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:share/share.dart'; 3 | import 'package:url_launcher/url_launcher.dart'; 4 | import 'package:webview_flutter/webview_flutter.dart'; 5 | 6 | class WebViewPage extends StatefulWidget { 7 | final String url; 8 | WebViewPage(this.url, {Key key}) : super(key: key); 9 | 10 | @override 11 | _WebViewPageState createState() => _WebViewPageState(); 12 | } 13 | 14 | class _WebViewPageState extends State { 15 | WebViewController _controller; 16 | String _title = "网页加载中..."; 17 | 18 | @override 19 | void setState(fn) { 20 | if (mounted) { 21 | super.setState(fn); 22 | } 23 | } 24 | 25 | @override 26 | Widget build(BuildContext context) { 27 | return Scaffold( 28 | appBar: AppBar( 29 | title: Text(_title), 30 | actions: [ 31 | IconButton( 32 | icon: Icon(Icons.share), 33 | onPressed: () async { 34 | Share.share( 35 | "${await _controller.getTitle()}\r\n${await _controller.currentUrl()}"); 36 | }), 37 | IconButton( 38 | icon: Icon(Icons.open_in_browser), 39 | onPressed: () async { 40 | launch(await _controller.currentUrl()); 41 | }) 42 | ], 43 | ), 44 | body: WebView( 45 | onWebViewCreated: (c) { 46 | _controller = c; 47 | }, 48 | initialUrl: widget.url, 49 | javascriptMode: JavascriptMode.unrestricted, 50 | userAgent: "", 51 | onPageFinished: (e) async { 52 | var title = await _controller.getTitle(); 53 | setState(() { 54 | _title = title; 55 | }); 56 | }, 57 | ), 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /lib/views/reader/comic_tc.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/app/user_helper.dart'; 3 | import 'package:flutter_dmzj/models/comic/comic_chapter_view_point.dart'; 4 | 5 | class ComicTCPage extends StatefulWidget { 6 | final List list; 7 | final int comicId; 8 | final int chapterId; 9 | ComicTCPage(this.list, this.comicId, this.chapterId, {Key key}) 10 | : super(key: key); 11 | 12 | @override 13 | ComicTCPageState createState() => ComicTCPageState(); 14 | } 15 | 16 | class ComicTCPageState extends State { 17 | @override 18 | void setState(fn) { 19 | if (mounted) { 20 | super.setState(fn); 21 | } 22 | } 23 | 24 | TextEditingController _textEditingController = TextEditingController(); 25 | @override 26 | Widget build(BuildContext context) { 27 | return Scaffold( 28 | appBar: AppBar( 29 | title: Text("吐槽"), 30 | ), 31 | body: SingleChildScrollView( 32 | padding: EdgeInsets.only(left: 8, right: 8, top: 8, bottom: 48), 33 | child: Wrap( 34 | children: widget.list.map((f) { 35 | var color = 0.2; 36 | if (f.num / 100 >= 1) { 37 | color = 1; 38 | } else { 39 | color = (f.num / 100) + 0.2; 40 | if (color > 1) { 41 | color = 1; 42 | } 43 | } 44 | return Padding( 45 | padding: EdgeInsets.all(2), 46 | child: InkWell( 47 | onTap: () async { 48 | var result = await UserHelper.comicLikeViewPoint(f.id); 49 | if (result) { 50 | setState(() { 51 | f.num++; 52 | }); 53 | } 54 | }, 55 | child: Container( 56 | padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4), 57 | decoration: BoxDecoration( 58 | color: Theme.of(context).accentColor.withOpacity(color), 59 | borderRadius: BorderRadius.circular(8)), 60 | child: Text( 61 | f.content, 62 | style: TextStyle(color: Colors.white), 63 | ), 64 | ), 65 | ), 66 | ); 67 | }).toList(), 68 | ), 69 | ), 70 | bottomSheet: Container( 71 | decoration: BoxDecoration( 72 | border: 73 | Border(top: BorderSide(color: Colors.grey.withOpacity(0.2)))), 74 | height: 48, 75 | width: double.infinity, 76 | child: Row( 77 | children: [ 78 | Expanded( 79 | child: Padding( 80 | padding: EdgeInsets.all(4), 81 | child: TextField( 82 | controller: _textEditingController, 83 | decoration: InputDecoration( 84 | contentPadding: EdgeInsets.symmetric(horizontal: 8), 85 | border: OutlineInputBorder(borderSide: BorderSide()), 86 | hintText: "说点什么吧~"), 87 | ), 88 | ), 89 | ), 90 | FlatButton.icon( 91 | onPressed: () async { 92 | if (_textEditingController.text.isEmpty) { 93 | return; 94 | } 95 | var result = await UserHelper.comicAddViewPoint( 96 | widget.comicId, 97 | widget.chapterId, 98 | _textEditingController.text); 99 | if (result) { 100 | setState(() { 101 | widget.list.add(ComicChapterViewPoint( 102 | content: _textEditingController.text, 103 | num: 0, 104 | page: 0)); 105 | }); 106 | _textEditingController.text = ""; 107 | } 108 | }, 109 | icon: Icon(Icons.send), 110 | label: Text("发送")) 111 | ], 112 | ), 113 | ), 114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /lib/views/settings/comic_reader_settings.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/app/app_setting.dart'; 3 | import 'package:provider/provider.dart'; 4 | 5 | class ComicReaderSettings extends StatefulWidget { 6 | ComicReaderSettings({Key key}) : super(key: key); 7 | 8 | @override 9 | _ComicReaderSettingsState createState() => _ComicReaderSettingsState(); 10 | } 11 | 12 | class _ComicReaderSettingsState extends State { 13 | @override 14 | Widget build(BuildContext context) { 15 | return Scaffold( 16 | appBar: AppBar( 17 | title: Text('漫画阅读设置'), 18 | ), 19 | body: ListView( 20 | children: [ 21 | SwitchListTile( 22 | title: Text( 23 | "使用系统亮度", 24 | ), 25 | value: Provider.of(context).comicSystemBrightness, 26 | onChanged: (e) { 27 | Provider.of(context, listen: false) 28 | .changeComicSystemBrightness(e); 29 | }), 30 | !Provider.of(context).comicSystemBrightness 31 | ? Row( 32 | children: [ 33 | SizedBox(width: 12), 34 | Icon( 35 | Icons.brightness_2, 36 | size: 18, 37 | ), 38 | Expanded( 39 | child: Slider( 40 | value: Provider.of(context) 41 | .comicBrightness, 42 | max: 1, 43 | min: 0.01, 44 | onChanged: (e) { 45 | Provider.of(context, listen: false) 46 | .changeBrightness(e); 47 | })), 48 | Icon(Icons.brightness_5, size: 18), 49 | SizedBox(width: 12), 50 | ], 51 | ) 52 | : Container(), 53 | SwitchListTile( 54 | title: Text( 55 | "使用网页API", 56 | ), 57 | subtitle: Text( 58 | "网页API部分单行本不分页", 59 | style: TextStyle(color: Colors.grey), 60 | ), 61 | value: Provider.of(context).comicWebApi, 62 | onChanged: (e) { 63 | Provider.of(context, listen: false) 64 | .changeComicWebApi(e); 65 | }), 66 | SwitchListTile( 67 | title: Text( 68 | "竖向阅读", 69 | ), 70 | value: Provider.of(context).comicVerticalMode, 71 | onChanged: (e) { 72 | Provider.of(context, listen: false) 73 | .changeComicVertical(e); 74 | //Navigator.pop(context); 75 | }), 76 | !Provider.of(context).comicVerticalMode 77 | ? SwitchListTile( 78 | title: Text( 79 | "日漫模式", 80 | ), 81 | value: Provider.of(context).comicReadReverse, 82 | onChanged: (e) { 83 | Provider.of(context, listen: false) 84 | .changeReadReverse(e); 85 | }) 86 | : Container(), 87 | SwitchListTile( 88 | title: Text( 89 | "屏幕常亮", 90 | ), 91 | value: Provider.of(context).comicWakelock, 92 | onChanged: (e) { 93 | Provider.of(context, listen: false) 94 | .changeComicWakelock(e); 95 | }), 96 | SwitchListTile( 97 | title: Text( 98 | "全屏阅读", 99 | ), 100 | value: Provider.of(context).comicReadShowStatusBar, 101 | onChanged: (e) { 102 | Provider.of(context, listen: false) 103 | .changeComicReadShowStatusBar(e); 104 | }), 105 | SwitchListTile( 106 | title: Text( 107 | "显示状态信息", 108 | ), 109 | value: Provider.of(context).comicReadShowstate, 110 | onChanged: (e) { 111 | Provider.of(context, listen: false) 112 | .changeComicReadShowState(e); 113 | }), 114 | // SwitchListTile( 115 | // title: Text( 116 | // "音量键翻页", 117 | // 118 | // ), 119 | // value: false, 120 | // onChanged: (e) => {}) 121 | ], 122 | ), 123 | ); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /lib/views/user/my_comment_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/app/user_info.dart'; 3 | import 'package:flutter_dmzj/widgets/user_comment_widget.dart'; 4 | import 'package:provider/provider.dart'; 5 | 6 | class MyCommentPage extends StatefulWidget { 7 | MyCommentPage({Key key}) : super(key: key); 8 | 9 | @override 10 | _MyCommentPageState createState() => _MyCommentPageState(); 11 | } 12 | 13 | class _MyCommentPageState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return DefaultTabController( 17 | length: 3, 18 | child: Scaffold( 19 | appBar: AppBar( 20 | title: Text("我的评论"), 21 | bottom: TabBar(tabs: [ 22 | Tab(text: "漫画"), 23 | Tab(text: "小说"), 24 | Tab(text: "新闻"), 25 | ]), 26 | ), 27 | body: TabBarView(children: [ 28 | UserCommentWidget( 29 | int.parse(Provider.of(context).loginInfo.uid ?? 0), 30 | type: 0, 31 | ), 32 | UserCommentWidget( 33 | int.parse(Provider.of(context).loginInfo.uid ?? 0), 34 | type: 1, 35 | ), 36 | UserCommentWidget( 37 | int.parse(Provider.of(context).loginInfo.uid ?? 0), 38 | type: 2, 39 | ) 40 | ]), 41 | ), 42 | ); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /lib/views/user/user_bind_phone.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class UserBindPhoneWidget extends StatefulWidget { 4 | UserBindPhoneWidget({Key key}) : super(key: key); 5 | 6 | @override 7 | _UserBindPhoneWidgetState createState() => _UserBindPhoneWidgetState(); 8 | } 9 | 10 | class _UserBindPhoneWidgetState extends State { 11 | @override 12 | Widget build(BuildContext context) { 13 | return Column( 14 | children: [ 15 | 16 | ], 17 | ); 18 | } 19 | } -------------------------------------------------------------------------------- /lib/views/user/user_page.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/app/user_info.dart'; 3 | import 'package:flutter_dmzj/app/utils.dart'; 4 | 5 | import 'package:provider/provider.dart'; 6 | 7 | class UserPage extends StatefulWidget { 8 | UserPage({Key key}) : super(key: key); 9 | 10 | _UserPageState createState() => _UserPageState(); 11 | } 12 | 13 | class _UserPageState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return Scaffold( 17 | appBar: AppBar( 18 | title: Row( 19 | children: [ 20 | Container( 21 | height: 36, 22 | width: 36, 23 | child: CircleAvatar( 24 | backgroundImage: Utils.createCachedImageProvider( 25 | Provider.of(context).userProfile?.cover), 26 | ), 27 | ), 28 | SizedBox(width: 12), 29 | Text(Provider.of(context).loginInfo?.nickname), 30 | ], 31 | ), 32 | actions: [ 33 | FlatButton( 34 | child: Text("退出登录"), 35 | textColor: Colors.white, 36 | onPressed: () { 37 | showDialog( 38 | context: context, 39 | builder: (_) => AlertDialog( 40 | title: Text("退出登录"), 41 | content: Text("确定要退出登录吗?"), 42 | actions: [ 43 | new FlatButton( 44 | child: new Text("取消"), 45 | onPressed: () { 46 | Navigator.of(context).pop(); 47 | }, 48 | ), 49 | new FlatButton( 50 | child: new Text("确定"), 51 | onPressed: () { 52 | Provider.of(context).logout(); 53 | Navigator.of(context).pop(); 54 | Navigator.of(context).pop(); 55 | }, 56 | ) 57 | ], 58 | )); 59 | }, 60 | ) 61 | ], 62 | ), 63 | body: Text(Provider.of(context).loginInfo?.nickname ?? ""), 64 | ); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /lib/widgets/app_banner.dart: -------------------------------------------------------------------------------- 1 | import 'package:cached_network_image/cached_network_image.dart'; 2 | import 'package:carousel_slider/carousel_slider.dart'; 3 | import 'package:flutter/material.dart'; 4 | 5 | class AppBanner extends StatefulWidget { 6 | final List items; 7 | 8 | AppBanner({Key key, this.items}) : super(key: key); 9 | 10 | _AppBannerState createState() => _AppBannerState(); 11 | } 12 | 13 | class _AppBannerState extends State { 14 | int currentBannerIndex = 0; 15 | @override 16 | Widget build(BuildContext context) { 17 | return Container( 18 | padding: EdgeInsets.all(8), 19 | constraints: BoxConstraints(maxWidth: 600), 20 | child: Stack( 21 | alignment: AlignmentDirectional.bottomEnd, 22 | children: [ 23 | ClipRRect( 24 | borderRadius: BorderRadius.circular(8), 25 | child: CarouselSlider( 26 | options: CarouselOptions( 27 | onPageChanged: (i, e) { 28 | setState(() { 29 | currentBannerIndex = i; 30 | }); 31 | }, 32 | aspectRatio: 7.5 / 4, 33 | viewportFraction: 1.0, 34 | autoPlay: true, 35 | ), 36 | items: widget.items.length != 0 37 | ? widget.items 38 | : [ 39 | Center( 40 | child: CircularProgressIndicator(), 41 | ) 42 | ], 43 | ), 44 | ), 45 | Positioned( 46 | right: 8.0, 47 | bottom: 4.0, 48 | child: Row( 49 | mainAxisAlignment: MainAxisAlignment.center, 50 | children: widget.items.map((index) { 51 | return Container( 52 | width: 8.0, 53 | height: 8.0, 54 | margin: 55 | EdgeInsets.symmetric(vertical: 10.0, horizontal: 2.0), 56 | decoration: BoxDecoration( 57 | shape: BoxShape.circle, 58 | color: currentBannerIndex == widget.items.indexOf(index) 59 | ? Theme.of(context).accentColor 60 | : Color.fromRGBO(0, 0, 0, 0.4)), 61 | ); 62 | }).toList(), 63 | )) 64 | ], 65 | ), 66 | ); 67 | } 68 | } 69 | 70 | class BannerImageItem extends StatelessWidget { 71 | final String pic; 72 | final Function onTaped; 73 | final String title; 74 | BannerImageItem({Key key, this.pic, this.onTaped, this.title = ""}) 75 | : super(key: key); 76 | 77 | @override 78 | Widget build(BuildContext context) { 79 | return InkWell( 80 | onTap: onTaped, 81 | child: Stack( 82 | alignment: AlignmentDirectional.bottomStart, 83 | fit: StackFit.expand, 84 | children: [ 85 | CachedNetworkImage( 86 | imageUrl: pic, 87 | fit: BoxFit.cover, 88 | httpHeaders: {"Referer": "http://www.dmzj.com/"}, 89 | placeholder: (context, url) => Center( 90 | child: Center(child: Icon(Icons.photo)), 91 | ), 92 | errorWidget: (context, url, error) => 93 | Center(child: Icon(Icons.error)), 94 | ), 95 | Positioned( 96 | bottom: 4, 97 | left: 8, 98 | child: Container( 99 | padding: EdgeInsets.all(8), 100 | child: Text(title, 101 | style: TextStyle( 102 | color: Colors.white, 103 | shadows: [ 104 | Shadow( 105 | blurRadius: 6.0, 106 | color: Colors.black26, 107 | offset: Offset(2.0, 2.0), 108 | ), 109 | ], 110 | )), 111 | )) 112 | ], 113 | ), 114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /lib/widgets/icon_text_button.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | class IconTextButton extends StatefulWidget { 4 | final Icon icon; 5 | final String title; 6 | final Function onTap; 7 | IconTextButton(this.icon, this.title, this.onTap, {Key key}) 8 | : super(key: key); 9 | 10 | _IconTextButtonState createState() => _IconTextButtonState(); 11 | } 12 | 13 | class _IconTextButtonState extends State { 14 | @override 15 | Widget build(BuildContext context) { 16 | return Container( 17 | child: Expanded( 18 | child: InkWell( 19 | onTap: widget.onTap, 20 | child: Container( 21 | padding: EdgeInsets.fromLTRB(8, 16, 8, 16), 22 | child: Row( 23 | mainAxisAlignment: MainAxisAlignment.center, 24 | children: [ 25 | widget.icon, 26 | Padding( 27 | padding: EdgeInsets.only(left: 8.0), 28 | child: Text(widget.title)) 29 | ], 30 | ), 31 | ), 32 | )), 33 | ); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/widgets/image_view.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:photo_view/photo_view.dart'; 3 | 4 | class ImageView extends StatefulWidget { 5 | ImageView({Key key}) : super(key: key); 6 | 7 | _ImageViewState createState() => _ImageViewState(); 8 | } 9 | 10 | class _ImageViewState extends State { 11 | @override 12 | Widget build(BuildContext context) { 13 | return Scaffold( 14 | appBar: AppBar( 15 | title: Text("2333"), 16 | ), 17 | bottomNavigationBar: FlatButton( 18 | onPressed: ()=>print("object"), 19 | textColor: Colors.white, 20 | child: Text("下载"), 21 | ), 22 | body: Container( 23 | child: PhotoView( 24 | imageProvider: AssetImage("assets/large-image.jpg"), 25 | )), 26 | ); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /lib/widgets/user_subscribe_widget.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:flutter_dmzj/app/utils.dart'; 3 | import 'package:flutter_dmzj/models/user/user_subscribe_item.dart'; 4 | 5 | class UserSubscribeWidget extends StatefulWidget { 6 | final List list; 7 | final int type; 8 | UserSubscribeWidget(this.list, {this.type = 0, Key key}) : super(key: key); 9 | 10 | @override 11 | _UserSubscribeWidgetState createState() => _UserSubscribeWidgetState(); 12 | } 13 | 14 | class _UserSubscribeWidgetState extends State { 15 | double getWidth() { 16 | var count = MediaQuery.of(context).size.width ~/ 160; 17 | if (count < 3) count = 3; 18 | return (MediaQuery.of(context).size.width - count * 8) / count - 8; 19 | } 20 | 21 | @override 22 | Widget build(BuildContext context) { 23 | return widget.list.length != 0 24 | ? GridView.builder( 25 | shrinkWrap: true, 26 | padding: EdgeInsets.symmetric(vertical: 8, horizontal: 4), 27 | physics: ScrollPhysics(), 28 | itemCount: widget.list.length, 29 | gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( 30 | crossAxisCount: MediaQuery.of(context).size.width ~/ 160 < 3 31 | ? 3 32 | : MediaQuery.of(context).size.width ~/ 160, 33 | crossAxisSpacing: 2.0, 34 | mainAxisSpacing: 4.0, 35 | childAspectRatio: 36 | getWidth() / ((getWidth() * (360 / 270)) + 64)), 37 | itemBuilder: (context, i) => _getComicItemBuilder( 38 | context, 39 | widget.list[i].id, 40 | widget.type + 1, 41 | widget.list[i].sub_img, 42 | widget.list[i].name, 43 | '更新:' + widget.list[i].sub_update, 44 | widget.list[i].status), 45 | ) 46 | : Center( 47 | child: Container( 48 | padding: EdgeInsets.all(24), 49 | child: Text( 50 | "什么都没有呢~", 51 | style: TextStyle(color: Colors.grey), 52 | ), 53 | ), 54 | ); 55 | } 56 | 57 | Widget _getComicItemBuilder(BuildContext context, int id, int type, 58 | String pic, String title, String lastUpdate, String view) { 59 | return Card( 60 | child: InkWell( 61 | onTap: () => Utils.openPage(context, id, type, title: title), 62 | child: Container( 63 | child: Column( 64 | crossAxisAlignment: CrossAxisAlignment.stretch, 65 | children: [ 66 | Utils.createCacheImage(pic, 270, 360), 67 | Padding( 68 | padding: EdgeInsets.all(4), 69 | child: Text( 70 | title, 71 | maxLines: 1, 72 | overflow: TextOverflow.ellipsis, 73 | ), 74 | ), 75 | Flexible( 76 | child: Padding( 77 | padding: EdgeInsets.symmetric(horizontal: 4), 78 | child: Text( 79 | lastUpdate, 80 | maxLines: 1, 81 | overflow: TextOverflow.ellipsis, 82 | style: TextStyle(color: Colors.grey, fontSize: 12.0), 83 | ), 84 | )), 85 | Flexible( 86 | child: Padding( 87 | padding: EdgeInsets.symmetric(horizontal: 4), 88 | child: Text( 89 | view, 90 | maxLines: 1, 91 | overflow: TextOverflow.ellipsis, 92 | style: TextStyle(color: Colors.grey, fontSize: 12.0), 93 | ), 94 | ), 95 | ), 96 | ], 97 | ), 98 | )), 99 | ); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /new_version.json: -------------------------------------------------------------------------------- 1 | { 2 | "version":"1.2.0", 3 | "version_code":"210616", 4 | "message":"更新API", 5 | "android_url":"https://xiaoyaocz.lanzoux.com/s/dmzj", 6 | "ios_url":"", 7 | "hide_banner":false 8 | } -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: flutter_dmzj 2 | description: A new Flutter project. 3 | 4 | # The following defines the version and build number for your application. 5 | # A version number is three numbers separated by dots, like 1.2.43 6 | # followed by an optional build number separated by a +. 7 | # Both the version and the builder number may be overridden in flutter 8 | # build by specifying --build-name and --build-number, respectively. 9 | # In Android, build-name is used as versionName while build-number used as versionCode. 10 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 11 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 12 | # Read more about iOS versioning at 13 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 14 | version: 1.2.1+220408 15 | 16 | environment: 17 | sdk: ">=2.1.0 <3.0.0" 18 | 19 | dependencies: 20 | flutter: 21 | sdk: flutter 22 | platform: ^3.1.0 23 | 24 | # The following adds the Cupertino Icons font to your application. 25 | # Use with the CupertinoIcons class for iOS style icons. 26 | cupertino_icons: ^1.0.4 27 | http: ^0.13.1 28 | flutter_spinkit: ^5.1.0 29 | # 透明图片占位 30 | transparent_image: ^2.0.0 31 | provider: ^6.0.2 32 | shared_preferences: ^2.0.13 33 | # 缓存图片 34 | cached_network_image: ^3.2.0 35 | event_bus: ^2.0.0 36 | carousel_slider: ^4.0.0 37 | common_utils: ^2.1.0 38 | webview_flutter: ^3.0.2 39 | photo_view: ^0.13.0 40 | fluttertoast: ^8.0.8 41 | sqflite: ^2.0.2 42 | url_launcher: ^6.0.20 43 | share: ^2.0.4 44 | flutter_easyrefresh: ^2.2.1 45 | html_unescape: ^2.0.0 46 | # 阅读界面电量监听 47 | battery: ^2.0.3 48 | # 阅读界面网络状态监听 49 | connectivity: ^3.0.6 50 | flutter_cache_manager: ^3.3.0 51 | wakelock: ^0.6.1+2 52 | screen_brightness: ^0.1.4 53 | path_provider: ^2.0.9 54 | preload_page_view: ^0.1.6 55 | package_info: ^2.0.0 56 | crypton: ^2.0.1 57 | crypto: ^3.0.1 58 | protobuf: ^2.0.0 59 | dio: ^4.0.0 60 | intl: ^0.17.0 61 | flutter_android_volume_keydown: ^1.0.0 62 | 63 | dev_dependencies: 64 | flutter_test: 65 | sdk: flutter 66 | 67 | 68 | # For information on the generic Dart part of this file, see the 69 | # following page: https://dart.dev/tools/pub/pubspec 70 | 71 | # The following section is specific to Flutter. 72 | flutter: 73 | 74 | # The following line ensures that the Material Icons font is 75 | # included with your application, so that you can use the icons in 76 | # the material Icons class. 77 | uses-material-design: true 78 | 79 | # To add assets to your application, add an assets section, like this: 80 | assets: 81 | - assets/ 82 | 83 | # An image asset can refer to one or more resolution-specific "variants", see 84 | # https://flutter.dev/assets-and-images/#resolution-aware. 85 | 86 | # For details regarding adding assets from package dependencies, see 87 | # https://flutter.dev/assets-and-images/#from-packages 88 | 89 | # To add custom fonts to your application, add a fonts section here, 90 | # in this "flutter" section. Each entry in this list should have a 91 | # "family" key with the font family name, and a "fonts" key with a 92 | # list giving the asset and other descriptors for the font. For 93 | # example: 94 | # fonts: 95 | # - family: Schyler 96 | # fonts: 97 | # - asset: fonts/Schyler-Regular.ttf 98 | # - asset: fonts/Schyler-Italic.ttf 99 | # style: italic 100 | # - family: Trajan Pro 101 | # fonts: 102 | # - asset: fonts/TrajanPro.ttf 103 | # - asset: fonts/TrajanPro_Bold.ttf 104 | # weight: 700 105 | # 106 | # For details regarding fonts from package dependencies, 107 | # see https://flutter.dev/custom-fonts/#from-packages 108 | -------------------------------------------------------------------------------- /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 that Flutter provides. 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_dmzj/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(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 | --------------------------------------------------------------------------------