Commit 68a4c50a70db6f568d0977212e4a9be36a82b573

Authored by xiaoyu
2 parents 5daad4bc 2879454a

Merge remote-tracking branch 'origin/feat-wqf-payment' into xiaoyu_cocossteve

添加带参数打开游戏
Showing 90 changed files with 2710 additions and 1097 deletions
android/app/build.gradle
... ... @@ -29,7 +29,7 @@ android {
29 29 namespace "com.kouyuxingqiu.wow_english"
30 30 // compileSdkVersion flutter.compileSdkVersion
31 31 compileSdkVersion 33
32   - // 展示没有ndk需求
  32 + // 暂时没有ndk需求
33 33 // ndkVersion flutter.ndkVersion
34 34  
35 35 compileOptions {
... ... @@ -87,4 +87,5 @@ dependencies {
87 87 implementation 'com.geyifeng.immersionbar:immersionbar:3.2.2'
88 88 // kotlin扩展(可选)
89 89 implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.2'
  90 + implementation 'io.keyss.android.library:bjgame:1.0.2'
90 91 }
... ...
android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/MainActivity.kt
... ... @@ -8,6 +8,7 @@ import androidx.core.view.WindowInsetsCompat
8 8 import androidx.core.view.WindowInsetsControllerCompat
9 9 import com.gyf.immersionbar.BarHide
10 10 import com.gyf.immersionbar.ImmersionBar
  11 +import com.kouyuxingqiu.wow_english.methodChannels.GameMethodChannel
11 12 import com.kouyuxingqiu.wow_english.methodChannels.SingSoungMethodChannel
12 13 import io.flutter.embedding.android.FlutterActivity
13 14  
... ... @@ -17,7 +18,10 @@ class MainActivity : FlutterActivity() {
17 18 Log.i("WowEnglish", "MainActivity onCreate")
18 19 //隐藏状态栏和导航栏
19 20 ImmersionBar.with(this).hideBar(BarHide.FLAG_HIDE_BAR).init()
20   - flutterEngine?.let { SingSoungMethodChannel(this, it) }
  21 + flutterEngine?.let {
  22 + SingSoungMethodChannel(this, it)
  23 + GameMethodChannel(this, it)
  24 + }
21 25 }
22 26  
23 27 override fun onResume() {
... ...
android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/methodChannels/GameMethodChannel.kt 0 → 100644
  1 +package com.kouyuxingqiu.wow_english.methodChannels
  2 +
  3 +import android.content.Intent
  4 +import android.content.Intent.getIntent
  5 +import android.util.Log
  6 +import androidx.core.content.ContextCompat.startActivity
  7 +import com.kouyuxingqiu.wow_english.singsound.SingEngineHelper
  8 +import com.kouyuxingqiu.wow_english.util.GlobalHandler
  9 +import io.flutter.embedding.android.FlutterActivity
  10 +import io.flutter.embedding.engine.FlutterEngine
  11 +import io.flutter.plugin.common.MethodChannel
  12 +import org.cocos2dx.cpp.AppActivity
  13 +import java.lang.ref.WeakReference
  14 +
  15 +
  16 +/**
  17 + * @author: stay
  18 + * @date: 2024/4/22 18:36
  19 + * @description: 游戏方法通道
  20 + */
  21 +class GameMethodChannel(activity: FlutterActivity, flutterEngine: FlutterEngine) {
  22 + private var methodChannel: MethodChannel? = null
  23 + private val TAG = "GameMethodChannel"
  24 +
  25 + companion object {
  26 + var channel: WeakReference<GameMethodChannel>? = null
  27 +
  28 + fun invokeMethod(method: String, arguments: Any?) {
  29 + channel?.get()?.methodChannel?.invokeMethod(method, arguments)
  30 + }
  31 + }
  32 +
  33 + init {
  34 + // name需与flutter端一致
  35 + methodChannel =
  36 + MethodChannel(
  37 + flutterEngine.dartExecutor.binaryMessenger,
  38 + "wow_english/game_method_channel"
  39 + )
  40 + methodChannel?.setMethodCallHandler { call, result ->
  41 + Log.d(TAG, "call=${call.method} ${call.arguments} result=$result")
  42 + when (call.method) {
  43 + "openGamePage" -> {
  44 + if (call.hasArgument("gameId")) {
  45 + val gameId = call.argument<Int>("gameId")
  46 + activity.startActivity(
  47 + Intent(activity, AppActivity::class.java).apply {
  48 + putExtra("game", gameId)
  49 + })
  50 + result.success(true)
  51 + } else {
  52 + result.success(false)
  53 + }
  54 + }
  55 + }
  56 + }
  57 + channel = WeakReference(this)
  58 + }
  59 +}
0 60 \ No newline at end of file
... ...
android/build.gradle
... ... @@ -17,6 +17,7 @@ allprojects {
17 17 google()
18 18 mavenCentral()
19 19 maven { url 'https://repo.singsound.com/repository/singsound_ginger_android_sdk/' }
  20 + maven { url 'https://maven.zjzxsl.com/repository/android-public/' }
20 21 }
21 22 }
22 23  
... ...
assets/images/apple_pay.png 0 → 100644

1.78 KB

assets/images/bg_frame_module.png 0 → 100644

54.1 KB

assets/images/bg_header_sliver.png 0 → 100644

120 KB

assets/images/btn_pay.png 0 → 100644

45.8 KB

assets/images/checked.png 0 → 100644

3.2 KB

assets/images/ic_countdown.png 0 → 100644

2.1 KB

assets/images/label_module_game.png 0 → 100644

15.7 KB

assets/images/label_module_study.png 0 → 100644

15.9 KB

assets/images/pic_module_game.png 0 → 100644

217 KB

assets/images/pic_module_study.png 0 → 100644

248 KB

assets/images/unchecked.png 0 → 100644

3.12 KB

assets/images/weixin.png 0 → 100644

3.79 KB

assets/images/zhifubao.png 0 → 100644

4.64 KB

ios/Podfile
... ... @@ -33,7 +33,7 @@ target &#39;Runner&#39; do
33 33 use_frameworks!
34 34 use_modular_headers!
35 35 pod 'SingSoundSDK'
36   -
  36 +
37 37 flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
38 38 target 'RunnerTests' do
39 39 inherit! :search_paths
... ...
ios/Runner.xcodeproj/project.pbxproj
... ... @@ -24,10 +24,7 @@
24 24 B891A6152BD21EF3006CB06E /* game_food in Resources */ = {isa = PBXBuildFile; fileRef = B891A6112BD21EEF006CB06E /* game_food */; };
25 25 B891A6162BD21EF3006CB06E /* game_halloween in Resources */ = {isa = PBXBuildFile; fileRef = B891A6122BD21EF2006CB06E /* game_halloween */; };
26 26 B891A6172BD21EF3006CB06E /* game_animal in Resources */ = {isa = PBXBuildFile; fileRef = B891A6132BD21EF3006CB06E /* game_animal */; };
27   - B891A61A2BD21F2B006CB06E /* CloseNormal.png in Resources */ = {isa = PBXBuildFile; fileRef = B891A6182BD21F2B006CB06E /* CloseNormal.png */; };
28   - B891A61B2BD21F2B006CB06E /* CloseSelected.png in Resources */ = {isa = PBXBuildFile; fileRef = B891A6192BD21F2B006CB06E /* CloseSelected.png */; };
29 27 B891A61D2BD21F6B006CB06E /* res in Resources */ = {isa = PBXBuildFile; fileRef = B891A61C2BD21F6B006CB06E /* res */; };
30   - B891A61F2BD21FA2006CB06E /* HelloWorld.png in Resources */ = {isa = PBXBuildFile; fileRef = B891A61E2BD21FA2006CB06E /* HelloWorld.png */; };
31 28 B891A7FE2BD24EFA006CB06E /* ActionData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B891A6202BD24EF9006CB06E /* ActionData.cpp */; };
32 29 B891A7FF2BD24EFA006CB06E /* AlertView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B891A6222BD24EF9006CB06E /* AlertView.cpp */; };
33 30 B891A8002BD24EFA006CB06E /* AppLinksView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B891A6242BD24EF9006CB06E /* AppLinksView.cpp */; };
... ... @@ -476,10 +473,7 @@
476 473 B891A6112BD21EEF006CB06E /* game_food */ = {isa = PBXFileReference; lastKnownFileType = folder; path = game_food; sourceTree = "<group>"; };
477 474 B891A6122BD21EF2006CB06E /* game_halloween */ = {isa = PBXFileReference; lastKnownFileType = folder; path = game_halloween; sourceTree = "<group>"; };
478 475 B891A6132BD21EF3006CB06E /* game_animal */ = {isa = PBXFileReference; lastKnownFileType = folder; path = game_animal; sourceTree = "<group>"; };
479   - B891A6182BD21F2B006CB06E /* CloseNormal.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CloseNormal.png; sourceTree = "<group>"; };
480   - B891A6192BD21F2B006CB06E /* CloseSelected.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = CloseSelected.png; sourceTree = "<group>"; };
481 476 B891A61C2BD21F6B006CB06E /* res */ = {isa = PBXFileReference; lastKnownFileType = folder; path = res; sourceTree = "<group>"; };
482   - B891A61E2BD21FA2006CB06E /* HelloWorld.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = HelloWorld.png; sourceTree = "<group>"; };
483 477 B891A6202BD24EF9006CB06E /* ActionData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ActionData.cpp; sourceTree = "<group>"; };
484 478 B891A6212BD24EF9006CB06E /* ActionData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionData.h; sourceTree = "<group>"; };
485 479 B891A6222BD24EF9006CB06E /* AlertView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AlertView.cpp; sourceTree = "<group>"; };
... ... @@ -1085,9 +1079,6 @@
1085 1079 B891A4112BCD13AB006CB06E /* Resources */ = {
1086 1080 isa = PBXGroup;
1087 1081 children = (
1088   - B891A61E2BD21FA2006CB06E /* HelloWorld.png */,
1089   - B891A6182BD21F2B006CB06E /* CloseNormal.png */,
1090   - B891A6192BD21F2B006CB06E /* CloseSelected.png */,
1091 1082 B891A61C2BD21F6B006CB06E /* res */,
1092 1083 B891A6132BD21EF3006CB06E /* game_animal */,
1093 1084 B891A6112BD21EEF006CB06E /* game_food */,
... ... @@ -1805,15 +1796,12 @@
1805 1796 buildActionMask = 2147483647;
1806 1797 files = (
1807 1798 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
1808   - B891A61B2BD21F2B006CB06E /* CloseSelected.png in Resources */,
1809 1799 B891A6152BD21EF3006CB06E /* game_food in Resources */,
1810 1800 B891A60F2BD21BBC006CB06E /* fonts in Resources */,
1811   - B891A61F2BD21FA2006CB06E /* HelloWorld.png in Resources */,
1812 1801 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
1813 1802 B891A6172BD21EF3006CB06E /* game_animal in Resources */,
1814 1803 B891A6142BD21EF3006CB06E /* game_toy in Resources */,
1815 1804 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
1816   - B891A61A2BD21F2B006CB06E /* CloseNormal.png in Resources */,
1817 1805 B891A61D2BD21F6B006CB06E /* res in Resources */,
1818 1806 B891A6162BD21EF3006CB06E /* game_halloween in Resources */,
1819 1807 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
... ... @@ -2321,15 +2309,17 @@
2321 2309 ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
2322 2310 CLANG_ENABLE_MODULES = YES;
2323 2311 CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
2324   - CURRENT_PROJECT_VERSION = 2;
2325   - DEVELOPMENT_TEAM = T8P9KW8GWH;
  2312 + CODE_SIGN_STYLE = Manual;
  2313 + CURRENT_PROJECT_VERSION = 3;
  2314 + DEVELOPMENT_TEAM = "";
  2315 + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = T8P9KW8GWH;
2326 2316 ENABLE_BITCODE = NO;
2327 2317 INFOPLIST_FILE = Runner/Info.plist;
2328 2318 LD_RUNPATH_SEARCH_PATHS = (
2329 2319 "$(inherited)",
2330 2320 "@executable_path/Frameworks",
2331 2321 );
2332   - MARKETING_VERSION = 1.0.2;
  2322 + MARKETING_VERSION = 1.0.3;
2333 2323 OTHER_CFLAGS = (
2334 2324 "-DNDEBUG",
2335 2325 "'-std=gnu99'",
... ... @@ -2457,6 +2447,8 @@
2457 2447 );
2458 2448 PRODUCT_BUNDLE_IDENTIFIER = com.kouyuxingqiu.wowenglish;
2459 2449 PRODUCT_NAME = "$(TARGET_NAME)";
  2450 + PROVISIONING_PROFILE_SPECIFIER = "";
  2451 + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "wow english";
2460 2452 SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
2461 2453 SUPPORTS_MACCATALYST = NO;
2462 2454 SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
... ... @@ -2664,8 +2656,10 @@
2664 2656 ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
2665 2657 CLANG_ENABLE_MODULES = YES;
2666 2658 CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
2667   - CURRENT_PROJECT_VERSION = 2;
2668   - DEVELOPMENT_TEAM = T8P9KW8GWH;
  2659 + CODE_SIGN_STYLE = Manual;
  2660 + CURRENT_PROJECT_VERSION = 3;
  2661 + DEVELOPMENT_TEAM = "";
  2662 + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = T8P9KW8GWH;
2669 2663 ENABLE_BITCODE = NO;
2670 2664 HEADER_SEARCH_PATHS = (
2671 2665 "$(inherited)",
... ... @@ -2694,7 +2688,7 @@
2694 2688 "$(inherited)",
2695 2689 "@executable_path/Frameworks",
2696 2690 );
2697   - MARKETING_VERSION = 1.0.2;
  2691 + MARKETING_VERSION = 1.0.3;
2698 2692 ONLY_ACTIVE_ARCH = NO;
2699 2693 OTHER_CFLAGS = "'-std=gnu99'";
2700 2694 OTHER_CPLUSPLUSFLAGS = "'-std=c++11'";
... ... @@ -2817,6 +2811,8 @@
2817 2811 );
2818 2812 PRODUCT_BUNDLE_IDENTIFIER = com.kouyuxingqiu.wowenglish;
2819 2813 PRODUCT_NAME = "$(TARGET_NAME)";
  2814 + PROVISIONING_PROFILE_SPECIFIER = "";
  2815 + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "wow english";
2820 2816 SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
2821 2817 SUPPORTS_MACCATALYST = NO;
2822 2818 SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
... ... @@ -2868,15 +2864,17 @@
2868 2864 ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
2869 2865 CLANG_ENABLE_MODULES = YES;
2870 2866 CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
2871   - CURRENT_PROJECT_VERSION = 2;
2872   - DEVELOPMENT_TEAM = T8P9KW8GWH;
  2867 + CODE_SIGN_STYLE = Manual;
  2868 + CURRENT_PROJECT_VERSION = 3;
  2869 + DEVELOPMENT_TEAM = "";
  2870 + "DEVELOPMENT_TEAM[sdk=iphoneos*]" = T8P9KW8GWH;
2873 2871 ENABLE_BITCODE = NO;
2874 2872 INFOPLIST_FILE = Runner/Info.plist;
2875 2873 LD_RUNPATH_SEARCH_PATHS = (
2876 2874 "$(inherited)",
2877 2875 "@executable_path/Frameworks",
2878 2876 );
2879   - MARKETING_VERSION = 1.0.2;
  2877 + MARKETING_VERSION = 1.0.3;
2880 2878 OTHER_CFLAGS = (
2881 2879 "-DNDEBUG",
2882 2880 "'-std=gnu99'",
... ... @@ -3004,6 +3002,8 @@
3004 3002 );
3005 3003 PRODUCT_BUNDLE_IDENTIFIER = com.kouyuxingqiu.wowenglish;
3006 3004 PRODUCT_NAME = "$(TARGET_NAME)";
  3005 + PROVISIONING_PROFILE_SPECIFIER = "";
  3006 + "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "wow english";
3007 3007 SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
3008 3008 SUPPORTS_MACCATALYST = NO;
3009 3009 SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
... ...
ios/Runner/AppDelegate.swift
... ... @@ -13,13 +13,6 @@ import Flutter
13 13 _ = XSMessageMehtodChannel(message: controller.binaryMessenger);
14 14 _ = GameMessageChannel(message: controller.binaryMessenger);
15 15  
16   -// DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 6) {
17   -// WowGameCocosManager.shared().runGame();
18   -// }
19   -// DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 15) {
20   -// WowGameCocosManager.shared().runGame();
21   -// }
22   -
23 16 return super.application(application, didFinishLaunchingWithOptions: launchOptions)
24 17 }
25 18 }
... ...
ios/Runner/GameMessageChannel.swift
... ... @@ -19,11 +19,11 @@ class GameMessageChannel: NSObject {
19 19  
20 20 func handle(_ call: FlutterMethodCall,_ result: @escaping FlutterResult) {
21 21 if (call.method == "openGamePage") {
22   - print("openGamePage")
23   - WowGameCocosManager.shared().runGame();
  22 + print("openGamePage");
  23 + let dict = call.arguments as! Dictionary<String, Any>
  24 + let gameid = dict["gameId"] as! Int
  25 + WowGameCocosManager.shared().runGame(gameid);
24 26 return
25 27 }
26   -
27 28 }
28   -
29 29 }
... ...
ios/Runner/Info.plist
... ... @@ -22,6 +22,19 @@
22 22 <string>$(FLUTTER_BUILD_NAME)</string>
23 23 <key>CFBundleSignature</key>
24 24 <string>????</string>
  25 + <key>CFBundleURLTypes</key>
  26 + <array>
  27 + <dict>
  28 + <key>CFBundleTypeRole</key>
  29 + <string>Editor</string>
  30 + <key>CFBundleURLName</key>
  31 + <string>ishowwoweng</string>
  32 + <key>CFBundleURLSchemes</key>
  33 + <array>
  34 + <string>ishowwoweng</string>
  35 + </array>
  36 + </dict>
  37 + </array>
25 38 <key>CFBundleVersion</key>
26 39 <string>$(FLUTTER_BUILD_NUMBER)</string>
27 40 <key>LSApplicationCategoryType</key>
... ...
ios/Runner/Runner.entitlements
... ... @@ -4,5 +4,9 @@
4 4 <dict>
5 5 <key>aps-environment</key>
6 6 <string>development</string>
  7 + <key>com.apple.developer.associated-domains</key>
  8 + <array>
  9 + <string>applinks:app-api.wowenglish.com.cn</string>
  10 + </array>
7 11 </dict>
8 12 </plist>
... ...
ios/Runner/Wowgame/Classes/CocosAppDelegate.cpp
... ... @@ -24,7 +24,15 @@
24 24  
25 25 #include "CocosAppDelegate.h"
26 26 #include "HelloWorldScene.h"
27   -#include "game_food/ScalingUtils.h"
  27 +
  28 +
  29 +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  30 +#include "NativeAndroid/AndroidUtils_cpp.h"
  31 +#endif
  32 +
  33 +
  34 +
  35 +
28 36 // #define USE_AUDIO_ENGINE 1
29 37  
30 38 #if USE_AUDIO_ENGINE
... ... @@ -41,11 +49,16 @@ CocosAppDelegate::CocosAppDelegate()
41 49 {
42 50 }
43 51  
44   -CocosAppDelegate::~CocosAppDelegate()
  52 +CocosAppDelegate::~CocosAppDelegate()
45 53 {
46 54 #if USE_AUDIO_ENGINE
47 55 AudioEngine::end();
48 56 #endif
  57 +
  58 + SpriteFrameCache::getInstance()->removeSpriteFrames();
  59 + Director::getInstance()->getTextureCache()->removeAllTextures();
  60 +
  61 +
49 62 }
50 63  
51 64 // if you want a different context, modify the value of glContextAttrs
... ... @@ -58,7 +71,7 @@ void CocosAppDelegate::initGLContextAttrs()
58 71 GLView::setGLContextAttrs(glContextAttrs);
59 72 }
60 73  
61   -// if you want to use the package manager to install more packages,
  74 +// if you want to use the package manager to install more packages,
62 75 // don't modify or remove this function
63 76 static int register_all_packages()
64 77 {
... ...
ios/Runner/Wowgame/Classes/HelloWorldScene.cpp
... ... @@ -71,69 +71,24 @@ bool HelloWorld::init()
71 71 return false;
72 72 }
73 73  
74   - auto visibleSize = Director::getInstance()->getVisibleSize();
75   - Vec2 origin = Director::getInstance()->getVisibleOrigin();
  74 + auto m_eventListener = EventListenerCustom::create("start_gameid", [=](EventCustom* event) {
  75 + char* pData = (char*)event->getUserData();
  76 + intptr_t gameid = (intptr_t)pData;
  77 + CCLOG("HelloWorld gameid = %d",gameid);
  78 + this->startGameById(gameid);
  79 + });
  80 + Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(m_eventListener, 1);
76 81  
77   - /////////////////////////////
78   - // 2. add a menu item with "X" image, which is clicked to quit the program
79   - // you may modify it.
80   -
81   - // add a "close" icon to exit the progress. it's an autorelease object
82   - auto closeItem = MenuItemImage::create( "CloseNormal.png","CloseSelected.png", CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
83   -
84   - if (closeItem == nullptr ||
85   - closeItem->getContentSize().width <= 0 ||
86   - closeItem->getContentSize().height <= 0)
87   - {
88   - problemLoading("'CloseNormal.png' and 'CloseSelected.png'");
89   - }
90   - else
91   - {
92   - float x = origin.x + visibleSize.width - closeItem->getContentSize().width/2;
93   - float y = origin.y + closeItem->getContentSize().height/2;
94   - closeItem->setPosition(Vec2(x,y));
95   - }
96   - auto lbl_game1 = Label::createWithTTF("food", "fonts/ComicSansMSBold.ttf", 48);
97   - auto lbl_game2 = Label::createWithTTF("halloween", "fonts/ComicSansMSBold.ttf", 48);
98   - auto lbl_game3 = Label::createWithTTF("toygamerepo", "fonts/ComicSansMSBold.ttf", 48);
99   - auto lbl_game4 = Label::createWithTTF("animal", "fonts/ComicSansMSBold.ttf", 48);
100   - auto lbl_game5 = Label::createWithTTF("exit ", "fonts/ComicSansMSBold.ttf", 48);
101   - auto btn_game1 = MenuItemLabel::create(lbl_game1, CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
102   - auto btn_game2 = MenuItemLabel::create(lbl_game2, CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
103   - auto btn_game3 = MenuItemLabel::create(lbl_game3, CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
104   - auto btn_game4 = MenuItemLabel::create(lbl_game4, CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
105   - auto btn_game5 = MenuItemLabel::create(lbl_game5, CC_CALLBACK_1(HelloWorld::menuCloseCallback, this));
106   - btn_game1->setPosition(visibleSize.width * 0.5, visibleSize.height * 0.5 + 400);
107   - btn_game2->setPosition(visibleSize.width * 0.5, visibleSize.height * 0.5 + 200);
108   - btn_game3->setPosition(visibleSize.width * 0.5, visibleSize.height * 0.5 - 0);
109   - btn_game4->setPosition(visibleSize.width * 0.5, visibleSize.height * 0.5 - 200);
110   - btn_game5->setPosition(visibleSize.width * 0.5, visibleSize.height * 0.5 - 400);
111   - btn_game1->setTag(101);
112   - btn_game2->setTag(102);
113   - btn_game3->setTag(103);
114   - btn_game4->setTag(104);
115   - btn_game5->setTag(105);
116   -
117   - // create menu, it's an autorelease object
118   - auto menu = Menu::create(closeItem, btn_game1, btn_game2, btn_game3, btn_game4,btn_game5, NULL);
119   - menu->setPosition(Vec2::ZERO);
120   - this->addChild(menu, 1);
121 82 CCLOG("HelloWorld init");
122   -
123 83 return true;
124 84 }
125 85  
126 86  
127   -void HelloWorld::menuCloseCallback(Ref* pSender)
  87 +void HelloWorld::startGameById(int gameid)
128 88 {
129   -
130   -
131   - auto node = (Node*)pSender;
132   - int tag = node -> getTag();
133   -
134   - if (tag == 101)//food
  89 + int tag = gameid;
  90 + if (tag == 1)//food
135 91 {
136   -
137 92 auto searchPaths = cocos2d::FileUtils::getInstance()->getSearchPaths();
138 93 searchPaths.push_back("game_food");
139 94 if(ScalingUtils::isSmallDevice()){
... ... @@ -152,13 +107,10 @@ void HelloWorld::menuCloseCallback(Ref* pSender)
152 107 Director::getInstance()->replaceScene(newScene);
153 108 }
154 109  
155   - if (tag == 102)//halloween
  110 + if (tag == 2)//halloween
156 111 {
157   -
158   -
159 112 auto searchPaths = cocos2d::FileUtils::getInstance()->getSearchPaths();
160 113 std::string deviceSpecificFolderName;
161   -
162 114 deviceSpecificFolderName = HResourcesConfig::RES_FOLDER_NAME_XLARGE;//TODO TEMP
163 115 searchPaths.push_back("game_halloween/" + deviceSpecificFolderName);
164 116 searchPaths.push_back("game_halloween/common");
... ... @@ -168,14 +120,11 @@ void HelloWorld::menuCloseCallback(Ref* pSender)
168 120 std::string layoutFilePath = "game_halloween/xlarge/scene_layout.scl";
169 121 HGameConfigParser parser(configFilePath);
170 122 auto gameScene = dynamic_cast<HSubGameSceneSpaceInvaders*>(parser.createGameScene(layoutFilePath));
171   - // run
172 123 Director::getInstance()->replaceScene(gameScene);
173 124 }
174 125  
175   - if (tag == 103)//toygamerepo
  126 + if (tag == 3)//toygamerepo
176 127 {
177   -
178   -
179 128 auto searchPaths = cocos2d::FileUtils::getInstance()->getSearchPaths();
180 129 std::string deviceSpecificFolderName;
181 130 deviceSpecificFolderName = ToyResourcesConfig::RES_FOLDER_NAME_XLARGE;//TODO TEMP
... ... @@ -188,13 +137,10 @@ void HelloWorld::menuCloseCallback(Ref* pSender)
188 137 // run
189 138 auto _mainScene = ToyMainMenuScene::create("graphics/main_menu/scene_layout.scl");
190 139 Director::getInstance()->replaceScene(_mainScene);
191   -
192 140 }
193 141  
194   - if (tag == 104)//animal
  142 + if (tag == 4)//animal
195 143 {
196   -
197   -
198 144 auto searchPaths = cocos2d::FileUtils::getInstance()->getSearchPaths();
199 145 std::string deviceSpecificFolderName;
200 146 deviceSpecificFolderName = ToyResourcesConfig::RES_FOLDER_NAME_XLARGE;//TODO TEMP
... ... @@ -206,13 +152,8 @@ void HelloWorld::menuCloseCallback(Ref* pSender)
206 152 srand(time(0));
207 153 auto _mainScene = AniPickLevelScene::create("");
208 154 Director::getInstance()->replaceScene(_mainScene);
209   -
210 155 }
211 156  
212   - if (tag == 105)//exit
213   - {
214   - Director::getInstance()->end();
215   - }
216 157  
217 158  
218 159  
... ... @@ -221,7 +162,7 @@ void HelloWorld::menuCloseCallback(Ref* pSender)
221 162  
222 163  
223 164  
224   -
  165 +
225 166  
226 167  
227 168  
... ...
ios/Runner/Wowgame/Classes/HelloWorldScene.h
... ... @@ -39,7 +39,7 @@ public:
39 39 // virtual void onExit() override;
40 40  
41 41 // a selector callback
42   - void menuCloseCallback(cocos2d::Ref* pSender);
  42 + void startGameById(int gameid);
43 43  
44 44 // implement the "static create()" method manually
45 45 CREATE_FUNC(HelloWorld);
... ...
ios/Runner/Wowgame/Classes/NativeIOS/RatePromptHandler_ios.h
... ... @@ -7,4 +7,5 @@
7 7  
8 8 void ratePromptHandler_nativePresentPromptIfApplicable();
9 9  
  10 +void handler_nativeExitGame();
10 11 #endif //RATE_PROMPT_HANDLER_IOS_H
... ...
ios/Runner/Wowgame/Classes/NativeIOS/RatePromptHandler_ios.mm
... ... @@ -11,4 +11,7 @@ void ratePromptHandler_nativePresentPromptIfApplicable(){
11 11 }
12 12 }
13 13  
  14 +void handler_nativeExitGame() {
  15 + [[NSNotificationCenter defaultCenter] postNotificationName:@"_kwowgamecocosexitgame" object:nil];
  16 +}
14 17  
... ...
ios/Runner/Wowgame/Classes/game_animal/AniAlertUtils.cpp
... ... @@ -12,6 +12,12 @@
12 12 #include "AniAlertView.h"
13 13 #include "AniMiscUtils.h"
14 14 #include "HelloWorldScene.h"
  15 +
  16 +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  17 +#include "RatePromptHandler_ios.h"
  18 +#endif
  19 +#include "audio/include/AudioEngine.h"
  20 +
15 21 static const int AniAlertViewTagDefault = 999;
16 22 static const int AniAlertViewTagCloseConfirm = 998;
17 23  
... ... @@ -46,15 +52,21 @@ bool AniAlertUtils::closeDialogIfNecessary(int tag){
46 52 return false;
47 53 }
48 54  
49   -#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  55 +//#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
50 56  
51 57 void AniAlertUtils::showAppCloseConfirmDialog(std::function<void()> onCancelCallback){
52 58 showTwoButtonDialog(AniAlertViewTagCloseConfirm, "Are you sure you want to quit?", "Yes, bye!", "No, let's play!", [](){
53   - //cocos2d::Director::getInstance()->end();
54   - auto scene = HelloWorld::createScene();
55   - cocos2d::Director::getInstance()->replaceScene(scene);
56   -
57   -
  59 +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  60 + cocos2d::Director::getInstance()->end();
  61 +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  62 + cocos2d::AudioEngine::stopAll();
  63 + cocos2d::Director::getInstance()->pause();
  64 + handler_nativeExitGame();
  65 +#else
  66 + cocos2d::Director::getInstance()->end();
  67 +#endif
  68 + //auto scene = HelloWorld::createScene();
  69 + //cocos2d::Director::getInstance()->replaceScene(scene);
58 70  
59 71 }, onCancelCallback);
60 72 }
... ... @@ -63,4 +75,4 @@ bool AniAlertUtils::closeAppCloseConfirmDialogIfNecessary(){
63 75 return closeDialogIfNecessary(AniAlertViewTagCloseConfirm);
64 76 }
65 77  
66   -#endif
  78 +//#endif
... ...
ios/Runner/Wowgame/Classes/game_animal/AniAlertUtils.h
... ... @@ -19,10 +19,10 @@ public:
19 19 static void showTwoButtonDialog(int tag, std::string text, std::string okButtonText, std::string cancelButtonText, std::function<void()> onOKCallback, std::function<void()> onCancelCallback = [](){});
20 20 static bool closeDialogIfNecessary(int tag);
21 21  
22   -#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  22 +//#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
23 23 static void showAppCloseConfirmDialog(std::function<void()> onCancelCallback);
24 24 static bool closeAppCloseConfirmDialogIfNecessary();
25   -#endif
  25 +//#endif
26 26 };
27 27  
28 28 #endif /* AniAlertUtils_h */
... ...
ios/Runner/Wowgame/Classes/game_animal/AniParentScene.cpp
... ... @@ -186,7 +186,7 @@ bool AniParentScene::touchHandlerForWidget(std::string objectName, cocos2d::ui::
186 186 // _AniScenarioHandler->pauseScenario();
187 187 // _AniScenarioHandler->stopAllActions();
188 188 AniSoundsRepo::stopAllSounds();
189   - cocos2d::Director::getInstance()->popScene();
  189 + cocos2d::Director::getInstance()->end();
190 190 _sceneDismissCallback();
191 191 return true;
192 192 } /*else if(objectName == "backgroundMusicButton" && touchEventType == cocos2d::ui::Widget::TouchEventType::ENDED){
... ... @@ -497,9 +497,9 @@ void AniParentScene::showTOSAcceptPopup(std::function&lt;void()&gt; onAccept){
497 497 if (n->isShowingParentalGate()) {
498 498 n->hideParentalGate();
499 499 } else {
500   - //cocos2d::Director::getInstance()->end();
501   - auto scene = HelloWorld::createScene();
502   - cocos2d::Director::getInstance()->replaceScene(scene);
  500 + cocos2d::Director::getInstance()->end();
  501 + //auto scene = HelloWorld::createScene();
  502 + //cocos2d::Director::getInstance()->replaceScene(scene);
503 503 }
504 504 }
505 505 }
... ... @@ -524,9 +524,9 @@ void AniParentScene::showAniLevelPickerLayer(std::function&lt;void()&gt; onLayerDismis
524 524 [&](cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event, cocos2d::Node *n) {
525 525 if (keyCode == cocos2d::EventKeyboard::KeyCode::KEY_BACK) {
526 526 if (AniMiscUtils::isNodeVisible(n)) {
527   - //cocos2d::Director::getInstance()->end();
528   - auto scene = HelloWorld::createScene();
529   - cocos2d::Director::getInstance()->replaceScene(scene);
  527 + cocos2d::Director::getInstance()->end();
  528 + // auto scene = HelloWorld::createScene();
  529 + // cocos2d::Director::getInstance()->replaceScene(scene);
530 530 }
531 531 }
532 532 }, std::placeholders::_1, std::placeholders::_2, AniLevelPickerLayer);
... ...
ios/Runner/Wowgame/Classes/game_animal/AniSettingsLayer.cpp
... ... @@ -12,6 +12,7 @@
12 12 #include "AniStrings.h"
13 13 #include "AniSimpleButton.h"
14 14 #include "AniKKGLinearLayout.h"
  15 +#include "AniAlertUtils.h"
15 16  
16 17 AniSettingsLayer* AniSettingsLayer::create(float width, float height, std::function<void(int)> onLevelPickedCallback, std::function<void()> onTutorialResetPickedCallback){
17 18 AniSettingsLayer * view = new (std::nothrow) AniSettingsLayer();
... ... @@ -58,6 +59,7 @@ bool AniSettingsLayer::init(float width, float height, std::function&lt;void(int)&gt;
58 59  
59 60 auto webLinkButton = AniSimpleButton::create();
60 61 container->addView(webLinkButton);
  62 + webLinkButton->setVisible(false);
61 63 auto buttonTexturePath = "settings_buttons/steve_maggie.png";
62 64 webLinkButton->loadTextures(buttonTexturePath, buttonTexturePath, buttonTexturePath);
63 65 webLinkButton->setOnTouchEndedCallback([&, webLinkButton](std::string name, cocos2d::ui::Widget::TouchEventType eventType){
... ... @@ -69,16 +71,38 @@ bool AniSettingsLayer::init(float width, float height, std::function&lt;void(int)&gt;
69 71 });
70 72 });
71 73  
  74 +
  75 +
72 76 auto replayTutorialButton = AniSimpleButton::create();
73 77 addChild(replayTutorialButton);
74 78 auto repTutButtonTexturePath = "settings_buttons/play_preview_again.png";
75 79 replayTutorialButton->loadTextures(repTutButtonTexturePath, repTutButtonTexturePath, repTutButtonTexturePath);
76 80 replayTutorialButton->setScale(1.5f);
77 81 replayTutorialButton->setOriginalScale(1.5f);
78   - replayTutorialButton->setPosition(cocos2d::Point(getContentSize().width-paddingTop-replayTutorialButton->getContentSize().width/2*1.5, getContentSize().height - paddingTop - replayTutorialButton->getContentSize().height*1.5/2));
  82 + auto pos_x = getContentSize().width-paddingTop-replayTutorialButton->getContentSize().width/2*1.5;
  83 + auto pos_y = getContentSize().height - paddingTop - replayTutorialButton->getContentSize().height*1.5/2;
  84 +
  85 + replayTutorialButton->setPosition(cocos2d::Point(pos_x - 400 ,pos_y));
79 86 replayTutorialButton->setOnTouchEndedCallback([&, replayTutorialButton](std::string name, cocos2d::ui::Widget::TouchEventType eventType){
80 87 _onTutorialReset();
81 88 });
  89 +
  90 +
  91 + auto appExitButton = AniSimpleButton::create();
  92 + addChild(appExitButton);
  93 + auto exitButtonTexturePath = "buttons/graphics/button_x.png";
  94 + appExitButton->loadTextures(exitButtonTexturePath, exitButtonTexturePath, exitButtonTexturePath);
  95 + appExitButton->setScale(1.5f);
  96 + appExitButton->setOriginalScale(1.5f);
  97 + appExitButton->setPosition(cocos2d::Point(getContentSize().width-paddingTop-appExitButton->getContentSize().width/2*1.5, pos_y));
  98 + appExitButton->setOnTouchEndedCallback([&, appExitButton](std::string name, cocos2d::ui::Widget::TouchEventType eventType){
  99 + AniAlertUtils::showAppCloseConfirmDialog([&](){
  100 + });
  101 + });
  102 +
  103 +
  104 +
  105 +
82 106  
83 107 auto menuPadding = 30*AniScalingUtils::scaleAspectFillToDesignIpadProSize();//TODO magic number
84 108  
... ...
ios/Runner/Wowgame/Classes/game_food/MiscUtils.cpp
... ... @@ -11,6 +11,12 @@
11 11 #include "GeometryUtils.h"
12 12 #include "AlertView.h"
13 13 #include "HelloWorldScene.h"
  14 +
  15 +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  16 +#include "RatePromptHandler_ios.h"
  17 +#endif
  18 +#include "audio/include/AudioEngine.h"
  19 +
14 20 float MiscUtils::StandardAnimationTime = 0.2;
15 21 const std::string MiscUtils::WHICH_LEVEL_UD_KEY = "WHICH_LEVEL_UD_KEY";
16 22 const std::string MiscUtils::TOS_ACCEPTED_UD_KEY = "TOS_ACCEPTED_UD_KEY";
... ... @@ -180,7 +186,7 @@ std::string MiscUtils::clockMinSecTimeString(int seconds){
180 186 return timeString;
181 187 }
182 188  
183   -#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  189 +//#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
184 190  
185 191 static const int AlertViewTag = 999;
186 192  
... ... @@ -198,10 +204,18 @@ void MiscUtils::showAppCloseConfirmDialog(std::function&lt;void()&gt; onCancelCallback
198 204 auto okColor = cocos2d::Color3B(200, 100, 100);
199 205  
200 206 auto alert = AlertView::create(message, okText, cancelText, okColor, cancelColor, []() {
201   - // cocos2d::Director::getInstance()->end();
202   - auto scene = HelloWorld::createScene();
203   - cocos2d::Director::getInstance()->replaceScene(scene);
204 207  
  208 +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  209 + cocos2d::Director::getInstance()->end();
  210 +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  211 + cocos2d::AudioEngine::stopAll();
  212 + cocos2d::Director::getInstance()->pause();
  213 + handler_nativeExitGame();
  214 +#else
  215 + cocos2d::Director::getInstance()->end();
  216 +#endif
  217 + // auto scene = HelloWorld::createScene();
  218 + // cocos2d::Director::getInstance()->replaceScene(scene);
205 219  
206 220  
207 221 }, onCancelCallback);
... ... @@ -231,4 +245,4 @@ bool MiscUtils::closeAppCloseConfirmDialogIfNecessary(){
231 245 return false;
232 246 }
233 247  
234   -#endif
  248 +//#endif
... ...
ios/Runner/Wowgame/Classes/game_food/MiscUtils.h
... ... @@ -67,10 +67,10 @@ static void changeAnchorPoint(cocos2d::Node* p_node, cocos2d::Point p_newAnchorP
67 67  
68 68 static std::string boolToString(bool value);
69 69  
70   -#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  70 +//#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
71 71 static void showAppCloseConfirmDialog(std::function<void()> onCancelCallback);
72 72 static bool closeAppCloseConfirmDialogIfNecessary();
73   -#endif
  73 +//#endif
74 74 };
75 75  
76 76 #endif /* MiscUtils_h */
... ...
ios/Runner/Wowgame/Classes/game_food/ParentScene.cpp
... ... @@ -497,9 +497,9 @@ void ParentScene::showTOSAcceptPopup(std::function&lt;void()&gt; onAccept){
497 497 if (n->isShowingParentalGate()) {
498 498 n->hideParentalGate();
499 499 } else {
500   - // cocos2d::Director::getInstance()->end();
501   - auto scene = HelloWorld::createScene();
502   - cocos2d::Director::getInstance()->replaceScene(scene);
  500 + cocos2d::Director::getInstance()->end();
  501 + // auto scene = HelloWorld::createScene();
  502 + // cocos2d::Director::getInstance()->replaceScene(scene);
503 503 }
504 504 }
505 505 }
... ... @@ -524,9 +524,9 @@ void ParentScene::showLevelPickerLayer(std::function&lt;void()&gt; onLayerDismissed, s
524 524 [&](cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event *event, cocos2d::Node *n) {
525 525 if (keyCode == cocos2d::EventKeyboard::KeyCode::KEY_BACK) {
526 526 if (MiscUtils::isNodeVisible(n)) {
527   - //cocos2d::Director::getInstance()->end();
528   - auto scene = HelloWorld::createScene();
529   - cocos2d::Director::getInstance()->replaceScene(scene);
  527 + cocos2d::Director::getInstance()->end();
  528 + //auto scene = HelloWorld::createScene();
  529 + //cocos2d::Director::getInstance()->replaceScene(scene);
530 530 }
531 531 }
532 532 }, std::placeholders::_1, std::placeholders::_2, levelPickerLayer);
... ...
ios/Runner/Wowgame/Classes/game_food/SettingsLayer.cpp
... ... @@ -73,31 +73,54 @@ bool SettingsLayer::init(float width, float height, std::function&lt;void(int)&gt; onL
73 73 #endif
74 74  
75 75 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
76   - setupAppLinksView(cocos2d::Point(getContentSize().width/2, upperStuffContainer->getBoundingBox().getMinY() - paddingBottom - paddingTop));
77   - wholeContainer->addChild(m_appLinksView); //TODO messy messy
78   - auto leftAppLinkSprite = cocos2d::Sprite::create("app_links/witch_halloween_app.png");
79   - leftAppLinkSprite->setAnchorPoint(cocos2d::Vec2(1,1));
80   - leftAppLinkSprite->setPosition(cocos2d::Vec2(m_appLinksView->getBoundingBox().getMinX(), m_appLinksView->getBoundingBox().getMaxY()));
81   - auto rightAppLinkSprite = cocos2d::Sprite::create("app_links/doll_toy_app.png");
82   - rightAppLinkSprite->setAnchorPoint(cocos2d::Vec2(0,0));
83   - rightAppLinkSprite->setPosition(cocos2d::Vec2(m_appLinksView->getBoundingBox().getMaxX(), m_appLinksView->getBoundingBox().getMinY()));
84   - wholeContainer->addChild(leftAppLinkSprite);
85   - wholeContainer->addChild(rightAppLinkSprite);
  76 + // setupAppLinksView(cocos2d::Point(getContentSize().width/2, upperStuffContainer->getBoundingBox().getMinY() - paddingBottom - paddingTop));
  77 + // wholeContainer->addChild(m_appLinksView); //TODO messy messy
  78 + // auto leftAppLinkSprite = cocos2d::Sprite::create("app_links/witch_halloween_app.png");
  79 + // leftAppLinkSprite->setAnchorPoint(cocos2d::Vec2(1,1));
  80 + // leftAppLinkSprite->setPosition(cocos2d::Vec2(m_appLinksView->getBoundingBox().getMinX(), m_appLinksView->getBoundingBox().getMaxY()));
  81 + // auto rightAppLinkSprite = cocos2d::Sprite::create("app_links/doll_toy_app.png");
  82 + // rightAppLinkSprite->setAnchorPoint(cocos2d::Vec2(0,0));
  83 + // rightAppLinkSprite->setPosition(cocos2d::Vec2(m_appLinksView->getBoundingBox().getMaxX(), m_appLinksView->getBoundingBox().getMinY()));
  84 + // wholeContainer->addChild(leftAppLinkSprite);
  85 + // wholeContainer->addChild(rightAppLinkSprite);
86 86 #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
87   - auto webLinkButton = SimpleButton::create();
88   - wholeContainer->addChild(webLinkButton);
89   - auto buttonTexturePath = "app_links/steve_maggie.png";
90   - webLinkButton->loadTextures(buttonTexturePath, buttonTexturePath, buttonTexturePath);
91   - webLinkButton->setPosition(cocos2d::Point(getContentSize().width/2, upperStuffContainer->getBoundingBox().getMinY() - paddingTop*3 - webLinkButton->getBoundingBox().size.height/2));
92   - webLinkButton->setOnTouchEndedCallback([&, webLinkButton](std::string name, cocos2d::ui::Widget::TouchEventType eventType){
93   - presentParentalGate([&](){
94   - hideParentalGate();
95   - cocos2d::Application::getInstance()->openURL("https://www.steveandmaggie.com"); //TODO hardcoded
96   - }, [&](){
97   - hideParentalGate();
  87 + // auto webLinkButton = SimpleButton::create();
  88 + // wholeContainer->addChild(webLinkButton);
  89 + // auto buttonTexturePath = "app_links/steve_maggie.png";
  90 + // webLinkButton->loadTextures(buttonTexturePath, buttonTexturePath, buttonTexturePath);
  91 + // webLinkButton->setPosition(cocos2d::Point(getContentSize().width/2, upperStuffContainer->getBoundingBox().getMinY() - paddingTop*3 - webLinkButton->getBoundingBox().size.height/2));
  92 + // webLinkButton->setOnTouchEndedCallback([&, webLinkButton](std::string name, cocos2d::ui::Widget::TouchEventType eventType){
  93 + // presentParentalGate([&](){
  94 + // hideParentalGate();
  95 + // cocos2d::Application::getInstance()->openURL("https://www.steveandmaggie.com"); //TODO hardcoded
  96 + // }, [&](){
  97 + // hideParentalGate();
  98 + // });
  99 + // });
  100 +#endif
  101 + auto paddingExitButton = 20*ScalingUtils::scaleAspectFillToDesignIpadProSize();
  102 + auto scaleExitButton = 1.0f;
  103 + if(ScalingUtils::isSmallDevice()){
  104 + paddingExitButton *= ScalingUtils::getScaleForSmallDevice();
  105 + scaleExitButton = 1.6f;
  106 + }
  107 +
  108 + auto appExitButton = SimpleButton::create();
  109 + addChild(appExitButton);
  110 + auto exitButtonTexturePath = "buttons/graphics/button_x.png";
  111 + appExitButton->loadTextures(exitButtonTexturePath, exitButtonTexturePath, exitButtonTexturePath);
  112 + appExitButton->setScale(scaleExitButton);
  113 + appExitButton->setOriginalScale(scaleExitButton);
  114 + appExitButton->setPosition(cocos2d::Point(getContentSize().width - appExitButton->getBoundingBox().size.width/2 - paddingExitButton, getContentSize().height - appExitButton->getBoundingBox().size.height/2 - paddingExitButton));
  115 + appExitButton->setOnTouchEndedCallback([&, appExitButton](std::string name, cocos2d::ui::Widget::TouchEventType eventType){
  116 + MiscUtils::showAppCloseConfirmDialog([&](){
98 117 });
99 118 });
100   -#endif
  119 +
  120 +
  121 +
  122 +
  123 +
101 124  
102 125 auto menuPadding = 30*ScalingUtils::scaleAspectFillToDesignIpadProSize();//TODO magic number
103 126  
... ... @@ -114,9 +137,9 @@ bool SettingsLayer::init(float width, float height, std::function&lt;void(int)&gt; onL
114 137 lowerStuffContainer->setAnchorPoint(cocos2d::Vec2(0.5, 1));
115 138  
116 139 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
117   - lowerStuffContainer->setPosition(getContentSize().width/2, m_appLinksView->getBoundingBox().getMinY() - paddingBottom);
  140 + lowerStuffContainer->setPosition(getContentSize().width/2, upperStuffContainer->getBoundingBox().getMinY() - paddingBottom);
118 141 #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
119   - lowerStuffContainer->setPosition(getContentSize().width/2, webLinkButton->getBoundingBox().getMinY() - paddingBottom);
  142 + lowerStuffContainer->setPosition(getContentSize().width/2, upperStuffContainer->getBoundingBox().getMinY() - paddingBottom);
120 143 #endif
121 144  
122 145 menuCenter->setPosition(lowerStuffContainer->getContentSize().width/2, lowerStuffContainer->getContentSize().height/2);
... ...
ios/Runner/Wowgame/Classes/game_food/SubGameScene.cpp
... ... @@ -196,7 +196,7 @@ void SubGameScene::presentGameResumeLayer(){
196 196 buttonResume->addChild(buttonBg);
197 197 buttonBg->setPosition(cocos2d::Vec2(buttonResume->getContentSize().width/2,buttonResume->getContentSize().height/2));
198 198 resumeLayer->addChild(buttonResume);
199   - buttonResume->setPosition(cocos2d::Vec2(resumeLayer->getContentSize().width/2 -150 , resumeLayer->getContentSize().height/2));
  199 + buttonResume->setPosition(cocos2d::Vec2(resumeLayer->getContentSize().width/2, resumeLayer->getContentSize().height/2));
200 200 buttonResume->setOnTouchEndedCallback(std::bind([&](std::string name, cocos2d::ui::Widget::TouchEventType eventType, cocos2d::Node* n){
201 201 resumeGame();
202 202 MiscUtils::hideAndRemoveView(n, true);
... ... @@ -204,29 +204,6 @@ void SubGameScene::presentGameResumeLayer(){
204 204  
205 205  
206 206  
207   - // add the close button
208   - auto buttonClose = SimpleButton::create();
209   - buttonClose->setCascadeOpacityEnabled(true);
210   - auto buttonTexturePath2 = "buttons/graphics/button_x.png";
211   - buttonClose->loadTextures(buttonTexturePath2, buttonTexturePath2, buttonTexturePath2);
212   -
213   - resumeLayer->addChild(buttonClose);
214   - buttonClose->setPosition(cocos2d::Vec2(resumeLayer->getContentSize().width / 2 + 150, resumeLayer->getContentSize().height / 2));
215   - buttonClose->setOnTouchEndedCallback(std::bind([&](std::string name, cocos2d::ui::Widget::TouchEventType eventType, cocos2d::Node* n) {
216   -
217   - auto scene = HelloWorld::createScene();
218   - // run
219   - cocos2d::Director::getInstance()->replaceScene(scene);
220   -
221   -
222   - }, std::placeholders::_1, std::placeholders::_2, resumeLayer));
223   -
224   -
225   -
226   -
227   -
228   -
229   -
230 207  
231 208 resumeLayer->setOpacity(0);
232 209 MiscUtils::showView(resumeLayer, true, 220.f);
... ...
ios/Runner/Wowgame/Classes/game_halloween/HMiscUtils.cpp
... ... @@ -14,6 +14,11 @@
14 14 #include "HSoundUtils.h"
15 15 #include "HelloWorldScene.h"
16 16  
  17 +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  18 +#include "RatePromptHandler_ios.h"
  19 +#endif
  20 +#include "audio/include/AudioEngine.h"
  21 +
17 22 float HMiscUtils::StandardAnimationTime = 0.2;
18 23 const std::string HMiscUtils::MAGGIE_TOUCHED_UD_KEY = "MAGGIE_TOUCHED_UD_KEY";
19 24 const std::string HMiscUtils::WHICH_LEVEL_UD_KEY = "WHICH_LEVEL_UD_KEY";
... ... @@ -184,12 +189,20 @@ void HMiscUtils::showAppCloseConfirmDialog(std::function&lt;void()&gt; onCancelCallbac
184 189 // HSoundUtils::stopAllSounds(); //todo dedup in other places?
185 190 // cocoss2d::AudioEngine::end();
186 191  
187   -
188   - //cocos2d::Director::getInstance()->end();
  192 +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  193 + cocos2d::Director::getInstance()->end();
  194 +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  195 + cocos2d::AudioEngine::stopAll();
  196 + cocos2d::Director::getInstance()->pause();
  197 + handler_nativeExitGame();
  198 +#else
  199 + cocos2d::Director::getInstance()->end();
  200 +#endif
  201 +
189 202 // create a scene. it's an autorelease object
190   - auto scene = HelloWorld::createScene();
  203 + //auto scene = HelloWorld::createScene();
191 204 // run
192   - cocos2d::Director::getInstance()->replaceScene(scene);
  205 + //cocos2d::Director::getInstance()->replaceScene(scene);
193 206  
194 207  
195 208  
... ...
ios/Runner/Wowgame/Classes/game_halloween/HSettingsLayer.cpp
... ... @@ -63,15 +63,16 @@ bool HSettingsLayer::init(float width, float height, std::function&lt;void(int)&gt; on
63 63  
64 64 auto webLinkButton = HalloweenSimpleButton::create();
65 65 wholeContainer->addView(webLinkButton);
  66 + webLinkButton->setVisible(false);
66 67 auto buttonTexturePath = "settings_buttons/steve_maggie.png";
67 68 webLinkButton->loadTextures(buttonTexturePath, buttonTexturePath, buttonTexturePath);
68 69 webLinkButton->setOnTouchEndedCallback([&, webLinkButton](std::string name, cocos2d::ui::Widget::TouchEventType eventType){
69   - presentParentalGate([&](){
70   - hideParentalGate();
71   - cocos2d::Application::getInstance()->openURL("https://www.steveandmaggie.com"); //TODO hardcoded
72   - }, [&](){
73   - hideParentalGate();
74   - });
  70 + // presentParentalGate([&](){
  71 + // hideParentalGate();
  72 + // cocos2d::Application::getInstance()->openURL("https://www.steveandmaggie.com"); //TODO hardcoded
  73 + // }, [&](){
  74 + // hideParentalGate();
  75 + // });
75 76 });
76 77  
77 78 auto lowerStuffContainer = cocos2d::Node::create();
... ...
ios/Runner/Wowgame/Classes/game_halloween/HSubGameScene.cpp
... ... @@ -568,10 +568,10 @@ void HSubGameScene::showTOSAcceptPopup(std::function&lt;void()&gt; onAccept){
568 568 } else {
569 569 // HSoundUtils::stopAllSounds();
570 570 // cocos2d::AudioEngine::end();
571   - //cocos2d::Director::getInstance()->end();
  571 + cocos2d::Director::getInstance()->end();
572 572  
573   - auto scene = HelloWorld::createScene();
574   - cocos2d::Director::getInstance()->replaceScene(scene);
  573 + //auto scene = HelloWorld::createScene();
  574 + //cocos2d::Director::getInstance()->replaceScene(scene);
575 575 }
576 576 }
577 577 }
... ... @@ -593,10 +593,10 @@ void HSubGameScene::showHLevelPickerLayer(std::function&lt;void()&gt; onLayerDismissed
593 593 if(HMiscUtils::isNodeVisible(n)){
594 594 // HSoundUtils::stopAllSounds();
595 595 // cocos2d::AudioEngine::end();
596   - //cocos2d::Director::getInstance()->end();
  596 + cocos2d::Director::getInstance()->end();
597 597  
598   - auto scene = HelloWorld::createScene();
599   - cocos2d::Director::getInstance()->replaceScene(scene);
  598 + //auto scene = HelloWorld::createScene();
  599 + //cocos2d::Director::getInstance()->replaceScene(scene);
600 600  
601 601  
602 602  
... ...
ios/Runner/Wowgame/Classes/game_toy/ToyMainMenuScene.cpp
... ... @@ -343,9 +343,9 @@ void ToyMainMenuScene::showTOSAcceptPopup(std::function&lt;void()&gt; onAccept){
343 343 } else {
344 344  
345 345  
346   - //cocos2d::Director::getInstance()->end();
347   - auto scene = HelloWorld::createScene();
348   - cocos2d::Director::getInstance()->replaceScene(scene);
  346 + cocos2d::Director::getInstance()->end();
  347 + //auto scene = HelloWorld::createScene();
  348 + //cocos2d::Director::getInstance()->replaceScene(scene);
349 349  
350 350  
351 351 }
... ...
ios/Runner/Wowgame/Classes/game_toy/ToyMiscUtils.cpp
... ... @@ -11,6 +11,14 @@
11 11 #include "ToyGeometryUtils.h"
12 12 #include "ToyAlertView.h"
13 13 #include "HelloWorldScene.h"
  14 +
  15 +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  16 +#include "RatePromptHandler_ios.h"
  17 +#endif
  18 +
  19 +#include "audio/include/AudioEngine.h"
  20 +
  21 +
14 22 float ToyMiscUtils::StandardAnimationTime = 0.2;
15 23 const std::string ToyMiscUtils::MAGGIE_TOUCHED_UD_KEY = "MAGGIE_TOUCHED_UD_KEY";
16 24 const std::string ToyMiscUtils::WHICH_LEVEL_UD_KEY = "WHICH_LEVEL_UD_KEY";
... ... @@ -196,12 +204,18 @@ void ToyMiscUtils::showAppCloseConfirmDialog(std::function&lt;void()&gt; onCancelCallb
196 204  
197 205 auto alert = ToyAlertView::create(message, okText, cancelText, okColor, cancelColor, []() {
198 206  
199   -
200   - //cocos2d::Director::getInstance()->end();
201   - auto scene = HelloWorld::createScene();
202   - cocos2d::Director::getInstance()->replaceScene(scene);
203   -
204   -
  207 +#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  208 + cocos2d::Director::getInstance()->end();
  209 +#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  210 + cocos2d::AudioEngine::stopAll();
  211 + cocos2d::Director::getInstance()->pause();
  212 + handler_nativeExitGame();
  213 +#else
  214 + cocos2d::Director::getInstance()->end();
  215 +#endif
  216 +
  217 + // auto scene = HelloWorld::createScene();
  218 + // cocos2d::Director::getInstance()->replaceScene(scene);
205 219  
206 220 }, onCancelCallback);
207 221 auto touchListener = cocos2d::EventListenerTouchOneByOne::create();
... ...
ios/Runner/Wowgame/Classes/game_toy/ToyParentScene.cpp
... ... @@ -497,10 +497,10 @@ void ToyParentScene::showTOSAcceptPopup(std::function&lt;void()&gt; onAccept){
497 497 if (n->isShowingParentalGate()) {
498 498 n->hideParentalGate();
499 499 } else {
500   - //cocos2d::Director::getInstance()->end();
  500 + cocos2d::Director::getInstance()->end();
501 501  
502   - auto scene = HelloWorld::createScene();
503   - cocos2d::Director::getInstance()->replaceScene(scene);
  502 + //auto scene = HelloWorld::createScene();
  503 + //cocos2d::Director::getInstance()->replaceScene(scene);
504 504  
505 505  
506 506 }
... ... @@ -523,9 +523,9 @@ void ToyParentScene::showToyLevelPickerLayer(std::function&lt;void()&gt; onLayerDismis
523 523 keyboardListener->onKeyReleased = std::bind([&](cocos2d::EventKeyboard::KeyCode keyCode, cocos2d::Event* event, cocos2d::Node* n){
524 524 if(keyCode == cocos2d::EventKeyboard::KeyCode::KEY_BACK){
525 525 if(ToyMiscUtils::isNodeVisible(n)){
526   - //cocos2d::Director::getInstance()->end();
527   - auto scene = HelloWorld::createScene();
528   - cocos2d::Director::getInstance()->replaceScene(scene);
  526 + cocos2d::Director::getInstance()->end();
  527 + //auto scene = HelloWorld::createScene();
  528 + //cocos2d::Director::getInstance()->replaceScene(scene);
529 529  
530 530  
531 531  
... ...
ios/Runner/Wowgame/Classes/game_toy/ToySettingsLayer.cpp
... ... @@ -76,13 +76,14 @@ bool ToySettingsLayer::init(float width, float height, std::function&lt;void(int)&gt;
76 76  
77 77 auto webLinkButton = ToySimpleButton::create();
78 78 wholeContainer->addChild(webLinkButton);
  79 + webLinkButton->setVisible(false);
79 80 auto buttonTexturePath = "settings_buttons/steve_maggie.png";
80 81 webLinkButton->loadTextures(buttonTexturePath, buttonTexturePath, buttonTexturePath);
81 82 webLinkButton->setPosition(cocos2d::Point(getContentSize().width/2, upperStuffContainer->getBoundingBox().getMinY() - paddingTop*2 - webLinkButton->getBoundingBox().size.height/2));
82 83 webLinkButton->setOnTouchEndedCallback([&, webLinkButton](std::string name, cocos2d::ui::Widget::TouchEventType eventType){
83 84 // presentParentalGate([&](){
84 85 // hideParentalGate();
85   - cocos2d::Application::getInstance()->openURL("https://www.steveandmaggie.com"); //TODO hardcoded
  86 +// cocos2d::Application::getInstance()->openURL("https://www.steveandmaggie.com"); //TODO hardcoded
86 87 // }, [&](){
87 88 // hideParentalGate();
88 89 // });
... ...
ios/Runner/Wowgame/Resources/CloseNormal.png deleted

3.51 KB

ios/Runner/Wowgame/Resources/CloseSelected.png deleted

2.74 KB

ios/Runner/Wowgame/Resources/HelloWorld.png deleted

37 KB

ios/Runner/Wowgame/Resources/game_animal/xlarge/buttons/graphics/button_x.png 0 → 100644

10.4 KB

ios/Runner/Wowgame/WowGameClasses/WowGameCocosManager.h
... ... @@ -16,7 +16,7 @@
16 16 + (instancetype)sharedManager;
17 17 - (void)detoryCocosEnvironment;
18 18  
19   -- (void)runGame;
  19 +- (void)runGame:(NSInteger)gameid;
20 20  
21 21 @end
22 22  
... ...
ios/Runner/Wowgame/WowGameClasses/WowGameCocosManager.mm
... ... @@ -7,7 +7,8 @@
7 7  
8 8 #import "WowGameCocosManager.h"
9 9  
10   -#import "cocos2d.h"
  10 +#include "cocos2d.h"
  11 +
11 12 #import "CocosAppDelegate.h"
12 13  
13 14 @interface WowGameCocosManager () {
... ... @@ -41,9 +42,15 @@ static CocosAppDelegate cocosAppDelegate;
41 42 cocos2d::GLViewImpl::convertAttrs();
42 43  
43 44 _app = app;
  45 +
  46 + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(exitGame) name:@"_kwowgamecocosexitgame" object:nil];
  47 +}
  48 +
  49 +- (void)exitGame {
  50 + [self.gameViewController dismissViewControllerAnimated:YES completion:nil];
44 51 }
45 52  
46   -- (void)runGame {
  53 +- (void)runGame:(NSInteger)gameid {
47 54 UIWindow *window = UIApplication.sharedApplication.delegate.window;
48 55 UIViewController *rootvc = window.rootViewController;
49 56 if ([rootvc isKindOfClass:WowGameViewController.class]) {
... ... @@ -52,35 +59,38 @@ static CocosAppDelegate cocosAppDelegate;
52 59 if (!self.gameViewController) {
53 60 WowGameViewController *cocosvc = [[WowGameViewController alloc] init];
54 61 cocosvc.wantsFullScreenLayout = YES;
55   -// self.gameViewController = cocosvc;
  62 + self.gameViewController = cocosvc;
56 63  
57 64 cocos2d::GLView *glview = cocos2d::GLViewImpl::createWithEAGLView((__bridge void *)cocosvc.view);
58 65 cocos2d::Director::getInstance()->setOpenGLView(glview);
59 66 _app->run();
60   - [rootvc presentViewController:cocosvc animated:YES completion:nil];
61   -// return;
62 67 } else {
63   - [self cocosWillEnterForeground];
  68 + cocos2d::Director::getInstance()->resume();
64 69 }
65   -//
  70 +
66 71 [rootvc presentViewController:self.gameViewController animated:YES completion:nil];
67 72  
68   -// debug exit game
69   - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
70   - [self popGame];
71   -// [self cocosDidEnterBackground];
72   -// [rootvc dismissViewControllerAnimated:YES completion:nil];
73   -
74   -// [self cocosDidEnterBackground];
  73 + [self startGameWithID:gameid];
  74 +
  75 +//// debug exit game
  76 +// dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  77 +// [self exitGame];
  78 +// });
  79 +}
  80 +
  81 +-(void)startGameWithID:(NSInteger)gameid {
  82 + cocos2d::Director::getInstance()->getScheduler()->performFunctionInCocosThread([=] {
  83 +// CCLOG("start gameid---> %d ", gameid);
  84 + cocos2d::EventCustom evtEnter("start_gameid");
  85 + evtEnter.setUserData((void *) gameid);
  86 + cocos2d::Director::getInstance()->getEventDispatcher()->dispatchEvent(&evtEnter);
75 87 });
76 88 }
77 89  
78 90 - (void)popGame {
79 91 [self.gameViewController dismissViewControllerAnimated:YES completion:nil];
80 92  
81   - [self cocosDidEnterBackground];
82   -// cocos2d::Director::getInstance()->end();
83   -
  93 +// [self cocosDidEnterBackground];
84 94 }
85 95  
86 96  
... ...
ios/cocos2d/cocos/base/CCDirector.cpp
... ... @@ -194,7 +194,7 @@ Director::~Director()
194 194 #endif
195 195  
196 196 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
197   - exit(0);
  197 +// exit(0);
198 198 #endif
199 199 }
200 200  
... ...
lib/app/app.dart
... ... @@ -3,8 +3,6 @@ import &#39;package:flutter_bloc/flutter_bloc.dart&#39;;
3 3 import 'package:flutter_easyloading/flutter_easyloading.dart';
4 4 import 'package:flutter_screenutil/flutter_screenutil.dart';
5 5 import 'package:responsive_framework/responsive_framework.dart';
6   -// import 'package:responsive_framework/breakpoint.dart';
7   -// import 'package:responsive_framework/responsive_breakpoints.dart';
8 6 import 'package:wow_english/common/blocs/cachebloc/cache_bloc.dart';
9 7 import 'package:wow_english/common/widgets/hide_keyboard_widget.dart';
10 8 import 'package:wow_english/pages/tab/blocs/tab_bloc.dart';
... ...
lib/app/splash_page.dart
... ... @@ -69,7 +69,7 @@ class _TransitionViewState extends State&lt;TransitionView&gt; {
69 69 } else {
70 70 pushNamedAndRemoveUntil(AppRouteName.login, (route) => false);
71 71 }*/
72   - pushNamedAndRemoveUntil(AppRouteName.home, (route) => false);
  72 + pushNamedAndRemoveUntil(AppRouteName.moduleSelect, (route) => false);
73 73 });
74 74 }
75 75  
... ...
lib/common/request/apis.dart
... ... @@ -82,4 +82,14 @@ class Apis {
82 82  
83 83 /// 退出课堂
84 84 static const String exitClass = 'course/exit/class';
  85 +
  86 + /// 商品列表
  87 + static const String productList = 'order/course/combo/list';
  88 +
  89 + /// 创建订单
  90 + static const String createOrder = 'order/create/order';
  91 +
  92 + /// 获取阿里支付token
  93 + static const String getAliPayToken = 'pay/alipay/token';
  94 +
85 95 }
... ...
lib/common/request/dao/shop_dao.dart 0 → 100644
  1 +import '../../../models/product_entity.dart';
  2 +import '../request_client.dart';
  3 +
  4 +class ShopDao {
  5 + ///商品列表
  6 + static Future productList() async {
  7 + return await requestClient.get<List<ProductEntity?>>(Apis.productList);
  8 + }
  9 +
  10 + ///创建订单
  11 + static Future createOrder(ProductEntity productEntity) async {
  12 + return await requestClient
  13 + .post<Map<String, dynamic>>(Apis.createOrder, data: {'courseComboId': productEntity.id});
  14 + }
  15 +
  16 + ///获取ali支付订单信息
  17 + static Future getAliPayToken(String orderNo) async {
  18 + return await requestClient
  19 + .post<Map<String, dynamic>>(Apis.getAliPayToken, data: {'orderNo': orderNo});
  20 + }
  21 +}
... ...
lib/generated/json/aliyun_oss_upload_sts_entity.g.dart
1 1 import 'package:wow_english/generated/json/base/json_convert_content.dart';
2 2 import 'package:wow_english/models/aliyun_oss_upload_sts_entity.dart';
3 3  
4   -AliyunOssUploadStsEntity $AliyunOssUploadStsEntityFromJson(Map<String, dynamic> json) {
5   - final AliyunOssUploadStsEntity aliyunOssUploadStsEntity = AliyunOssUploadStsEntity();
6   - final String? securityToken = jsonConvert.convert<String>(json['securityToken']);
7   - if (securityToken != null) {
8   - aliyunOssUploadStsEntity.securityToken = securityToken;
9   - }
10   - final String? expiration = jsonConvert.convert<String>(json['expiration']);
11   - if (expiration != null) {
12   - aliyunOssUploadStsEntity.expiration = expiration;
13   - }
14   - final String? endpoint = jsonConvert.convert<String>(json['endpoint']);
15   - if (endpoint != null) {
16   - aliyunOssUploadStsEntity.endpoint = endpoint;
17   - }
18   - final String? fileKey = jsonConvert.convert<String>(json['fileKey']);
19   - if (fileKey != null) {
20   - aliyunOssUploadStsEntity.fileKey = fileKey;
21   - }
22   - final String? accessKeyId = jsonConvert.convert<String>(json['accessKeyId']);
23   - if (accessKeyId != null) {
24   - aliyunOssUploadStsEntity.accessKeyId = accessKeyId;
25   - }
26   - final String? accessKeySecret = jsonConvert.convert<String>(json['accessKeySecret']);
27   - if (accessKeySecret != null) {
28   - aliyunOssUploadStsEntity.accessKeySecret = accessKeySecret;
29   - }
30   - final String? bucket = jsonConvert.convert<String>(json['bucket']);
31   - if (bucket != null) {
32   - aliyunOssUploadStsEntity.bucket = bucket;
33   - }
34   - final String? ossDomain = jsonConvert.convert<String>(json['ossDomain']);
35   - if (ossDomain != null) {
36   - aliyunOssUploadStsEntity.ossDomain = ossDomain;
37   - }
38   - final String? host = jsonConvert.convert<String>(json['host']);
39   - if (host != null) {
40   - aliyunOssUploadStsEntity.host = host;
41   - }
42   - final AliyunOssUploadStsCallbackParam? callbackParam = jsonConvert.convert<AliyunOssUploadStsCallbackParam>(json['callbackParam']);
43   - if (callbackParam != null) {
44   - aliyunOssUploadStsEntity.callbackParam = callbackParam;
45   - }
46   - return aliyunOssUploadStsEntity;
  4 +AliyunOssUploadStsEntity $AliyunOssUploadStsEntityFromJson(
  5 + Map<String, dynamic> json) {
  6 + final AliyunOssUploadStsEntity aliyunOssUploadStsEntity = AliyunOssUploadStsEntity();
  7 + final String? securityToken = jsonConvert.convert<String>(
  8 + json['securityToken']);
  9 + if (securityToken != null) {
  10 + aliyunOssUploadStsEntity.securityToken = securityToken;
  11 + }
  12 + final String? expiration = jsonConvert.convert<String>(json['expiration']);
  13 + if (expiration != null) {
  14 + aliyunOssUploadStsEntity.expiration = expiration;
  15 + }
  16 + final String? endpoint = jsonConvert.convert<String>(json['endpoint']);
  17 + if (endpoint != null) {
  18 + aliyunOssUploadStsEntity.endpoint = endpoint;
  19 + }
  20 + final String? fileKey = jsonConvert.convert<String>(json['fileKey']);
  21 + if (fileKey != null) {
  22 + aliyunOssUploadStsEntity.fileKey = fileKey;
  23 + }
  24 + final String? accessKeyId = jsonConvert.convert<String>(json['accessKeyId']);
  25 + if (accessKeyId != null) {
  26 + aliyunOssUploadStsEntity.accessKeyId = accessKeyId;
  27 + }
  28 + final String? accessKeySecret = jsonConvert.convert<String>(
  29 + json['accessKeySecret']);
  30 + if (accessKeySecret != null) {
  31 + aliyunOssUploadStsEntity.accessKeySecret = accessKeySecret;
  32 + }
  33 + final String? bucket = jsonConvert.convert<String>(json['bucket']);
  34 + if (bucket != null) {
  35 + aliyunOssUploadStsEntity.bucket = bucket;
  36 + }
  37 + final String? ossDomain = jsonConvert.convert<String>(json['ossDomain']);
  38 + if (ossDomain != null) {
  39 + aliyunOssUploadStsEntity.ossDomain = ossDomain;
  40 + }
  41 + final String? host = jsonConvert.convert<String>(json['host']);
  42 + if (host != null) {
  43 + aliyunOssUploadStsEntity.host = host;
  44 + }
  45 + final AliyunOssUploadStsCallbackParam? callbackParam = jsonConvert.convert<
  46 + AliyunOssUploadStsCallbackParam>(json['callbackParam']);
  47 + if (callbackParam != null) {
  48 + aliyunOssUploadStsEntity.callbackParam = callbackParam;
  49 + }
  50 + return aliyunOssUploadStsEntity;
47 51 }
48 52  
49   -Map<String, dynamic> $AliyunOssUploadStsEntityToJson(AliyunOssUploadStsEntity entity) {
50   - final Map<String, dynamic> data = <String, dynamic>{};
51   - data['securityToken'] = entity.securityToken;
52   - data['expiration'] = entity.expiration;
53   - data['endpoint'] = entity.endpoint;
54   - data['fileKey'] = entity.fileKey;
55   - data['accessKeyId'] = entity.accessKeyId;
56   - data['accessKeySecret'] = entity.accessKeySecret;
57   - data['bucket'] = entity.bucket;
58   - data['ossDomain'] = entity.ossDomain;
59   - data['host'] = entity.host;
60   - data['callbackParam'] = entity.callbackParam.toJson();
61   - return data;
  53 +Map<String, dynamic> $AliyunOssUploadStsEntityToJson(
  54 + AliyunOssUploadStsEntity entity) {
  55 + final Map<String, dynamic> data = <String, dynamic>{};
  56 + data['securityToken'] = entity.securityToken;
  57 + data['expiration'] = entity.expiration;
  58 + data['endpoint'] = entity.endpoint;
  59 + data['fileKey'] = entity.fileKey;
  60 + data['accessKeyId'] = entity.accessKeyId;
  61 + data['accessKeySecret'] = entity.accessKeySecret;
  62 + data['bucket'] = entity.bucket;
  63 + data['ossDomain'] = entity.ossDomain;
  64 + data['host'] = entity.host;
  65 + data['callbackParam'] = entity.callbackParam.toJson();
  66 + return data;
62 67 }
63 68  
64   -AliyunOssUploadStsCallbackParam $AliyunOssUploadStsCallbackParamFromJson(Map<String, dynamic> json) {
65   - final AliyunOssUploadStsCallbackParam aliyunOssUploadStsCallbackParam = AliyunOssUploadStsCallbackParam();
66   - final String? callbackBody = jsonConvert.convert<String>(json['callbackBody']);
67   - if (callbackBody != null) {
68   - aliyunOssUploadStsCallbackParam.callbackBody = callbackBody;
69   - }
70   - final String? callbackBodyType = jsonConvert.convert<String>(json['callbackBodyType']);
71   - if (callbackBodyType != null) {
72   - aliyunOssUploadStsCallbackParam.callbackBodyType = callbackBodyType;
73   - }
74   - final String? callbackUrl = jsonConvert.convert<String>(json['callbackUrl']);
75   - if (callbackUrl != null) {
76   - aliyunOssUploadStsCallbackParam.callbackUrl = callbackUrl;
77   - }
78   - return aliyunOssUploadStsCallbackParam;
  69 +extension AliyunOssUploadStsEntityExtension on AliyunOssUploadStsEntity {
  70 + AliyunOssUploadStsEntity copyWith({
  71 + String? securityToken,
  72 + String? expiration,
  73 + String? endpoint,
  74 + String? fileKey,
  75 + String? accessKeyId,
  76 + String? accessKeySecret,
  77 + String? bucket,
  78 + String? ossDomain,
  79 + String? host,
  80 + AliyunOssUploadStsCallbackParam? callbackParam,
  81 + }) {
  82 + return AliyunOssUploadStsEntity()
  83 + ..securityToken = securityToken ?? this.securityToken
  84 + ..expiration = expiration ?? this.expiration
  85 + ..endpoint = endpoint ?? this.endpoint
  86 + ..fileKey = fileKey ?? this.fileKey
  87 + ..accessKeyId = accessKeyId ?? this.accessKeyId
  88 + ..accessKeySecret = accessKeySecret ?? this.accessKeySecret
  89 + ..bucket = bucket ?? this.bucket
  90 + ..ossDomain = ossDomain ?? this.ossDomain
  91 + ..host = host ?? this.host
  92 + ..callbackParam = callbackParam ?? this.callbackParam;
  93 + }
79 94 }
80 95  
81   -Map<String, dynamic> $AliyunOssUploadStsCallbackParamToJson(AliyunOssUploadStsCallbackParam entity) {
82   - final Map<String, dynamic> data = <String, dynamic>{};
83   - data['callbackBody'] = entity.callbackBody;
84   - data['callbackBodyType'] = entity.callbackBodyType;
85   - data['callbackUrl'] = entity.callbackUrl;
86   - return data;
  96 +AliyunOssUploadStsCallbackParam $AliyunOssUploadStsCallbackParamFromJson(
  97 + Map<String, dynamic> json) {
  98 + final AliyunOssUploadStsCallbackParam aliyunOssUploadStsCallbackParam = AliyunOssUploadStsCallbackParam();
  99 + final String? callbackBody = jsonConvert.convert<String>(
  100 + json['callbackBody']);
  101 + if (callbackBody != null) {
  102 + aliyunOssUploadStsCallbackParam.callbackBody = callbackBody;
  103 + }
  104 + final String? callbackBodyType = jsonConvert.convert<String>(
  105 + json['callbackBodyType']);
  106 + if (callbackBodyType != null) {
  107 + aliyunOssUploadStsCallbackParam.callbackBodyType = callbackBodyType;
  108 + }
  109 + final String? callbackUrl = jsonConvert.convert<String>(json['callbackUrl']);
  110 + if (callbackUrl != null) {
  111 + aliyunOssUploadStsCallbackParam.callbackUrl = callbackUrl;
  112 + }
  113 + return aliyunOssUploadStsCallbackParam;
87 114 }
  115 +
  116 +Map<String, dynamic> $AliyunOssUploadStsCallbackParamToJson(
  117 + AliyunOssUploadStsCallbackParam entity) {
  118 + final Map<String, dynamic> data = <String, dynamic>{};
  119 + data['callbackBody'] = entity.callbackBody;
  120 + data['callbackBodyType'] = entity.callbackBodyType;
  121 + data['callbackUrl'] = entity.callbackUrl;
  122 + return data;
  123 +}
  124 +
  125 +extension AliyunOssUploadStsCallbackParamExtension on AliyunOssUploadStsCallbackParam {
  126 + AliyunOssUploadStsCallbackParam copyWith({
  127 + String? callbackBody,
  128 + String? callbackBodyType,
  129 + String? callbackUrl,
  130 + }) {
  131 + return AliyunOssUploadStsCallbackParam()
  132 + ..callbackBody = callbackBody ?? this.callbackBody
  133 + ..callbackBodyType = callbackBodyType ?? this.callbackBodyType
  134 + ..callbackUrl = callbackUrl ?? this.callbackUrl;
  135 + }
  136 +}
88 137 \ No newline at end of file
... ...
lib/generated/json/base/json_convert_content.dart
... ... @@ -10,30 +10,47 @@ import &#39;package:wow_english/models/course_module_entity.dart&#39;;
10 10 import 'package:wow_english/models/course_process_entity.dart';
11 11 import 'package:wow_english/models/follow_read_entity.dart';
12 12 import 'package:wow_english/models/listen_entity.dart';
  13 +import 'package:wow_english/models/product_entity.dart';
13 14 import 'package:wow_english/models/read_content_entity.dart';
14 15 import 'package:wow_english/models/user_entity.dart';
15 16  
16 17 JsonConvert jsonConvert = JsonConvert();
  18 +
17 19 typedef JsonConvertFunction<T> = T Function(Map<String, dynamic> json);
18 20 typedef EnumConvertFunction<T> = T Function(String value);
  21 +typedef ConvertExceptionHandler = void Function(Object error, StackTrace stackTrace);
  22 +extension MapSafeExt<K, V> on Map<K, V> {
  23 + T? getOrNull<T>(K? key) {
  24 + if (!containsKey(key) || key == null) {
  25 + return null;
  26 + } else {
  27 + return this[key] as T?;
  28 + }
  29 + }
  30 +}
19 31  
20 32 class JsonConvert {
21   - static final Map<String, JsonConvertFunction> convertFuncMap = {
22   - (AliyunOssUploadStsEntity).toString(): AliyunOssUploadStsEntity.fromJson,
23   - (AliyunOssUploadStsCallbackParam).toString(): AliyunOssUploadStsCallbackParam.fromJson,
24   - (CourseEntity).toString(): CourseEntity.fromJson,
25   - (CourseCourseLessons).toString(): CourseCourseLessons.fromJson,
26   - (CourseModuleEntity).toString(): CourseModuleEntity.fromJson,
27   - (CourseProcessEntity).toString(): CourseProcessEntity.fromJson,
28   - (CourseProcessReadings).toString(): CourseProcessReadings.fromJson,
29   - (CourseProcessTopics).toString(): CourseProcessTopics.fromJson,
30   - (CourseProcessTopicsTopicAnswerList).toString(): CourseProcessTopicsTopicAnswerList.fromJson,
31   - (CourseProcessVideos).toString(): CourseProcessVideos.fromJson,
32   - (FollowReadEntity).toString(): FollowReadEntity.fromJson,
33   - (ListenEntity).toString(): ListenEntity.fromJson,
34   - (ReadContentEntity).toString(): ReadContentEntity.fromJson,
35   - (UserEntity).toString(): UserEntity.fromJson,
36   - };
  33 + static ConvertExceptionHandler? onError;
  34 + JsonConvertClassCollection convertFuncMap = JsonConvertClassCollection();
  35 +
  36 + /// When you are in the development, to generate a new model class, hot-reload doesn't find new generation model class, you can build on MaterialApp method called jsonConvert. ReassembleConvertFuncMap (); This method only works in a development environment
  37 + /// https://flutter.cn/docs/development/tools/hot-reload
  38 + /// class MyApp extends StatelessWidget {
  39 + /// const MyApp({Key? key})
  40 + /// : super(key: key);
  41 + ///
  42 + /// @override
  43 + /// Widget build(BuildContext context) {
  44 + /// jsonConvert.reassembleConvertFuncMap();
  45 + /// return MaterialApp();
  46 + /// }
  47 + /// }
  48 + void reassembleConvertFuncMap() {
  49 + bool isReleaseMode = const bool.fromEnvironment('dart.vm.product');
  50 + if (!isReleaseMode) {
  51 + convertFuncMap = JsonConvertClassCollection();
  52 + }
  53 + }
37 54  
38 55 T? convert<T>(dynamic value, {EnumConvertFunction? enumConvert}) {
39 56 if (value == null) {
... ... @@ -46,30 +63,43 @@ class JsonConvert {
46 63 return _asT<T>(value, enumConvert: enumConvert);
47 64 } catch (e, stackTrace) {
48 65 debugPrint('asT<$T> $e $stackTrace');
  66 + if (onError != null) {
  67 + onError!(e, stackTrace);
  68 + }
49 69 return null;
50 70 }
51 71 }
52 72  
53   - List<T?>? convertList<T>(List<dynamic>? value, {EnumConvertFunction? enumConvert}) {
  73 + List<T?>? convertList<T>(List<dynamic>? value,
  74 + {EnumConvertFunction? enumConvert}) {
54 75 if (value == null) {
55 76 return null;
56 77 }
57 78 try {
58   - return value.map((dynamic e) => _asT<T>(e,enumConvert: enumConvert)).toList();
  79 + return value.map((dynamic e) => _asT<T>(e, enumConvert: enumConvert))
  80 + .toList();
59 81 } catch (e, stackTrace) {
60 82 debugPrint('asT<$T> $e $stackTrace');
  83 + if (onError != null) {
  84 + onError!(e, stackTrace);
  85 + }
61 86 return <T>[];
62 87 }
63 88 }
64 89  
65   -List<T>? convertListNotNull<T>(dynamic value, {EnumConvertFunction? enumConvert}) {
  90 + List<T>? convertListNotNull<T>(dynamic value,
  91 + {EnumConvertFunction? enumConvert}) {
66 92 if (value == null) {
67 93 return null;
68 94 }
69 95 try {
70   - return (value as List<dynamic>).map((dynamic e) => _asT<T>(e,enumConvert: enumConvert)!).toList();
  96 + return (value as List<dynamic>).map((dynamic e) =>
  97 + _asT<T>(e, enumConvert: enumConvert)!).toList();
71 98 } catch (e, stackTrace) {
72 99 debugPrint('asT<$T> $e $stackTrace');
  100 + if (onError != null) {
  101 + onError!(e, stackTrace);
  102 + }
73 103 return <T>[];
74 104 }
75 105 }
... ... @@ -102,68 +132,126 @@ List&lt;T&gt;? convertListNotNull&lt;T&gt;(dynamic value, {EnumConvertFunction? enumConvert}
102 132 return value as T;
103 133 } else {
104 134 if (convertFuncMap.containsKey(type)) {
105   - return convertFuncMap[type]!(Map<String, dynamic>.from(value)) as T;
  135 + if (value == null) {
  136 + return null;
  137 + }
  138 + return convertFuncMap[type]!(value as Map<String, dynamic>) as T;
106 139 } else {
107   - throw UnimplementedError('$type unimplemented');
  140 + throw UnimplementedError(
  141 + '$type unimplemented,you can try running the app again');
108 142 }
109 143 }
110 144 }
111 145  
112   - //list is returned by type
113   - static M? _getListChildType<M>(List<Map<String, dynamic>> data) {
114   - if(<AliyunOssUploadStsEntity>[] is M){
115   - return data.map<AliyunOssUploadStsEntity>((Map<String, dynamic> e) => AliyunOssUploadStsEntity.fromJson(e)).toList() as M;
116   - }
117   - if(<AliyunOssUploadStsCallbackParam>[] is M){
118   - return data.map<AliyunOssUploadStsCallbackParam>((Map<String, dynamic> e) => AliyunOssUploadStsCallbackParam.fromJson(e)).toList() as M;
119   - }
120   - if(<CourseEntity>[] is M){
121   - return data.map<CourseEntity>((Map<String, dynamic> e) => CourseEntity.fromJson(e)).toList() as M;
122   - }
123   - if(<CourseCourseLessons>[] is M){
124   - return data.map<CourseCourseLessons>((Map<String, dynamic> e) => CourseCourseLessons.fromJson(e)).toList() as M;
125   - }
126   - if(<CourseModuleEntity>[] is M){
127   - return data.map<CourseModuleEntity>((Map<String, dynamic> e) => CourseModuleEntity.fromJson(e)).toList() as M;
128   - }
129   - if(<CourseProcessEntity>[] is M){
130   - return data.map<CourseProcessEntity>((Map<String, dynamic> e) => CourseProcessEntity.fromJson(e)).toList() as M;
131   - }
132   - if(<CourseProcessReadings>[] is M){
133   - return data.map<CourseProcessReadings>((Map<String, dynamic> e) => CourseProcessReadings.fromJson(e)).toList() as M;
134   - }
135   - if(<CourseProcessTopics>[] is M){
136   - return data.map<CourseProcessTopics>((Map<String, dynamic> e) => CourseProcessTopics.fromJson(e)).toList() as M;
137   - }
138   - if(<CourseProcessTopicsTopicAnswerList>[] is M){
139   - return data.map<CourseProcessTopicsTopicAnswerList>((Map<String, dynamic> e) => CourseProcessTopicsTopicAnswerList.fromJson(e)).toList() as M;
140   - }
141   - if(<CourseProcessVideos>[] is M){
142   - return data.map<CourseProcessVideos>((Map<String, dynamic> e) => CourseProcessVideos.fromJson(e)).toList() as M;
143   - }
144   - if(<FollowReadEntity>[] is M){
145   - return data.map<FollowReadEntity>((Map<String, dynamic> e) => FollowReadEntity.fromJson(e)).toList() as M;
146   - }
147   - if(<ListenEntity>[] is M){
148   - return data.map<ListenEntity>((Map<String, dynamic> e) => ListenEntity.fromJson(e)).toList() as M;
149   - }
150   - if(<ReadContentEntity>[] is M){
151   - return data.map<ReadContentEntity>((Map<String, dynamic> e) => ReadContentEntity.fromJson(e)).toList() as M;
152   - }
153   - if(<UserEntity>[] is M){
154   - return data.map<UserEntity>((Map<String, dynamic> e) => UserEntity.fromJson(e)).toList() as M;
155   - }
156   -
157   - debugPrint("${M.toString()} not found");
158   -
159   - return null;
160   -}
  146 + //list is returned by type
  147 + static M? _getListChildType<M>(List<Map<String, dynamic>> data) {
  148 + if (<AliyunOssUploadStsEntity>[] is M) {
  149 + return data.map<AliyunOssUploadStsEntity>((Map<String, dynamic> e) =>
  150 + AliyunOssUploadStsEntity.fromJson(e)).toList() as M;
  151 + }
  152 + if (<AliyunOssUploadStsCallbackParam>[] is M) {
  153 + return data.map<AliyunOssUploadStsCallbackParam>((
  154 + Map<String, dynamic> e) =>
  155 + AliyunOssUploadStsCallbackParam.fromJson(e)).toList() as M;
  156 + }
  157 + if (<CourseEntity>[] is M) {
  158 + return data.map<CourseEntity>((Map<String, dynamic> e) =>
  159 + CourseEntity.fromJson(e)).toList() as M;
  160 + }
  161 + if (<CourseCourseLessons>[] is M) {
  162 + return data.map<CourseCourseLessons>((Map<String, dynamic> e) =>
  163 + CourseCourseLessons.fromJson(e)).toList() as M;
  164 + }
  165 + if (<CourseModuleEntity>[] is M) {
  166 + return data.map<CourseModuleEntity>((Map<String, dynamic> e) =>
  167 + CourseModuleEntity.fromJson(e)).toList() as M;
  168 + }
  169 + if (<CourseProcessEntity>[] is M) {
  170 + return data.map<CourseProcessEntity>((Map<String, dynamic> e) =>
  171 + CourseProcessEntity.fromJson(e)).toList() as M;
  172 + }
  173 + if (<CourseProcessReadings>[] is M) {
  174 + return data.map<CourseProcessReadings>((Map<String, dynamic> e) =>
  175 + CourseProcessReadings.fromJson(e)).toList() as M;
  176 + }
  177 + if (<CourseProcessTopics>[] is M) {
  178 + return data.map<CourseProcessTopics>((Map<String, dynamic> e) =>
  179 + CourseProcessTopics.fromJson(e)).toList() as M;
  180 + }
  181 + if (<CourseProcessTopicsTopicAnswerList>[] is M) {
  182 + return data.map<CourseProcessTopicsTopicAnswerList>((
  183 + Map<String, dynamic> e) =>
  184 + CourseProcessTopicsTopicAnswerList.fromJson(e)).toList() as M;
  185 + }
  186 + if (<CourseProcessVideos>[] is M) {
  187 + return data.map<CourseProcessVideos>((Map<String, dynamic> e) =>
  188 + CourseProcessVideos.fromJson(e)).toList() as M;
  189 + }
  190 + if (<FollowReadEntity>[] is M) {
  191 + return data.map<FollowReadEntity>((Map<String, dynamic> e) =>
  192 + FollowReadEntity.fromJson(e)).toList() as M;
  193 + }
  194 + if (<ListenEntity>[] is M) {
  195 + return data.map<ListenEntity>((Map<String, dynamic> e) =>
  196 + ListenEntity.fromJson(e)).toList() as M;
  197 + }
  198 + if (<ProductEntity>[] is M) {
  199 + return data.map<ProductEntity>((Map<String, dynamic> e) =>
  200 + ProductEntity.fromJson(e)).toList() as M;
  201 + }
  202 + if (<ReadContentEntity>[] is M) {
  203 + return data.map<ReadContentEntity>((Map<String, dynamic> e) =>
  204 + ReadContentEntity.fromJson(e)).toList() as M;
  205 + }
  206 + if (<UserEntity>[] is M) {
  207 + return data.map<UserEntity>((Map<String, dynamic> e) =>
  208 + UserEntity.fromJson(e)).toList() as M;
  209 + }
161 210  
162   - static M? fromJsonAsT<M>(dynamic json) {
163   - if (json is List) {
164   - return _getListChildType<M>(json.map((e) => e as Map<String, dynamic>).toList());
165   - } else {
166   - return jsonConvert.convert<M>(json);
167   - }
168   - }
  211 + debugPrint("$M not found");
  212 +
  213 + return null;
  214 + }
  215 +
  216 + static M? fromJsonAsT<M>(dynamic json) {
  217 + if (json is M) {
  218 + return json;
  219 + }
  220 + if (json is List) {
  221 + return _getListChildType<M>(
  222 + json.map((dynamic e) => e as Map<String, dynamic>).toList());
  223 + } else {
  224 + return jsonConvert.convert<M>(json);
  225 + }
  226 + }
169 227 }
  228 +
  229 +class JsonConvertClassCollection {
  230 + Map<String, JsonConvertFunction> convertFuncMap = {
  231 + (AliyunOssUploadStsEntity).toString(): AliyunOssUploadStsEntity.fromJson,
  232 + (AliyunOssUploadStsCallbackParam)
  233 + .toString(): AliyunOssUploadStsCallbackParam.fromJson,
  234 + (CourseEntity).toString(): CourseEntity.fromJson,
  235 + (CourseCourseLessons).toString(): CourseCourseLessons.fromJson,
  236 + (CourseModuleEntity).toString(): CourseModuleEntity.fromJson,
  237 + (CourseProcessEntity).toString(): CourseProcessEntity.fromJson,
  238 + (CourseProcessReadings).toString(): CourseProcessReadings.fromJson,
  239 + (CourseProcessTopics).toString(): CourseProcessTopics.fromJson,
  240 + (CourseProcessTopicsTopicAnswerList)
  241 + .toString(): CourseProcessTopicsTopicAnswerList.fromJson,
  242 + (CourseProcessVideos).toString(): CourseProcessVideos.fromJson,
  243 + (FollowReadEntity).toString(): FollowReadEntity.fromJson,
  244 + (ListenEntity).toString(): ListenEntity.fromJson,
  245 + (ProductEntity).toString(): ProductEntity.fromJson,
  246 + (ReadContentEntity).toString(): ReadContentEntity.fromJson,
  247 + (UserEntity).toString(): UserEntity.fromJson,
  248 + };
  249 +
  250 + bool containsKey(String type) {
  251 + return convertFuncMap.containsKey(type);
  252 + }
  253 +
  254 + JsonConvertFunction? operator [](String key) {
  255 + return convertFuncMap[key];
  256 + }
  257 +}
170 258 \ No newline at end of file
... ...
lib/generated/json/base/json_field.dart
... ... @@ -4,10 +4,14 @@
4 4  
5 5 // This file is automatically generated. DO NOT EDIT, all your changes would be lost.
6 6  
7   -class JsonSerializable{
8   - const JsonSerializable();
  7 +import 'package:meta/meta_meta.dart';
  8 +
  9 +@Target({TargetKind.classType})
  10 +class JsonSerializable {
  11 + const JsonSerializable();
9 12 }
10 13  
  14 +@Target({TargetKind.field})
11 15 class JSONField {
12 16 //Specify the parse field name
13 17 final String? name;
... ... @@ -18,8 +22,11 @@ class JSONField {
18 22 //Whether to participate in fromMap
19 23 final bool? deserialize;
20 24  
  25 + //Whether to participate in copyWith
  26 + final bool? copyWith;
  27 +
21 28 //Enumeration or not
22 29 final bool? isEnum;
23 30  
24   - const JSONField({this.name, this.serialize, this.deserialize, this.isEnum});
  31 + const JSONField({this.name, this.serialize, this.deserialize, this.isEnum, this.copyWith});
25 32 }
... ...
lib/generated/json/course_entity.g.dart
... ... @@ -2,116 +2,181 @@ import &#39;package:wow_english/generated/json/base/json_convert_content.dart&#39;;
2 2 import 'package:wow_english/models/course_entity.dart';
3 3  
4 4 CourseEntity $CourseEntityFromJson(Map<String, dynamic> json) {
5   - final CourseEntity courseEntity = CourseEntity();
6   - final List<CourseCourseLessons>? courseLessons = jsonConvert.convertListNotNull<CourseCourseLessons>(json['courseLessons']);
7   - if (courseLessons != null) {
8   - courseEntity.courseLessons = courseLessons;
9   - }
10   - final int? nowCourseLesson = jsonConvert.convert<int>(json['nowCourseLesson']);
11   - if (nowCourseLesson != null) {
12   - courseEntity.nowCourseLesson = nowCourseLesson;
13   - }
14   - final int? nowCourseModuleId = jsonConvert.convert<int>(json['nowCourseModuleId']);
15   - if (nowCourseModuleId != null) {
16   - courseEntity.nowCourseModuleId = nowCourseModuleId;
17   - }
18   - final String? nowCourseModuleName = jsonConvert.convert<String>(json['nowCourseModuleName']);
19   - if (nowCourseModuleName != null) {
20   - courseEntity.nowCourseModuleName = nowCourseModuleName;
21   - }
22   - final int? totalCourseLesson = jsonConvert.convert<int>(json['totalCourseLesson']);
23   - if (totalCourseLesson != null) {
24   - courseEntity.totalCourseLesson = totalCourseLesson;
25   - }
26   - final String? courseModuleThemeColor = jsonConvert.convert<String>(json['courseModuleThemeColor']);
27   - if (courseModuleThemeColor != null) {
28   - courseEntity.courseModuleThemeColor = courseModuleThemeColor;
29   - }
30   - final String? courseModuleCode = jsonConvert.convert<String>(json['courseModuleCode']);
31   - if (courseModuleCode != null) {
32   - courseEntity.courseModuleCode = courseModuleCode;
33   - }
34   - return courseEntity;
  5 + final CourseEntity courseEntity = CourseEntity();
  6 + final List<
  7 + CourseCourseLessons>? courseLessons = (json['courseLessons'] as List<
  8 + dynamic>?)
  9 + ?.map(
  10 + (e) =>
  11 + jsonConvert.convert<CourseCourseLessons>(e) as CourseCourseLessons)
  12 + .toList();
  13 + if (courseLessons != null) {
  14 + courseEntity.courseLessons = courseLessons;
  15 + }
  16 + final int? nowCourseLesson = jsonConvert.convert<int>(
  17 + json['nowCourseLesson']);
  18 + if (nowCourseLesson != null) {
  19 + courseEntity.nowCourseLesson = nowCourseLesson;
  20 + }
  21 + final int? nowCourseModuleId = jsonConvert.convert<int>(
  22 + json['nowCourseModuleId']);
  23 + if (nowCourseModuleId != null) {
  24 + courseEntity.nowCourseModuleId = nowCourseModuleId;
  25 + }
  26 + final String? nowCourseModuleName = jsonConvert.convert<String>(
  27 + json['nowCourseModuleName']);
  28 + if (nowCourseModuleName != null) {
  29 + courseEntity.nowCourseModuleName = nowCourseModuleName;
  30 + }
  31 + final int? totalCourseLesson = jsonConvert.convert<int>(
  32 + json['totalCourseLesson']);
  33 + if (totalCourseLesson != null) {
  34 + courseEntity.totalCourseLesson = totalCourseLesson;
  35 + }
  36 + final String? courseModuleThemeColor = jsonConvert.convert<String>(
  37 + json['courseModuleThemeColor']);
  38 + if (courseModuleThemeColor != null) {
  39 + courseEntity.courseModuleThemeColor = courseModuleThemeColor;
  40 + }
  41 + final String? courseModuleCode = jsonConvert.convert<String>(
  42 + json['courseModuleCode']);
  43 + if (courseModuleCode != null) {
  44 + courseEntity.courseModuleCode = courseModuleCode;
  45 + }
  46 + return courseEntity;
35 47 }
36 48  
37 49 Map<String, dynamic> $CourseEntityToJson(CourseEntity entity) {
38   - final Map<String, dynamic> data = <String, dynamic>{};
39   - data['courseLessons'] = entity.courseLessons?.map((v) => v.toJson()).toList();
40   - data['nowCourseLesson'] = entity.nowCourseLesson;
41   - data['nowCourseModuleId'] = entity.nowCourseModuleId;
42   - data['nowCourseModuleName'] = entity.nowCourseModuleName;
43   - data['totalCourseLesson'] = entity.totalCourseLesson;
44   - data['courseModuleThemeColor'] = entity.courseModuleThemeColor;
45   - data['courseModuleCode'] = entity.courseModuleCode;
46   - return data;
  50 + final Map<String, dynamic> data = <String, dynamic>{};
  51 + data['courseLessons'] = entity.courseLessons?.map((v) => v.toJson()).toList();
  52 + data['nowCourseLesson'] = entity.nowCourseLesson;
  53 + data['nowCourseModuleId'] = entity.nowCourseModuleId;
  54 + data['nowCourseModuleName'] = entity.nowCourseModuleName;
  55 + data['totalCourseLesson'] = entity.totalCourseLesson;
  56 + data['courseModuleThemeColor'] = entity.courseModuleThemeColor;
  57 + data['courseModuleCode'] = entity.courseModuleCode;
  58 + return data;
  59 +}
  60 +
  61 +extension CourseEntityExtension on CourseEntity {
  62 + CourseEntity copyWith({
  63 + List<CourseCourseLessons>? courseLessons,
  64 + int? nowCourseLesson,
  65 + int? nowCourseModuleId,
  66 + String? nowCourseModuleName,
  67 + int? totalCourseLesson,
  68 + String? courseModuleThemeColor,
  69 + String? courseModuleCode,
  70 + }) {
  71 + return CourseEntity()
  72 + ..courseLessons = courseLessons ?? this.courseLessons
  73 + ..nowCourseLesson = nowCourseLesson ?? this.nowCourseLesson
  74 + ..nowCourseModuleId = nowCourseModuleId ?? this.nowCourseModuleId
  75 + ..nowCourseModuleName = nowCourseModuleName ?? this.nowCourseModuleName
  76 + ..totalCourseLesson = totalCourseLesson ?? this.totalCourseLesson
  77 + ..courseModuleThemeColor = courseModuleThemeColor ??
  78 + this.courseModuleThemeColor
  79 + ..courseModuleCode = courseModuleCode ?? this.courseModuleCode;
  80 + }
47 81 }
48 82  
49 83 CourseCourseLessons $CourseCourseLessonsFromJson(Map<String, dynamic> json) {
50   - final CourseCourseLessons courseCourseLessons = CourseCourseLessons();
51   - final int? courseModuleId = jsonConvert.convert<int>(json['courseModuleId']);
52   - if (courseModuleId != null) {
53   - courseCourseLessons.courseModuleId = courseModuleId;
54   - }
55   - final int? courseType = jsonConvert.convert<int>(json['courseType']);
56   - if (courseType != null) {
57   - courseCourseLessons.courseType = courseType;
58   - }
59   - final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
60   - if (coverUrl != null) {
61   - courseCourseLessons.coverUrl = coverUrl;
62   - }
63   - final String? createTime = jsonConvert.convert<String>(json['createTime']);
64   - if (createTime != null) {
65   - courseCourseLessons.createTime = createTime;
66   - }
67   - final String? deleted = jsonConvert.convert<String>(json['deleted']);
68   - if (deleted != null) {
69   - courseCourseLessons.deleted = deleted;
70   - }
71   - final String? des = jsonConvert.convert<String>(json['des']);
72   - if (des != null) {
73   - courseCourseLessons.des = des;
74   - }
75   - final String? id = jsonConvert.convert<String>(json['id']);
76   - if (id != null) {
77   - courseCourseLessons.id = id;
78   - }
79   - final bool? lock = jsonConvert.convert<bool>(json['lock']);
80   - if (lock != null) {
81   - courseCourseLessons.lock = lock;
82   - }
83   - final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
84   - if (modifyTime != null) {
85   - courseCourseLessons.modifyTime = modifyTime;
86   - }
87   - final String? name = jsonConvert.convert<String>(json['name']);
88   - if (name != null) {
89   - courseCourseLessons.name = name;
90   - }
91   - final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
92   - if (sortOrder != null) {
93   - courseCourseLessons.sortOrder = sortOrder;
94   - }
95   - final int? status = jsonConvert.convert<int>(json['status']);
96   - if (status != null) {
97   - courseCourseLessons.status = status;
98   - }
99   - return courseCourseLessons;
  84 + final CourseCourseLessons courseCourseLessons = CourseCourseLessons();
  85 + final int? courseModuleId = jsonConvert.convert<int>(json['courseModuleId']);
  86 + if (courseModuleId != null) {
  87 + courseCourseLessons.courseModuleId = courseModuleId;
  88 + }
  89 + final int? courseType = jsonConvert.convert<int>(json['courseType']);
  90 + if (courseType != null) {
  91 + courseCourseLessons.courseType = courseType;
  92 + }
  93 + final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
  94 + if (coverUrl != null) {
  95 + courseCourseLessons.coverUrl = coverUrl;
  96 + }
  97 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  98 + if (createTime != null) {
  99 + courseCourseLessons.createTime = createTime;
  100 + }
  101 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  102 + if (deleted != null) {
  103 + courseCourseLessons.deleted = deleted;
  104 + }
  105 + final String? des = jsonConvert.convert<String>(json['des']);
  106 + if (des != null) {
  107 + courseCourseLessons.des = des;
  108 + }
  109 + final String? id = jsonConvert.convert<String>(json['id']);
  110 + if (id != null) {
  111 + courseCourseLessons.id = id;
  112 + }
  113 + final bool? lock = jsonConvert.convert<bool>(json['lock']);
  114 + if (lock != null) {
  115 + courseCourseLessons.lock = lock;
  116 + }
  117 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  118 + if (modifyTime != null) {
  119 + courseCourseLessons.modifyTime = modifyTime;
  120 + }
  121 + final String? name = jsonConvert.convert<String>(json['name']);
  122 + if (name != null) {
  123 + courseCourseLessons.name = name;
  124 + }
  125 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  126 + if (sortOrder != null) {
  127 + courseCourseLessons.sortOrder = sortOrder;
  128 + }
  129 + final int? status = jsonConvert.convert<int>(json['status']);
  130 + if (status != null) {
  131 + courseCourseLessons.status = status;
  132 + }
  133 + return courseCourseLessons;
100 134 }
101 135  
102 136 Map<String, dynamic> $CourseCourseLessonsToJson(CourseCourseLessons entity) {
103   - final Map<String, dynamic> data = <String, dynamic>{};
104   - data['courseModuleId'] = entity.courseModuleId;
105   - data['courseType'] = entity.courseType;
106   - data['coverUrl'] = entity.coverUrl;
107   - data['createTime'] = entity.createTime;
108   - data['deleted'] = entity.deleted;
109   - data['des'] = entity.des;
110   - data['id'] = entity.id;
111   - data['lock'] = entity.lock;
112   - data['modifyTime'] = entity.modifyTime;
113   - data['name'] = entity.name;
114   - data['sortOrder'] = entity.sortOrder;
115   - data['status'] = entity.status;
116   - return data;
  137 + final Map<String, dynamic> data = <String, dynamic>{};
  138 + data['courseModuleId'] = entity.courseModuleId;
  139 + data['courseType'] = entity.courseType;
  140 + data['coverUrl'] = entity.coverUrl;
  141 + data['createTime'] = entity.createTime;
  142 + data['deleted'] = entity.deleted;
  143 + data['des'] = entity.des;
  144 + data['id'] = entity.id;
  145 + data['lock'] = entity.lock;
  146 + data['modifyTime'] = entity.modifyTime;
  147 + data['name'] = entity.name;
  148 + data['sortOrder'] = entity.sortOrder;
  149 + data['status'] = entity.status;
  150 + return data;
  151 +}
  152 +
  153 +extension CourseCourseLessonsExtension on CourseCourseLessons {
  154 + CourseCourseLessons copyWith({
  155 + int? courseModuleId,
  156 + int? courseType,
  157 + String? coverUrl,
  158 + String? createTime,
  159 + String? deleted,
  160 + String? des,
  161 + String? id,
  162 + bool? lock,
  163 + String? modifyTime,
  164 + String? name,
  165 + int? sortOrder,
  166 + int? status,
  167 + }) {
  168 + return CourseCourseLessons()
  169 + ..courseModuleId = courseModuleId ?? this.courseModuleId
  170 + ..courseType = courseType ?? this.courseType
  171 + ..coverUrl = coverUrl ?? this.coverUrl
  172 + ..createTime = createTime ?? this.createTime
  173 + ..deleted = deleted ?? this.deleted
  174 + ..des = des ?? this.des
  175 + ..id = id ?? this.id
  176 + ..lock = lock ?? this.lock
  177 + ..modifyTime = modifyTime ?? this.modifyTime
  178 + ..name = name ?? this.name
  179 + ..sortOrder = sortOrder ?? this.sortOrder
  180 + ..status = status ?? this.status;
  181 + }
117 182 }
118 183 \ No newline at end of file
... ...
lib/generated/json/course_module_entity.g.dart
... ... @@ -2,86 +2,126 @@ import &#39;package:wow_english/generated/json/base/json_convert_content.dart&#39;;
2 2 import 'package:wow_english/models/course_module_entity.dart';
3 3  
4 4 CourseModuleEntity $CourseModuleEntityFromJson(Map<String, dynamic> json) {
5   - final CourseModuleEntity courseModuleEntity = CourseModuleEntity();
6   - final String? id = jsonConvert.convert<String>(json['id']);
7   - if (id != null) {
8   - courseModuleEntity.id = id;
9   - }
10   - final String? code = jsonConvert.convert<String>(json['code']);
11   - if (code != null) {
12   - courseModuleEntity.code = code;
13   - }
14   - final int? courseModuleThemeId = jsonConvert.convert<int>(json['courseModuleThemeId']);
15   - if (courseModuleThemeId != null) {
16   - courseModuleEntity.courseModuleThemeId = courseModuleThemeId;
17   - }
18   - final int? courseTotal = jsonConvert.convert<int>(json['courseTotal']);
19   - if (courseTotal != null) {
20   - courseModuleEntity.courseTotal = courseTotal;
21   - }
22   - final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
23   - if (coverUrl != null) {
24   - courseModuleEntity.coverUrl = coverUrl;
25   - }
26   - final String? createTime = jsonConvert.convert<String>(json['createTime']);
27   - if (createTime != null) {
28   - courseModuleEntity.createTime = createTime;
29   - }
30   - final String? deleted = jsonConvert.convert<String>(json['deleted']);
31   - if (deleted != null) {
32   - courseModuleEntity.deleted = deleted;
33   - }
34   - final String? des = jsonConvert.convert<String>(json['des']);
35   - if (des != null) {
36   - courseModuleEntity.des = des;
37   - }
38   - final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
39   - if (modifyTime != null) {
40   - courseModuleEntity.modifyTime = modifyTime;
41   - }
42   - final String? name = jsonConvert.convert<String>(json['name']);
43   - if (name != null) {
44   - courseModuleEntity.name = name;
45   - }
46   - final int? opening = jsonConvert.convert<int>(json['opening']);
47   - if (opening != null) {
48   - courseModuleEntity.opening = opening;
49   - }
50   - final String? picUrl = jsonConvert.convert<String>(json['picUrl']);
51   - if (picUrl != null) {
52   - courseModuleEntity.picUrl = picUrl;
53   - }
54   - final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
55   - if (sortOrder != null) {
56   - courseModuleEntity.sortOrder = sortOrder;
57   - }
58   - final int? status = jsonConvert.convert<int>(json['status']);
59   - if (status != null) {
60   - courseModuleEntity.status = status;
61   - }
62   - final String? courseModuleThemeColor = jsonConvert.convert<String>(json['courseModuleThemeColor']);
63   - if (courseModuleThemeColor != null) {
64   - courseModuleEntity.courseModuleThemeColor = courseModuleThemeColor;
65   - }
66   - return courseModuleEntity;
  5 + final CourseModuleEntity courseModuleEntity = CourseModuleEntity();
  6 + final String? id = jsonConvert.convert<String>(json['id']);
  7 + if (id != null) {
  8 + courseModuleEntity.id = id;
  9 + }
  10 + final String? code = jsonConvert.convert<String>(json['code']);
  11 + if (code != null) {
  12 + courseModuleEntity.code = code;
  13 + }
  14 + final int? courseModuleThemeId = jsonConvert.convert<int>(
  15 + json['courseModuleThemeId']);
  16 + if (courseModuleThemeId != null) {
  17 + courseModuleEntity.courseModuleThemeId = courseModuleThemeId;
  18 + }
  19 + final int? courseTotal = jsonConvert.convert<int>(json['courseTotal']);
  20 + if (courseTotal != null) {
  21 + courseModuleEntity.courseTotal = courseTotal;
  22 + }
  23 + final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
  24 + if (coverUrl != null) {
  25 + courseModuleEntity.coverUrl = coverUrl;
  26 + }
  27 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  28 + if (createTime != null) {
  29 + courseModuleEntity.createTime = createTime;
  30 + }
  31 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  32 + if (deleted != null) {
  33 + courseModuleEntity.deleted = deleted;
  34 + }
  35 + final String? des = jsonConvert.convert<String>(json['des']);
  36 + if (des != null) {
  37 + courseModuleEntity.des = des;
  38 + }
  39 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  40 + if (modifyTime != null) {
  41 + courseModuleEntity.modifyTime = modifyTime;
  42 + }
  43 + final String? name = jsonConvert.convert<String>(json['name']);
  44 + if (name != null) {
  45 + courseModuleEntity.name = name;
  46 + }
  47 + final int? opening = jsonConvert.convert<int>(json['opening']);
  48 + if (opening != null) {
  49 + courseModuleEntity.opening = opening;
  50 + }
  51 + final String? picUrl = jsonConvert.convert<String>(json['picUrl']);
  52 + if (picUrl != null) {
  53 + courseModuleEntity.picUrl = picUrl;
  54 + }
  55 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  56 + if (sortOrder != null) {
  57 + courseModuleEntity.sortOrder = sortOrder;
  58 + }
  59 + final int? status = jsonConvert.convert<int>(json['status']);
  60 + if (status != null) {
  61 + courseModuleEntity.status = status;
  62 + }
  63 + final String? courseModuleThemeColor = jsonConvert.convert<String>(
  64 + json['courseModuleThemeColor']);
  65 + if (courseModuleThemeColor != null) {
  66 + courseModuleEntity.courseModuleThemeColor = courseModuleThemeColor;
  67 + }
  68 + return courseModuleEntity;
67 69 }
68 70  
69 71 Map<String, dynamic> $CourseModuleEntityToJson(CourseModuleEntity entity) {
70   - final Map<String, dynamic> data = <String, dynamic>{};
71   - data['id'] = entity.id;
72   - data['code'] = entity.code;
73   - data['courseModuleThemeId'] = entity.courseModuleThemeId;
74   - data['courseTotal'] = entity.courseTotal;
75   - data['coverUrl'] = entity.coverUrl;
76   - data['createTime'] = entity.createTime;
77   - data['deleted'] = entity.deleted;
78   - data['des'] = entity.des;
79   - data['modifyTime'] = entity.modifyTime;
80   - data['name'] = entity.name;
81   - data['opening'] = entity.opening;
82   - data['picUrl'] = entity.picUrl;
83   - data['sortOrder'] = entity.sortOrder;
84   - data['status'] = entity.status;
85   - data['courseModuleThemeColor'] = entity.courseModuleThemeColor;
86   - return data;
  72 + final Map<String, dynamic> data = <String, dynamic>{};
  73 + data['id'] = entity.id;
  74 + data['code'] = entity.code;
  75 + data['courseModuleThemeId'] = entity.courseModuleThemeId;
  76 + data['courseTotal'] = entity.courseTotal;
  77 + data['coverUrl'] = entity.coverUrl;
  78 + data['createTime'] = entity.createTime;
  79 + data['deleted'] = entity.deleted;
  80 + data['des'] = entity.des;
  81 + data['modifyTime'] = entity.modifyTime;
  82 + data['name'] = entity.name;
  83 + data['opening'] = entity.opening;
  84 + data['picUrl'] = entity.picUrl;
  85 + data['sortOrder'] = entity.sortOrder;
  86 + data['status'] = entity.status;
  87 + data['courseModuleThemeColor'] = entity.courseModuleThemeColor;
  88 + return data;
87 89 }
  90 +
  91 +extension CourseModuleEntityExtension on CourseModuleEntity {
  92 + CourseModuleEntity copyWith({
  93 + String? id,
  94 + String? code,
  95 + int? courseModuleThemeId,
  96 + int? courseTotal,
  97 + String? coverUrl,
  98 + String? createTime,
  99 + String? deleted,
  100 + String? des,
  101 + String? modifyTime,
  102 + String? name,
  103 + int? opening,
  104 + String? picUrl,
  105 + int? sortOrder,
  106 + int? status,
  107 + String? courseModuleThemeColor,
  108 + }) {
  109 + return CourseModuleEntity()
  110 + ..id = id ?? this.id
  111 + ..code = code ?? this.code
  112 + ..courseModuleThemeId = courseModuleThemeId ?? this.courseModuleThemeId
  113 + ..courseTotal = courseTotal ?? this.courseTotal
  114 + ..coverUrl = coverUrl ?? this.coverUrl
  115 + ..createTime = createTime ?? this.createTime
  116 + ..deleted = deleted ?? this.deleted
  117 + ..des = des ?? this.des
  118 + ..modifyTime = modifyTime ?? this.modifyTime
  119 + ..name = name ?? this.name
  120 + ..opening = opening ?? this.opening
  121 + ..picUrl = picUrl ?? this.picUrl
  122 + ..sortOrder = sortOrder ?? this.sortOrder
  123 + ..status = status ?? this.status
  124 + ..courseModuleThemeColor = courseModuleThemeColor ??
  125 + this.courseModuleThemeColor;
  126 + }
  127 +}
88 128 \ No newline at end of file
... ...
lib/generated/json/course_process_entity.g.dart
... ... @@ -2,286 +2,435 @@ import &#39;package:wow_english/generated/json/base/json_convert_content.dart&#39;;
2 2 import 'package:wow_english/models/course_process_entity.dart';
3 3  
4 4 CourseProcessEntity $CourseProcessEntityFromJson(Map<String, dynamic> json) {
5   - final CourseProcessEntity courseProcessEntity = CourseProcessEntity();
6   - final int? currentStep = jsonConvert.convert<int>(json['currentStep']);
7   - if (currentStep != null) {
8   - courseProcessEntity.currentStep = currentStep;
9   - }
10   - final int? currentTime = jsonConvert.convert<int>(json['currentTime']);
11   - if (currentTime != null) {
12   - courseProcessEntity.currentTime = currentTime;
13   - }
14   - final List<CourseProcessReadings>? readings = jsonConvert.convertListNotNull<CourseProcessReadings>(json['readings']);
15   - if (readings != null) {
16   - courseProcessEntity.readings = readings;
17   - }
18   - final List<CourseProcessTopics>? topics = jsonConvert.convertListNotNull<CourseProcessTopics>(json['topics']);
19   - if (topics != null) {
20   - courseProcessEntity.topics = topics;
21   - }
22   - final CourseProcessVideos? videos = jsonConvert.convert<CourseProcessVideos>(json['videos']);
23   - if (videos != null) {
24   - courseProcessEntity.videos = videos;
25   - }
26   - return courseProcessEntity;
  5 + final CourseProcessEntity courseProcessEntity = CourseProcessEntity();
  6 + final int? currentStep = jsonConvert.convert<int>(json['currentStep']);
  7 + if (currentStep != null) {
  8 + courseProcessEntity.currentStep = currentStep;
  9 + }
  10 + final int? currentTime = jsonConvert.convert<int>(json['currentTime']);
  11 + if (currentTime != null) {
  12 + courseProcessEntity.currentTime = currentTime;
  13 + }
  14 + final List<CourseProcessReadings>? readings = (json['readings'] as List<
  15 + dynamic>?)
  16 + ?.map(
  17 + (e) =>
  18 + jsonConvert.convert<CourseProcessReadings>(e) as CourseProcessReadings)
  19 + .toList();
  20 + if (readings != null) {
  21 + courseProcessEntity.readings = readings;
  22 + }
  23 + final List<CourseProcessTopics>? topics = (json['topics'] as List<dynamic>?)
  24 + ?.map(
  25 + (e) =>
  26 + jsonConvert.convert<CourseProcessTopics>(e) as CourseProcessTopics)
  27 + .toList();
  28 + if (topics != null) {
  29 + courseProcessEntity.topics = topics;
  30 + }
  31 + final CourseProcessVideos? videos = jsonConvert.convert<CourseProcessVideos>(
  32 + json['videos']);
  33 + if (videos != null) {
  34 + courseProcessEntity.videos = videos;
  35 + }
  36 + return courseProcessEntity;
27 37 }
28 38  
29 39 Map<String, dynamic> $CourseProcessEntityToJson(CourseProcessEntity entity) {
30   - final Map<String, dynamic> data = <String, dynamic>{};
31   - data['currentStep'] = entity.currentStep;
32   - data['currentTime'] = entity.currentTime;
33   - data['readings'] = entity.readings?.map((v) => v.toJson()).toList();
34   - data['topics'] = entity.topics?.map((v) => v.toJson()).toList();
35   - data['videos'] = entity.videos?.toJson();
36   - return data;
  40 + final Map<String, dynamic> data = <String, dynamic>{};
  41 + data['currentStep'] = entity.currentStep;
  42 + data['currentTime'] = entity.currentTime;
  43 + data['readings'] = entity.readings?.map((v) => v.toJson()).toList();
  44 + data['topics'] = entity.topics?.map((v) => v.toJson()).toList();
  45 + data['videos'] = entity.videos?.toJson();
  46 + return data;
37 47 }
38 48  
39   -CourseProcessReadings $CourseProcessReadingsFromJson(Map<String, dynamic> json) {
40   - final CourseProcessReadings courseProcessReadings = CourseProcessReadings();
41   - final String? audioUrl = jsonConvert.convert<String>(json['audioUrl']);
42   - if (audioUrl != null) {
43   - courseProcessReadings.audioUrl = audioUrl;
44   - }
45   - final int? courseLessonId = jsonConvert.convert<int>(json['courseLessonId']);
46   - if (courseLessonId != null) {
47   - courseProcessReadings.courseLessonId = courseLessonId;
48   - }
49   - final String? createTime = jsonConvert.convert<String>(json['createTime']);
50   - if (createTime != null) {
51   - courseProcessReadings.createTime = createTime;
52   - }
53   - final String? deleted = jsonConvert.convert<String>(json['deleted']);
54   - if (deleted != null) {
55   - courseProcessReadings.deleted = deleted;
56   - }
57   - final String? id = jsonConvert.convert<String>(json['id']);
58   - if (id != null) {
59   - courseProcessReadings.id = id;
60   - }
61   - final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
62   - if (modifyTime != null) {
63   - courseProcessReadings.modifyTime = modifyTime;
64   - }
65   - final String? padPicUrl = jsonConvert.convert<String>(json['padPicUrl']);
66   - if (padPicUrl != null) {
67   - courseProcessReadings.padPicUrl = padPicUrl;
68   - }
69   - final String? picUrl = jsonConvert.convert<String>(json['picUrl']);
70   - if (picUrl != null) {
71   - courseProcessReadings.picUrl = picUrl;
72   - }
73   - final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
74   - if (sortOrder != null) {
75   - courseProcessReadings.sortOrder = sortOrder;
76   - }
77   - final String? word = jsonConvert.convert<String>(json['word']);
78   - if (word != null) {
79   - courseProcessReadings.word = word;
80   - }
81   - final String? recordUrl = jsonConvert.convert<String>(json['recordUrl']);
82   - if (recordUrl != null) {
83   - courseProcessReadings.recordUrl = recordUrl;
84   - }
85   - final String? recordScore = jsonConvert.convert<String>(json['recordScore']);
86   - if (recordScore != null) {
87   - courseProcessReadings.recordScore = recordScore;
88   - }
89   - return courseProcessReadings;
  49 +extension CourseProcessEntityExtension on CourseProcessEntity {
  50 + CourseProcessEntity copyWith({
  51 + int? currentStep,
  52 + int? currentTime,
  53 + List<CourseProcessReadings>? readings,
  54 + List<CourseProcessTopics>? topics,
  55 + CourseProcessVideos? videos,
  56 + }) {
  57 + return CourseProcessEntity()
  58 + ..currentStep = currentStep ?? this.currentStep
  59 + ..currentTime = currentTime ?? this.currentTime
  60 + ..readings = readings ?? this.readings
  61 + ..topics = topics ?? this.topics
  62 + ..videos = videos ?? this.videos;
  63 + }
90 64 }
91 65  
92   -Map<String, dynamic> $CourseProcessReadingsToJson(CourseProcessReadings entity) {
93   - final Map<String, dynamic> data = <String, dynamic>{};
94   - data['audioUrl'] = entity.audioUrl;
95   - data['courseLessonId'] = entity.courseLessonId;
96   - data['createTime'] = entity.createTime;
97   - data['deleted'] = entity.deleted;
98   - data['id'] = entity.id;
99   - data['modifyTime'] = entity.modifyTime;
100   - data['padPicUrl'] = entity.padPicUrl;
101   - data['picUrl'] = entity.picUrl;
102   - data['sortOrder'] = entity.sortOrder;
103   - data['word'] = entity.word;
104   - data['recordUrl'] = entity.recordUrl;
105   - data['recordScore'] = entity.recordScore;
106   - return data;
  66 +CourseProcessReadings $CourseProcessReadingsFromJson(
  67 + Map<String, dynamic> json) {
  68 + final CourseProcessReadings courseProcessReadings = CourseProcessReadings();
  69 + final String? audioUrl = jsonConvert.convert<String>(json['audioUrl']);
  70 + if (audioUrl != null) {
  71 + courseProcessReadings.audioUrl = audioUrl;
  72 + }
  73 + final int? courseLessonId = jsonConvert.convert<int>(json['courseLessonId']);
  74 + if (courseLessonId != null) {
  75 + courseProcessReadings.courseLessonId = courseLessonId;
  76 + }
  77 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  78 + if (createTime != null) {
  79 + courseProcessReadings.createTime = createTime;
  80 + }
  81 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  82 + if (deleted != null) {
  83 + courseProcessReadings.deleted = deleted;
  84 + }
  85 + final String? id = jsonConvert.convert<String>(json['id']);
  86 + if (id != null) {
  87 + courseProcessReadings.id = id;
  88 + }
  89 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  90 + if (modifyTime != null) {
  91 + courseProcessReadings.modifyTime = modifyTime;
  92 + }
  93 + final String? padPicUrl = jsonConvert.convert<String>(json['padPicUrl']);
  94 + if (padPicUrl != null) {
  95 + courseProcessReadings.padPicUrl = padPicUrl;
  96 + }
  97 + final String? picUrl = jsonConvert.convert<String>(json['picUrl']);
  98 + if (picUrl != null) {
  99 + courseProcessReadings.picUrl = picUrl;
  100 + }
  101 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  102 + if (sortOrder != null) {
  103 + courseProcessReadings.sortOrder = sortOrder;
  104 + }
  105 + final String? word = jsonConvert.convert<String>(json['word']);
  106 + if (word != null) {
  107 + courseProcessReadings.word = word;
  108 + }
  109 + final String? recordUrl = jsonConvert.convert<String>(json['recordUrl']);
  110 + if (recordUrl != null) {
  111 + courseProcessReadings.recordUrl = recordUrl;
  112 + }
  113 + final String? recordScore = jsonConvert.convert<String>(json['recordScore']);
  114 + if (recordScore != null) {
  115 + courseProcessReadings.recordScore = recordScore;
  116 + }
  117 + return courseProcessReadings;
  118 +}
  119 +
  120 +Map<String, dynamic> $CourseProcessReadingsToJson(
  121 + CourseProcessReadings entity) {
  122 + final Map<String, dynamic> data = <String, dynamic>{};
  123 + data['audioUrl'] = entity.audioUrl;
  124 + data['courseLessonId'] = entity.courseLessonId;
  125 + data['createTime'] = entity.createTime;
  126 + data['deleted'] = entity.deleted;
  127 + data['id'] = entity.id;
  128 + data['modifyTime'] = entity.modifyTime;
  129 + data['padPicUrl'] = entity.padPicUrl;
  130 + data['picUrl'] = entity.picUrl;
  131 + data['sortOrder'] = entity.sortOrder;
  132 + data['word'] = entity.word;
  133 + data['recordUrl'] = entity.recordUrl;
  134 + data['recordScore'] = entity.recordScore;
  135 + return data;
  136 +}
  137 +
  138 +extension CourseProcessReadingsExtension on CourseProcessReadings {
  139 + CourseProcessReadings copyWith({
  140 + String? audioUrl,
  141 + int? courseLessonId,
  142 + String? createTime,
  143 + String? deleted,
  144 + String? id,
  145 + String? modifyTime,
  146 + String? padPicUrl,
  147 + String? picUrl,
  148 + int? sortOrder,
  149 + String? word,
  150 + String? recordUrl,
  151 + String? recordScore,
  152 + }) {
  153 + return CourseProcessReadings()
  154 + ..audioUrl = audioUrl ?? this.audioUrl
  155 + ..courseLessonId = courseLessonId ?? this.courseLessonId
  156 + ..createTime = createTime ?? this.createTime
  157 + ..deleted = deleted ?? this.deleted
  158 + ..id = id ?? this.id
  159 + ..modifyTime = modifyTime ?? this.modifyTime
  160 + ..padPicUrl = padPicUrl ?? this.padPicUrl
  161 + ..picUrl = picUrl ?? this.picUrl
  162 + ..sortOrder = sortOrder ?? this.sortOrder
  163 + ..word = word ?? this.word
  164 + ..recordUrl = recordUrl ?? this.recordUrl
  165 + ..recordScore = recordScore ?? this.recordScore;
  166 + }
107 167 }
108 168  
109 169 CourseProcessTopics $CourseProcessTopicsFromJson(Map<String, dynamic> json) {
110   - final CourseProcessTopics courseProcessTopics = CourseProcessTopics();
111   - final String? audioUrl = jsonConvert.convert<String>(json['audioUrl']);
112   - if (audioUrl != null) {
113   - courseProcessTopics.audioUrl = audioUrl;
114   - }
115   - final int? courseLessonId = jsonConvert.convert<int>(json['courseLessonId']);
116   - if (courseLessonId != null) {
117   - courseProcessTopics.courseLessonId = courseLessonId;
118   - }
119   - final String? createTime = jsonConvert.convert<String>(json['createTime']);
120   - if (createTime != null) {
121   - courseProcessTopics.createTime = createTime;
122   - }
123   - final String? deleted = jsonConvert.convert<String>(json['deleted']);
124   - if (deleted != null) {
125   - courseProcessTopics.deleted = deleted;
126   - }
127   - final String? id = jsonConvert.convert<String>(json['id']);
128   - if (id != null) {
129   - courseProcessTopics.id = id;
130   - }
131   - final String? keyWord = jsonConvert.convert<String>(json['keyWord']);
132   - if (keyWord != null) {
133   - courseProcessTopics.keyWord = keyWord;
134   - }
135   - final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
136   - if (modifyTime != null) {
137   - courseProcessTopics.modifyTime = modifyTime;
138   - }
139   - final String? picUrl = jsonConvert.convert<String>(json['picUrl']);
140   - if (picUrl != null) {
141   - courseProcessTopics.picUrl = picUrl;
142   - }
143   - final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
144   - if (sortOrder != null) {
145   - courseProcessTopics.sortOrder = sortOrder;
146   - }
147   - final int? status = jsonConvert.convert<int>(json['status']);
148   - if (status != null) {
149   - courseProcessTopics.status = status;
150   - }
151   - final List<CourseProcessTopicsTopicAnswerList>? topicAnswerList = jsonConvert.convertListNotNull<CourseProcessTopicsTopicAnswerList>(json['topicAnswerList']);
152   - if (topicAnswerList != null) {
153   - courseProcessTopics.topicAnswerList = topicAnswerList;
154   - }
155   - final int? type = jsonConvert.convert<int>(json['type']);
156   - if (type != null) {
157   - courseProcessTopics.type = type;
158   - }
159   - final String? word = jsonConvert.convert<String>(json['word']);
160   - if (word != null) {
161   - courseProcessTopics.word = word;
162   - }
163   - return courseProcessTopics;
  170 + final CourseProcessTopics courseProcessTopics = CourseProcessTopics();
  171 + final String? audioUrl = jsonConvert.convert<String>(json['audioUrl']);
  172 + if (audioUrl != null) {
  173 + courseProcessTopics.audioUrl = audioUrl;
  174 + }
  175 + final int? courseLessonId = jsonConvert.convert<int>(json['courseLessonId']);
  176 + if (courseLessonId != null) {
  177 + courseProcessTopics.courseLessonId = courseLessonId;
  178 + }
  179 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  180 + if (createTime != null) {
  181 + courseProcessTopics.createTime = createTime;
  182 + }
  183 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  184 + if (deleted != null) {
  185 + courseProcessTopics.deleted = deleted;
  186 + }
  187 + final String? id = jsonConvert.convert<String>(json['id']);
  188 + if (id != null) {
  189 + courseProcessTopics.id = id;
  190 + }
  191 + final String? keyWord = jsonConvert.convert<String>(json['keyWord']);
  192 + if (keyWord != null) {
  193 + courseProcessTopics.keyWord = keyWord;
  194 + }
  195 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  196 + if (modifyTime != null) {
  197 + courseProcessTopics.modifyTime = modifyTime;
  198 + }
  199 + final String? picUrl = jsonConvert.convert<String>(json['picUrl']);
  200 + if (picUrl != null) {
  201 + courseProcessTopics.picUrl = picUrl;
  202 + }
  203 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  204 + if (sortOrder != null) {
  205 + courseProcessTopics.sortOrder = sortOrder;
  206 + }
  207 + final int? status = jsonConvert.convert<int>(json['status']);
  208 + if (status != null) {
  209 + courseProcessTopics.status = status;
  210 + }
  211 + final List<
  212 + CourseProcessTopicsTopicAnswerList>? topicAnswerList = (json['topicAnswerList'] as List<
  213 + dynamic>?)?.map(
  214 + (e) =>
  215 + jsonConvert.convert<CourseProcessTopicsTopicAnswerList>(
  216 + e) as CourseProcessTopicsTopicAnswerList).toList();
  217 + if (topicAnswerList != null) {
  218 + courseProcessTopics.topicAnswerList = topicAnswerList;
  219 + }
  220 + final int? type = jsonConvert.convert<int>(json['type']);
  221 + if (type != null) {
  222 + courseProcessTopics.type = type;
  223 + }
  224 + final String? word = jsonConvert.convert<String>(json['word']);
  225 + if (word != null) {
  226 + courseProcessTopics.word = word;
  227 + }
  228 + return courseProcessTopics;
164 229 }
165 230  
166 231 Map<String, dynamic> $CourseProcessTopicsToJson(CourseProcessTopics entity) {
167   - final Map<String, dynamic> data = <String, dynamic>{};
168   - data['audioUrl'] = entity.audioUrl;
169   - data['courseLessonId'] = entity.courseLessonId;
170   - data['createTime'] = entity.createTime;
171   - data['deleted'] = entity.deleted;
172   - data['id'] = entity.id;
173   - data['keyWord'] = entity.keyWord;
174   - data['modifyTime'] = entity.modifyTime;
175   - data['picUrl'] = entity.picUrl;
176   - data['sortOrder'] = entity.sortOrder;
177   - data['status'] = entity.status;
178   - data['topicAnswerList'] = entity.topicAnswerList?.map((v) => v.toJson()).toList();
179   - data['type'] = entity.type;
180   - data['word'] = entity.word;
181   - return data;
  232 + final Map<String, dynamic> data = <String, dynamic>{};
  233 + data['audioUrl'] = entity.audioUrl;
  234 + data['courseLessonId'] = entity.courseLessonId;
  235 + data['createTime'] = entity.createTime;
  236 + data['deleted'] = entity.deleted;
  237 + data['id'] = entity.id;
  238 + data['keyWord'] = entity.keyWord;
  239 + data['modifyTime'] = entity.modifyTime;
  240 + data['picUrl'] = entity.picUrl;
  241 + data['sortOrder'] = entity.sortOrder;
  242 + data['status'] = entity.status;
  243 + data['topicAnswerList'] =
  244 + entity.topicAnswerList?.map((v) => v.toJson()).toList();
  245 + data['type'] = entity.type;
  246 + data['word'] = entity.word;
  247 + return data;
  248 +}
  249 +
  250 +extension CourseProcessTopicsExtension on CourseProcessTopics {
  251 + CourseProcessTopics copyWith({
  252 + String? audioUrl,
  253 + int? courseLessonId,
  254 + String? createTime,
  255 + String? deleted,
  256 + String? id,
  257 + String? keyWord,
  258 + String? modifyTime,
  259 + String? picUrl,
  260 + int? sortOrder,
  261 + int? status,
  262 + List<CourseProcessTopicsTopicAnswerList>? topicAnswerList,
  263 + int? type,
  264 + String? word,
  265 + }) {
  266 + return CourseProcessTopics()
  267 + ..audioUrl = audioUrl ?? this.audioUrl
  268 + ..courseLessonId = courseLessonId ?? this.courseLessonId
  269 + ..createTime = createTime ?? this.createTime
  270 + ..deleted = deleted ?? this.deleted
  271 + ..id = id ?? this.id
  272 + ..keyWord = keyWord ?? this.keyWord
  273 + ..modifyTime = modifyTime ?? this.modifyTime
  274 + ..picUrl = picUrl ?? this.picUrl
  275 + ..sortOrder = sortOrder ?? this.sortOrder
  276 + ..status = status ?? this.status
  277 + ..topicAnswerList = topicAnswerList ?? this.topicAnswerList
  278 + ..type = type ?? this.type
  279 + ..word = word ?? this.word;
  280 + }
  281 +}
  282 +
  283 +CourseProcessTopicsTopicAnswerList $CourseProcessTopicsTopicAnswerListFromJson(
  284 + Map<String, dynamic> json) {
  285 + final CourseProcessTopicsTopicAnswerList courseProcessTopicsTopicAnswerList = CourseProcessTopicsTopicAnswerList();
  286 + final int? correct = jsonConvert.convert<int>(json['correct']);
  287 + if (correct != null) {
  288 + courseProcessTopicsTopicAnswerList.correct = correct;
  289 + }
  290 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  291 + if (createTime != null) {
  292 + courseProcessTopicsTopicAnswerList.createTime = createTime;
  293 + }
  294 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  295 + if (deleted != null) {
  296 + courseProcessTopicsTopicAnswerList.deleted = deleted;
  297 + }
  298 + final String? id = jsonConvert.convert<String>(json['id']);
  299 + if (id != null) {
  300 + courseProcessTopicsTopicAnswerList.id = id;
  301 + }
  302 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  303 + if (modifyTime != null) {
  304 + courseProcessTopicsTopicAnswerList.modifyTime = modifyTime;
  305 + }
  306 + final String? picUrl = jsonConvert.convert<String>(json['picUrl']);
  307 + if (picUrl != null) {
  308 + courseProcessTopicsTopicAnswerList.picUrl = picUrl;
  309 + }
  310 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  311 + if (sortOrder != null) {
  312 + courseProcessTopicsTopicAnswerList.sortOrder = sortOrder;
  313 + }
  314 + final int? topicId = jsonConvert.convert<int>(json['topicId']);
  315 + if (topicId != null) {
  316 + courseProcessTopicsTopicAnswerList.topicId = topicId;
  317 + }
  318 + final String? word = jsonConvert.convert<String>(json['word']);
  319 + if (word != null) {
  320 + courseProcessTopicsTopicAnswerList.word = word;
  321 + }
  322 + return courseProcessTopicsTopicAnswerList;
182 323 }
183 324  
184   -CourseProcessTopicsTopicAnswerList $CourseProcessTopicsTopicAnswerListFromJson(Map<String, dynamic> json) {
185   - final CourseProcessTopicsTopicAnswerList courseProcessTopicsTopicAnswerList = CourseProcessTopicsTopicAnswerList();
186   - final int? correct = jsonConvert.convert<int>(json['correct']);
187   - if (correct != null) {
188   - courseProcessTopicsTopicAnswerList.correct = correct;
189   - }
190   - final String? createTime = jsonConvert.convert<String>(json['createTime']);
191   - if (createTime != null) {
192   - courseProcessTopicsTopicAnswerList.createTime = createTime;
193   - }
194   - final String? deleted = jsonConvert.convert<String>(json['deleted']);
195   - if (deleted != null) {
196   - courseProcessTopicsTopicAnswerList.deleted = deleted;
197   - }
198   - final String? id = jsonConvert.convert<String>(json['id']);
199   - if (id != null) {
200   - courseProcessTopicsTopicAnswerList.id = id;
201   - }
202   - final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
203   - if (modifyTime != null) {
204   - courseProcessTopicsTopicAnswerList.modifyTime = modifyTime;
205   - }
206   - final String? picUrl = jsonConvert.convert<String>(json['picUrl']);
207   - if (picUrl != null) {
208   - courseProcessTopicsTopicAnswerList.picUrl = picUrl;
209   - }
210   - final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
211   - if (sortOrder != null) {
212   - courseProcessTopicsTopicAnswerList.sortOrder = sortOrder;
213   - }
214   - final int? topicId = jsonConvert.convert<int>(json['topicId']);
215   - if (topicId != null) {
216   - courseProcessTopicsTopicAnswerList.topicId = topicId;
217   - }
218   - final String? word = jsonConvert.convert<String>(json['word']);
219   - if (word != null) {
220   - courseProcessTopicsTopicAnswerList.word = word;
221   - }
222   - return courseProcessTopicsTopicAnswerList;
  325 +Map<String, dynamic> $CourseProcessTopicsTopicAnswerListToJson(
  326 + CourseProcessTopicsTopicAnswerList entity) {
  327 + final Map<String, dynamic> data = <String, dynamic>{};
  328 + data['correct'] = entity.correct;
  329 + data['createTime'] = entity.createTime;
  330 + data['deleted'] = entity.deleted;
  331 + data['id'] = entity.id;
  332 + data['modifyTime'] = entity.modifyTime;
  333 + data['picUrl'] = entity.picUrl;
  334 + data['sortOrder'] = entity.sortOrder;
  335 + data['topicId'] = entity.topicId;
  336 + data['word'] = entity.word;
  337 + return data;
223 338 }
224 339  
225   -Map<String, dynamic> $CourseProcessTopicsTopicAnswerListToJson(CourseProcessTopicsTopicAnswerList entity) {
226   - final Map<String, dynamic> data = <String, dynamic>{};
227   - data['correct'] = entity.correct;
228   - data['createTime'] = entity.createTime;
229   - data['deleted'] = entity.deleted;
230   - data['id'] = entity.id;
231   - data['modifyTime'] = entity.modifyTime;
232   - data['picUrl'] = entity.picUrl;
233   - data['sortOrder'] = entity.sortOrder;
234   - data['topicId'] = entity.topicId;
235   - data['word'] = entity.word;
236   - return data;
  340 +extension CourseProcessTopicsTopicAnswerListExtension on CourseProcessTopicsTopicAnswerList {
  341 + CourseProcessTopicsTopicAnswerList copyWith({
  342 + int? correct,
  343 + String? createTime,
  344 + String? deleted,
  345 + String? id,
  346 + String? modifyTime,
  347 + String? picUrl,
  348 + int? sortOrder,
  349 + int? topicId,
  350 + String? word,
  351 + }) {
  352 + return CourseProcessTopicsTopicAnswerList()
  353 + ..correct = correct ?? this.correct
  354 + ..createTime = createTime ?? this.createTime
  355 + ..deleted = deleted ?? this.deleted
  356 + ..id = id ?? this.id
  357 + ..modifyTime = modifyTime ?? this.modifyTime
  358 + ..picUrl = picUrl ?? this.picUrl
  359 + ..sortOrder = sortOrder ?? this.sortOrder
  360 + ..topicId = topicId ?? this.topicId
  361 + ..word = word ?? this.word;
  362 + }
237 363 }
238 364  
239 365 CourseProcessVideos $CourseProcessVideosFromJson(Map<String, dynamic> json) {
240   - final CourseProcessVideos courseProcessVideos = CourseProcessVideos();
241   - final int? courseLessonId = jsonConvert.convert<int>(json['courseLessonId']);
242   - if (courseLessonId != null) {
243   - courseProcessVideos.courseLessonId = courseLessonId;
244   - }
245   - final String? createTime = jsonConvert.convert<String>(json['createTime']);
246   - if (createTime != null) {
247   - courseProcessVideos.createTime = createTime;
248   - }
249   - final String? deleted = jsonConvert.convert<String>(json['deleted']);
250   - if (deleted != null) {
251   - courseProcessVideos.deleted = deleted;
252   - }
253   - final String? id = jsonConvert.convert<String>(json['id']);
254   - if (id != null) {
255   - courseProcessVideos.id = id;
256   - }
257   - final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
258   - if (modifyTime != null) {
259   - courseProcessVideos.modifyTime = modifyTime;
260   - }
261   - final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
262   - if (sortOrder != null) {
263   - courseProcessVideos.sortOrder = sortOrder;
264   - }
265   - final String? subtitleUrl = jsonConvert.convert<String>(json['subtitleUrl']);
266   - if (subtitleUrl != null) {
267   - courseProcessVideos.subtitleUrl = subtitleUrl;
268   - }
269   - final String? videoUrl = jsonConvert.convert<String>(json['videoUrl']);
270   - if (videoUrl != null) {
271   - courseProcessVideos.videoUrl = videoUrl;
272   - }
273   - return courseProcessVideos;
  366 + final CourseProcessVideos courseProcessVideos = CourseProcessVideos();
  367 + final int? courseLessonId = jsonConvert.convert<int>(json['courseLessonId']);
  368 + if (courseLessonId != null) {
  369 + courseProcessVideos.courseLessonId = courseLessonId;
  370 + }
  371 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  372 + if (createTime != null) {
  373 + courseProcessVideos.createTime = createTime;
  374 + }
  375 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  376 + if (deleted != null) {
  377 + courseProcessVideos.deleted = deleted;
  378 + }
  379 + final String? id = jsonConvert.convert<String>(json['id']);
  380 + if (id != null) {
  381 + courseProcessVideos.id = id;
  382 + }
  383 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  384 + if (modifyTime != null) {
  385 + courseProcessVideos.modifyTime = modifyTime;
  386 + }
  387 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  388 + if (sortOrder != null) {
  389 + courseProcessVideos.sortOrder = sortOrder;
  390 + }
  391 + final String? subtitleUrl = jsonConvert.convert<String>(json['subtitleUrl']);
  392 + if (subtitleUrl != null) {
  393 + courseProcessVideos.subtitleUrl = subtitleUrl;
  394 + }
  395 + final String? videoUrl = jsonConvert.convert<String>(json['videoUrl']);
  396 + if (videoUrl != null) {
  397 + courseProcessVideos.videoUrl = videoUrl;
  398 + }
  399 + return courseProcessVideos;
274 400 }
275 401  
276 402 Map<String, dynamic> $CourseProcessVideosToJson(CourseProcessVideos entity) {
277   - final Map<String, dynamic> data = <String, dynamic>{};
278   - data['courseLessonId'] = entity.courseLessonId;
279   - data['createTime'] = entity.createTime;
280   - data['deleted'] = entity.deleted;
281   - data['id'] = entity.id;
282   - data['modifyTime'] = entity.modifyTime;
283   - data['sortOrder'] = entity.sortOrder;
284   - data['subtitleUrl'] = entity.subtitleUrl;
285   - data['videoUrl'] = entity.videoUrl;
286   - return data;
  403 + final Map<String, dynamic> data = <String, dynamic>{};
  404 + data['courseLessonId'] = entity.courseLessonId;
  405 + data['createTime'] = entity.createTime;
  406 + data['deleted'] = entity.deleted;
  407 + data['id'] = entity.id;
  408 + data['modifyTime'] = entity.modifyTime;
  409 + data['sortOrder'] = entity.sortOrder;
  410 + data['subtitleUrl'] = entity.subtitleUrl;
  411 + data['videoUrl'] = entity.videoUrl;
  412 + return data;
  413 +}
  414 +
  415 +extension CourseProcessVideosExtension on CourseProcessVideos {
  416 + CourseProcessVideos copyWith({
  417 + int? courseLessonId,
  418 + String? createTime,
  419 + String? deleted,
  420 + String? id,
  421 + String? modifyTime,
  422 + int? sortOrder,
  423 + String? subtitleUrl,
  424 + String? videoUrl,
  425 + }) {
  426 + return CourseProcessVideos()
  427 + ..courseLessonId = courseLessonId ?? this.courseLessonId
  428 + ..createTime = createTime ?? this.createTime
  429 + ..deleted = deleted ?? this.deleted
  430 + ..id = id ?? this.id
  431 + ..modifyTime = modifyTime ?? this.modifyTime
  432 + ..sortOrder = sortOrder ?? this.sortOrder
  433 + ..subtitleUrl = subtitleUrl ?? this.subtitleUrl
  434 + ..videoUrl = videoUrl ?? this.videoUrl;
  435 + }
287 436 }
288 437 \ No newline at end of file
... ...
lib/generated/json/follow_read_entity.g.dart
... ... @@ -2,66 +2,95 @@ import &#39;package:wow_english/generated/json/base/json_convert_content.dart&#39;;
2 2 import 'package:wow_english/models/follow_read_entity.dart';
3 3  
4 4 FollowReadEntity $FollowReadEntityFromJson(Map<String, dynamic> json) {
5   - final FollowReadEntity followReadEntity = FollowReadEntity();
6   - final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
7   - if (coverUrl != null) {
8   - followReadEntity.coverUrl = coverUrl;
9   - }
10   - final String? createTime = jsonConvert.convert<String>(json['createTime']);
11   - if (createTime != null) {
12   - followReadEntity.createTime = createTime;
13   - }
14   - final String? deleted = jsonConvert.convert<String>(json['deleted']);
15   - if (deleted != null) {
16   - followReadEntity.deleted = deleted;
17   - }
18   - final String? id = jsonConvert.convert<String>(json['id']);
19   - if (id != null) {
20   - followReadEntity.id = id;
21   - }
22   - final bool? lock = jsonConvert.convert<bool>(json['lock']);
23   - if (lock != null) {
24   - followReadEntity.lock = lock;
25   - }
26   - final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
27   - if (modifyTime != null) {
28   - followReadEntity.modifyTime = modifyTime;
29   - }
30   - final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
31   - if (sortOrder != null) {
32   - followReadEntity.sortOrder = sortOrder;
33   - }
34   - final int? star = jsonConvert.convert<int>(json['star']);
35   - if (star != null) {
36   - followReadEntity.star = star;
37   - }
38   - final int? status = jsonConvert.convert<int>(json['status']);
39   - if (status != null) {
40   - followReadEntity.status = status;
41   - }
42   - final String? title = jsonConvert.convert<String>(json['title']);
43   - if (title != null) {
44   - followReadEntity.title = title;
45   - }
46   - final int? videoTotal = jsonConvert.convert<int>(json['videoTotal']);
47   - if (videoTotal != null) {
48   - followReadEntity.videoTotal = videoTotal;
49   - }
50   - return followReadEntity;
  5 + final FollowReadEntity followReadEntity = FollowReadEntity();
  6 + final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
  7 + if (coverUrl != null) {
  8 + followReadEntity.coverUrl = coverUrl;
  9 + }
  10 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  11 + if (createTime != null) {
  12 + followReadEntity.createTime = createTime;
  13 + }
  14 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  15 + if (deleted != null) {
  16 + followReadEntity.deleted = deleted;
  17 + }
  18 + final String? id = jsonConvert.convert<String>(json['id']);
  19 + if (id != null) {
  20 + followReadEntity.id = id;
  21 + }
  22 + final bool? lock = jsonConvert.convert<bool>(json['lock']);
  23 + if (lock != null) {
  24 + followReadEntity.lock = lock;
  25 + }
  26 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  27 + if (modifyTime != null) {
  28 + followReadEntity.modifyTime = modifyTime;
  29 + }
  30 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  31 + if (sortOrder != null) {
  32 + followReadEntity.sortOrder = sortOrder;
  33 + }
  34 + final int? star = jsonConvert.convert<int>(json['star']);
  35 + if (star != null) {
  36 + followReadEntity.star = star;
  37 + }
  38 + final int? status = jsonConvert.convert<int>(json['status']);
  39 + if (status != null) {
  40 + followReadEntity.status = status;
  41 + }
  42 + final String? title = jsonConvert.convert<String>(json['title']);
  43 + if (title != null) {
  44 + followReadEntity.title = title;
  45 + }
  46 + final int? videoTotal = jsonConvert.convert<int>(json['videoTotal']);
  47 + if (videoTotal != null) {
  48 + followReadEntity.videoTotal = videoTotal;
  49 + }
  50 + return followReadEntity;
51 51 }
52 52  
53 53 Map<String, dynamic> $FollowReadEntityToJson(FollowReadEntity entity) {
54   - final Map<String, dynamic> data = <String, dynamic>{};
55   - data['coverUrl'] = entity.coverUrl;
56   - data['createTime'] = entity.createTime;
57   - data['deleted'] = entity.deleted;
58   - data['id'] = entity.id;
59   - data['lock'] = entity.lock;
60   - data['modifyTime'] = entity.modifyTime;
61   - data['sortOrder'] = entity.sortOrder;
62   - data['star'] = entity.star;
63   - data['status'] = entity.status;
64   - data['title'] = entity.title;
65   - data['videoTotal'] = entity.videoTotal;
66   - return data;
  54 + final Map<String, dynamic> data = <String, dynamic>{};
  55 + data['coverUrl'] = entity.coverUrl;
  56 + data['createTime'] = entity.createTime;
  57 + data['deleted'] = entity.deleted;
  58 + data['id'] = entity.id;
  59 + data['lock'] = entity.lock;
  60 + data['modifyTime'] = entity.modifyTime;
  61 + data['sortOrder'] = entity.sortOrder;
  62 + data['star'] = entity.star;
  63 + data['status'] = entity.status;
  64 + data['title'] = entity.title;
  65 + data['videoTotal'] = entity.videoTotal;
  66 + return data;
  67 +}
  68 +
  69 +extension FollowReadEntityExtension on FollowReadEntity {
  70 + FollowReadEntity copyWith({
  71 + String? coverUrl,
  72 + String? createTime,
  73 + String? deleted,
  74 + String? id,
  75 + bool? lock,
  76 + String? modifyTime,
  77 + int? sortOrder,
  78 + int? star,
  79 + int? status,
  80 + String? title,
  81 + int? videoTotal,
  82 + }) {
  83 + return FollowReadEntity()
  84 + ..coverUrl = coverUrl ?? this.coverUrl
  85 + ..createTime = createTime ?? this.createTime
  86 + ..deleted = deleted ?? this.deleted
  87 + ..id = id ?? this.id
  88 + ..lock = lock ?? this.lock
  89 + ..modifyTime = modifyTime ?? this.modifyTime
  90 + ..sortOrder = sortOrder ?? this.sortOrder
  91 + ..star = star ?? this.star
  92 + ..status = status ?? this.status
  93 + ..title = title ?? this.title
  94 + ..videoTotal = videoTotal ?? this.videoTotal;
  95 + }
67 96 }
68 97 \ No newline at end of file
... ...
lib/generated/json/listen_entity.g.dart
... ... @@ -2,66 +2,95 @@ import &#39;package:wow_english/generated/json/base/json_convert_content.dart&#39;;
2 2 import 'package:wow_english/models/listen_entity.dart';
3 3  
4 4 ListenEntity $ListenEntityFromJson(Map<String, dynamic> json) {
5   - final ListenEntity listenEntity = ListenEntity();
6   - final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
7   - if (coverUrl != null) {
8   - listenEntity.coverUrl = coverUrl;
9   - }
10   - final String? createTime = jsonConvert.convert<String>(json['createTime']);
11   - if (createTime != null) {
12   - listenEntity.createTime = createTime;
13   - }
14   - final String? deleted = jsonConvert.convert<String>(json['deleted']);
15   - if (deleted != null) {
16   - listenEntity.deleted = deleted;
17   - }
18   - final String? id = jsonConvert.convert<String>(json['id']);
19   - if (id != null) {
20   - listenEntity.id = id;
21   - }
22   - final bool? lock = jsonConvert.convert<bool>(json['lock']);
23   - if (lock != null) {
24   - listenEntity.lock = lock;
25   - }
26   - final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
27   - if (modifyTime != null) {
28   - listenEntity.modifyTime = modifyTime;
29   - }
30   - final double? sortOrder = jsonConvert.convert<double>(json['sortOrder']);
31   - if (sortOrder != null) {
32   - listenEntity.sortOrder = sortOrder;
33   - }
34   - final double? status = jsonConvert.convert<double>(json['status']);
35   - if (status != null) {
36   - listenEntity.status = status;
37   - }
38   - final String? subtitleUrl = jsonConvert.convert<String>(json['subtitleUrl']);
39   - if (subtitleUrl != null) {
40   - listenEntity.subtitleUrl = subtitleUrl;
41   - }
42   - final String? title = jsonConvert.convert<String>(json['title']);
43   - if (title != null) {
44   - listenEntity.title = title;
45   - }
46   - final String? videoUrl = jsonConvert.convert<String>(json['videoUrl']);
47   - if (videoUrl != null) {
48   - listenEntity.videoUrl = videoUrl;
49   - }
50   - return listenEntity;
  5 + final ListenEntity listenEntity = ListenEntity();
  6 + final String? coverUrl = jsonConvert.convert<String>(json['coverUrl']);
  7 + if (coverUrl != null) {
  8 + listenEntity.coverUrl = coverUrl;
  9 + }
  10 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  11 + if (createTime != null) {
  12 + listenEntity.createTime = createTime;
  13 + }
  14 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  15 + if (deleted != null) {
  16 + listenEntity.deleted = deleted;
  17 + }
  18 + final String? id = jsonConvert.convert<String>(json['id']);
  19 + if (id != null) {
  20 + listenEntity.id = id;
  21 + }
  22 + final bool? lock = jsonConvert.convert<bool>(json['lock']);
  23 + if (lock != null) {
  24 + listenEntity.lock = lock;
  25 + }
  26 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  27 + if (modifyTime != null) {
  28 + listenEntity.modifyTime = modifyTime;
  29 + }
  30 + final double? sortOrder = jsonConvert.convert<double>(json['sortOrder']);
  31 + if (sortOrder != null) {
  32 + listenEntity.sortOrder = sortOrder;
  33 + }
  34 + final double? status = jsonConvert.convert<double>(json['status']);
  35 + if (status != null) {
  36 + listenEntity.status = status;
  37 + }
  38 + final String? subtitleUrl = jsonConvert.convert<String>(json['subtitleUrl']);
  39 + if (subtitleUrl != null) {
  40 + listenEntity.subtitleUrl = subtitleUrl;
  41 + }
  42 + final String? title = jsonConvert.convert<String>(json['title']);
  43 + if (title != null) {
  44 + listenEntity.title = title;
  45 + }
  46 + final String? videoUrl = jsonConvert.convert<String>(json['videoUrl']);
  47 + if (videoUrl != null) {
  48 + listenEntity.videoUrl = videoUrl;
  49 + }
  50 + return listenEntity;
51 51 }
52 52  
53 53 Map<String, dynamic> $ListenEntityToJson(ListenEntity entity) {
54   - final Map<String, dynamic> data = <String, dynamic>{};
55   - data['coverUrl'] = entity.coverUrl;
56   - data['createTime'] = entity.createTime;
57   - data['deleted'] = entity.deleted;
58   - data['id'] = entity.id;
59   - data['lock'] = entity.lock;
60   - data['modifyTime'] = entity.modifyTime;
61   - data['sortOrder'] = entity.sortOrder;
62   - data['status'] = entity.status;
63   - data['subtitleUrl'] = entity.subtitleUrl;
64   - data['title'] = entity.title;
65   - data['videoUrl'] = entity.videoUrl;
66   - return data;
  54 + final Map<String, dynamic> data = <String, dynamic>{};
  55 + data['coverUrl'] = entity.coverUrl;
  56 + data['createTime'] = entity.createTime;
  57 + data['deleted'] = entity.deleted;
  58 + data['id'] = entity.id;
  59 + data['lock'] = entity.lock;
  60 + data['modifyTime'] = entity.modifyTime;
  61 + data['sortOrder'] = entity.sortOrder;
  62 + data['status'] = entity.status;
  63 + data['subtitleUrl'] = entity.subtitleUrl;
  64 + data['title'] = entity.title;
  65 + data['videoUrl'] = entity.videoUrl;
  66 + return data;
  67 +}
  68 +
  69 +extension ListenEntityExtension on ListenEntity {
  70 + ListenEntity copyWith({
  71 + String? coverUrl,
  72 + String? createTime,
  73 + String? deleted,
  74 + String? id,
  75 + bool? lock,
  76 + String? modifyTime,
  77 + double? sortOrder,
  78 + double? status,
  79 + String? subtitleUrl,
  80 + String? title,
  81 + String? videoUrl,
  82 + }) {
  83 + return ListenEntity()
  84 + ..coverUrl = coverUrl ?? this.coverUrl
  85 + ..createTime = createTime ?? this.createTime
  86 + ..deleted = deleted ?? this.deleted
  87 + ..id = id ?? this.id
  88 + ..lock = lock ?? this.lock
  89 + ..modifyTime = modifyTime ?? this.modifyTime
  90 + ..sortOrder = sortOrder ?? this.sortOrder
  91 + ..status = status ?? this.status
  92 + ..subtitleUrl = subtitleUrl ?? this.subtitleUrl
  93 + ..title = title ?? this.title
  94 + ..videoUrl = videoUrl ?? this.videoUrl;
  95 + }
67 96 }
68 97 \ No newline at end of file
... ...
lib/generated/json/product_entity.g.dart 0 → 100644
  1 +import 'package:wow_english/generated/json/base/json_convert_content.dart';
  2 +import 'package:wow_english/models/product_entity.dart';
  3 +
  4 +ProductEntity $ProductEntityFromJson(Map<String, dynamic> json) {
  5 + final ProductEntity productEntity = ProductEntity();
  6 + final int? id = jsonConvert.convert<int>(json['id']);
  7 + if (id != null) {
  8 + productEntity.id = id;
  9 + }
  10 + final String? name = jsonConvert.convert<String>(json['name']);
  11 + if (name != null) {
  12 + productEntity.name = name;
  13 + }
  14 + final String? title = jsonConvert.convert<String>(json['title']);
  15 + if (title != null) {
  16 + productEntity.title = title;
  17 + }
  18 + final double? price = jsonConvert.convert<double>(json['price']);
  19 + if (price != null) {
  20 + productEntity.price = price;
  21 + }
  22 + final String? picUrl = jsonConvert.convert<String>(json['picUrl']);
  23 + if (picUrl != null) {
  24 + productEntity.picUrl = picUrl;
  25 + }
  26 + final String? bannerPicUrl = jsonConvert.convert<String>(
  27 + json['bannerPicUrl']);
  28 + if (bannerPicUrl != null) {
  29 + productEntity.bannerPicUrl = bannerPicUrl;
  30 + }
  31 + final String? detailPicUrl = jsonConvert.convert<String>(
  32 + json['detailPicUrl']);
  33 + if (detailPicUrl != null) {
  34 + productEntity.detailPicUrl = detailPicUrl;
  35 + }
  36 + final int? saleType = jsonConvert.convert<int>(json['saleType']);
  37 + if (saleType != null) {
  38 + productEntity.saleType = saleType;
  39 + }
  40 + final int? status = jsonConvert.convert<int>(json['status']);
  41 + if (status != null) {
  42 + productEntity.status = status;
  43 + }
  44 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  45 + if (sortOrder != null) {
  46 + productEntity.sortOrder = sortOrder;
  47 + }
  48 + final int? validityType = jsonConvert.convert<int>(json['validityType']);
  49 + if (validityType != null) {
  50 + productEntity.validityType = validityType;
  51 + }
  52 + return productEntity;
  53 +}
  54 +
  55 +Map<String, dynamic> $ProductEntityToJson(ProductEntity entity) {
  56 + final Map<String, dynamic> data = <String, dynamic>{};
  57 + data['id'] = entity.id;
  58 + data['name'] = entity.name;
  59 + data['title'] = entity.title;
  60 + data['price'] = entity.price;
  61 + data['picUrl'] = entity.picUrl;
  62 + data['bannerPicUrl'] = entity.bannerPicUrl;
  63 + data['detailPicUrl'] = entity.detailPicUrl;
  64 + data['saleType'] = entity.saleType;
  65 + data['status'] = entity.status;
  66 + data['sortOrder'] = entity.sortOrder;
  67 + data['validityType'] = entity.validityType;
  68 + return data;
  69 +}
  70 +
  71 +extension ProductEntityExtension on ProductEntity {
  72 + ProductEntity copyWith({
  73 + int? id,
  74 + String? name,
  75 + String? title,
  76 + double? price,
  77 + String? picUrl,
  78 + String? bannerPicUrl,
  79 + String? detailPicUrl,
  80 + int? saleType,
  81 + int? status,
  82 + int? sortOrder,
  83 + int? validityType,
  84 + }) {
  85 + return ProductEntity()
  86 + ..id = id ?? this.id
  87 + ..name = name ?? this.name
  88 + ..title = title ?? this.title
  89 + ..price = price ?? this.price
  90 + ..picUrl = picUrl ?? this.picUrl
  91 + ..bannerPicUrl = bannerPicUrl ?? this.bannerPicUrl
  92 + ..detailPicUrl = detailPicUrl ?? this.detailPicUrl
  93 + ..saleType = saleType ?? this.saleType
  94 + ..status = status ?? this.status
  95 + ..sortOrder = sortOrder ?? this.sortOrder
  96 + ..validityType = validityType ?? this.validityType;
  97 + }
  98 +}
0 99 \ No newline at end of file
... ...
lib/generated/json/read_content_entity.g.dart
... ... @@ -2,56 +2,82 @@ import &#39;package:wow_english/generated/json/base/json_convert_content.dart&#39;;
2 2 import 'package:wow_english/models/read_content_entity.dart';
3 3  
4 4 ReadContentEntity $ReadContentEntityFromJson(Map<String, dynamic> json) {
5   - final ReadContentEntity readContentEntity = ReadContentEntity();
6   - final String? createTime = jsonConvert.convert<String>(json['createTime']);
7   - if (createTime != null) {
8   - readContentEntity.createTime = createTime;
9   - }
10   - final String? deleted = jsonConvert.convert<String>(json['deleted']);
11   - if (deleted != null) {
12   - readContentEntity.deleted = deleted;
13   - }
14   - final String? id = jsonConvert.convert<String>(json['id']);
15   - if (id != null) {
16   - readContentEntity.id = id;
17   - }
18   - final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
19   - if (modifyTime != null) {
20   - readContentEntity.modifyTime = modifyTime;
21   - }
22   - final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
23   - if (sortOrder != null) {
24   - readContentEntity.sortOrder = sortOrder;
25   - }
26   - final int? status = jsonConvert.convert<int>(json['status']);
27   - if (status != null) {
28   - readContentEntity.status = status;
29   - }
30   - final int? videoFollowReadId = jsonConvert.convert<int>(json['videoFollowReadId']);
31   - if (videoFollowReadId != null) {
32   - readContentEntity.videoFollowReadId = videoFollowReadId;
33   - }
34   - final String? videoUrl = jsonConvert.convert<String>(json['videoUrl']);
35   - if (videoUrl != null) {
36   - readContentEntity.videoUrl = videoUrl;
37   - }
38   - final String? word = jsonConvert.convert<String>(json['word']);
39   - if (word != null) {
40   - readContentEntity.word = word;
41   - }
42   - return readContentEntity;
  5 + final ReadContentEntity readContentEntity = ReadContentEntity();
  6 + final String? createTime = jsonConvert.convert<String>(json['createTime']);
  7 + if (createTime != null) {
  8 + readContentEntity.createTime = createTime;
  9 + }
  10 + final String? deleted = jsonConvert.convert<String>(json['deleted']);
  11 + if (deleted != null) {
  12 + readContentEntity.deleted = deleted;
  13 + }
  14 + final String? id = jsonConvert.convert<String>(json['id']);
  15 + if (id != null) {
  16 + readContentEntity.id = id;
  17 + }
  18 + final String? modifyTime = jsonConvert.convert<String>(json['modifyTime']);
  19 + if (modifyTime != null) {
  20 + readContentEntity.modifyTime = modifyTime;
  21 + }
  22 + final int? sortOrder = jsonConvert.convert<int>(json['sortOrder']);
  23 + if (sortOrder != null) {
  24 + readContentEntity.sortOrder = sortOrder;
  25 + }
  26 + final int? status = jsonConvert.convert<int>(json['status']);
  27 + if (status != null) {
  28 + readContentEntity.status = status;
  29 + }
  30 + final int? videoFollowReadId = jsonConvert.convert<int>(
  31 + json['videoFollowReadId']);
  32 + if (videoFollowReadId != null) {
  33 + readContentEntity.videoFollowReadId = videoFollowReadId;
  34 + }
  35 + final String? videoUrl = jsonConvert.convert<String>(json['videoUrl']);
  36 + if (videoUrl != null) {
  37 + readContentEntity.videoUrl = videoUrl;
  38 + }
  39 + final String? word = jsonConvert.convert<String>(json['word']);
  40 + if (word != null) {
  41 + readContentEntity.word = word;
  42 + }
  43 + return readContentEntity;
43 44 }
44 45  
45 46 Map<String, dynamic> $ReadContentEntityToJson(ReadContentEntity entity) {
46   - final Map<String, dynamic> data = <String, dynamic>{};
47   - data['createTime'] = entity.createTime;
48   - data['deleted'] = entity.deleted;
49   - data['id'] = entity.id;
50   - data['modifyTime'] = entity.modifyTime;
51   - data['sortOrder'] = entity.sortOrder;
52   - data['status'] = entity.status;
53   - data['videoFollowReadId'] = entity.videoFollowReadId;
54   - data['videoUrl'] = entity.videoUrl;
55   - data['word'] = entity.word;
56   - return data;
  47 + final Map<String, dynamic> data = <String, dynamic>{};
  48 + data['createTime'] = entity.createTime;
  49 + data['deleted'] = entity.deleted;
  50 + data['id'] = entity.id;
  51 + data['modifyTime'] = entity.modifyTime;
  52 + data['sortOrder'] = entity.sortOrder;
  53 + data['status'] = entity.status;
  54 + data['videoFollowReadId'] = entity.videoFollowReadId;
  55 + data['videoUrl'] = entity.videoUrl;
  56 + data['word'] = entity.word;
  57 + return data;
  58 +}
  59 +
  60 +extension ReadContentEntityExtension on ReadContentEntity {
  61 + ReadContentEntity copyWith({
  62 + String? createTime,
  63 + String? deleted,
  64 + String? id,
  65 + String? modifyTime,
  66 + int? sortOrder,
  67 + int? status,
  68 + int? videoFollowReadId,
  69 + String? videoUrl,
  70 + String? word,
  71 + }) {
  72 + return ReadContentEntity()
  73 + ..createTime = createTime ?? this.createTime
  74 + ..deleted = deleted ?? this.deleted
  75 + ..id = id ?? this.id
  76 + ..modifyTime = modifyTime ?? this.modifyTime
  77 + ..sortOrder = sortOrder ?? this.sortOrder
  78 + ..status = status ?? this.status
  79 + ..videoFollowReadId = videoFollowReadId ?? this.videoFollowReadId
  80 + ..videoUrl = videoUrl ?? this.videoUrl
  81 + ..word = word ?? this.word;
  82 + }
57 83 }
58 84 \ No newline at end of file
... ...
lib/generated/json/user_entity.g.dart
... ... @@ -2,61 +2,90 @@ import &#39;package:wow_english/generated/json/base/json_convert_content.dart&#39;;
2 2 import 'package:wow_english/models/user_entity.dart';
3 3  
4 4 UserEntity $UserEntityFromJson(Map<String, dynamic> json) {
5   - final UserEntity userEntity = UserEntity();
6   - final int? id = jsonConvert.convert<int>(json['id']);
7   - if (id != null) {
8   - userEntity.id = id;
9   - }
10   - final String? name = jsonConvert.convert<String>(json['name']);
11   - if (name != null) {
12   - userEntity.name = name;
13   - }
14   - final String? token = jsonConvert.convert<String>(json['token']);
15   - if (token != null) {
16   - userEntity.token = token;
17   - }
18   - final int? age = jsonConvert.convert<int>(json['age']);
19   - if (age != null) {
20   - userEntity.age = age;
21   - }
22   - final int? gender = jsonConvert.convert<int>(json['gender']);
23   - if (gender != null) {
24   - userEntity.gender = gender;
25   - }
26   - final String? avatarUrl = jsonConvert.convert<String>(json['avatarUrl']);
27   - if (avatarUrl != null) {
28   - userEntity.avatarUrl = avatarUrl;
29   - }
30   - final String? phoneNum = jsonConvert.convert<String>(json['phoneNum']);
31   - if (phoneNum != null) {
32   - userEntity.phoneNum = phoneNum;
33   - }
34   - final int? fillUserInfo = jsonConvert.convert<int>(json['fillUserInfo']);
35   - if (fillUserInfo != null) {
36   - userEntity.fillUserInfo = fillUserInfo;
37   - }
38   - final int? nowCourseModuleId = jsonConvert.convert<int>(json['nowCourseModuleId']);
39   - if (nowCourseModuleId != null) {
40   - userEntity.nowCourseModuleId = nowCourseModuleId;
41   - }
42   - final String? effectiveDate = jsonConvert.convert<String>(json['effectiveDate']);
43   - if (effectiveDate != null) {
44   - userEntity.effectiveDate = effectiveDate;
45   - }
46   - return userEntity;
  5 + final UserEntity userEntity = UserEntity();
  6 + final int? id = jsonConvert.convert<int>(json['id']);
  7 + if (id != null) {
  8 + userEntity.id = id;
  9 + }
  10 + final String? name = jsonConvert.convert<String>(json['name']);
  11 + if (name != null) {
  12 + userEntity.name = name;
  13 + }
  14 + final String? token = jsonConvert.convert<String>(json['token']);
  15 + if (token != null) {
  16 + userEntity.token = token;
  17 + }
  18 + final int? age = jsonConvert.convert<int>(json['age']);
  19 + if (age != null) {
  20 + userEntity.age = age;
  21 + }
  22 + final int? gender = jsonConvert.convert<int>(json['gender']);
  23 + if (gender != null) {
  24 + userEntity.gender = gender;
  25 + }
  26 + final String? avatarUrl = jsonConvert.convert<String>(json['avatarUrl']);
  27 + if (avatarUrl != null) {
  28 + userEntity.avatarUrl = avatarUrl;
  29 + }
  30 + final String? phoneNum = jsonConvert.convert<String>(json['phoneNum']);
  31 + if (phoneNum != null) {
  32 + userEntity.phoneNum = phoneNum;
  33 + }
  34 + final int? fillUserInfo = jsonConvert.convert<int>(json['fillUserInfo']);
  35 + if (fillUserInfo != null) {
  36 + userEntity.fillUserInfo = fillUserInfo;
  37 + }
  38 + final int? nowCourseModuleId = jsonConvert.convert<int>(
  39 + json['nowCourseModuleId']);
  40 + if (nowCourseModuleId != null) {
  41 + userEntity.nowCourseModuleId = nowCourseModuleId;
  42 + }
  43 + final String? effectiveDate = jsonConvert.convert<String>(
  44 + json['effectiveDate']);
  45 + if (effectiveDate != null) {
  46 + userEntity.effectiveDate = effectiveDate;
  47 + }
  48 + return userEntity;
47 49 }
48 50  
49 51 Map<String, dynamic> $UserEntityToJson(UserEntity entity) {
50   - final Map<String, dynamic> data = <String, dynamic>{};
51   - data['id'] = entity.id;
52   - data['name'] = entity.name;
53   - data['token'] = entity.token;
54   - data['age'] = entity.age;
55   - data['gender'] = entity.gender;
56   - data['avatarUrl'] = entity.avatarUrl;
57   - data['phoneNum'] = entity.phoneNum;
58   - data['fillUserInfo'] = entity.fillUserInfo;
59   - data['nowCourseModuleId'] = entity.nowCourseModuleId;
60   - data['effectiveDate'] = entity.effectiveDate;
61   - return data;
  52 + final Map<String, dynamic> data = <String, dynamic>{};
  53 + data['id'] = entity.id;
  54 + data['name'] = entity.name;
  55 + data['token'] = entity.token;
  56 + data['age'] = entity.age;
  57 + data['gender'] = entity.gender;
  58 + data['avatarUrl'] = entity.avatarUrl;
  59 + data['phoneNum'] = entity.phoneNum;
  60 + data['fillUserInfo'] = entity.fillUserInfo;
  61 + data['nowCourseModuleId'] = entity.nowCourseModuleId;
  62 + data['effectiveDate'] = entity.effectiveDate;
  63 + return data;
  64 +}
  65 +
  66 +extension UserEntityExtension on UserEntity {
  67 + UserEntity copyWith({
  68 + int? id,
  69 + String? name,
  70 + String? token,
  71 + int? age,
  72 + int? gender,
  73 + String? avatarUrl,
  74 + String? phoneNum,
  75 + int? fillUserInfo,
  76 + int? nowCourseModuleId,
  77 + String? effectiveDate,
  78 + }) {
  79 + return UserEntity()
  80 + ..id = id ?? this.id
  81 + ..name = name ?? this.name
  82 + ..token = token ?? this.token
  83 + ..age = age ?? this.age
  84 + ..gender = gender ?? this.gender
  85 + ..avatarUrl = avatarUrl ?? this.avatarUrl
  86 + ..phoneNum = phoneNum ?? this.phoneNum
  87 + ..fillUserInfo = fillUserInfo ?? this.fillUserInfo
  88 + ..nowCourseModuleId = nowCourseModuleId ?? this.nowCourseModuleId
  89 + ..effectiveDate = effectiveDate ?? this.effectiveDate;
  90 + }
62 91 }
63 92 \ No newline at end of file
... ...
lib/models/product_entity.dart 0 → 100644
  1 +import 'package:wow_english/generated/json/base/json_field.dart';
  2 +import 'package:wow_english/generated/json/product_entity.g.dart';
  3 +import 'dart:convert';
  4 +export 'package:wow_english/generated/json/product_entity.g.dart';
  5 +
  6 +@JsonSerializable()
  7 +class ProductEntity {
  8 +
  9 + int? id;
  10 +
  11 + String? name;
  12 +
  13 + String? title;
  14 +
  15 + /// 售卖价格
  16 + double? price;
  17 + /// 商品图片
  18 + String? picUrl;
  19 + /// 商品banner图片
  20 + String? bannerPicUrl;
  21 + /// 商品详情图片
  22 + String? detailPicUrl;
  23 + /// 销售类型
  24 + int? saleType;
  25 + /// 状态
  26 + int? status;
  27 + /// 序号
  28 + int? sortOrder;
  29 + /// 有效期类型
  30 + int? validityType;
  31 +
  32 +
  33 + ProductEntity();
  34 +
  35 + factory ProductEntity.fromJson(Map<String, dynamic> json) => $ProductEntityFromJson(json);
  36 +
  37 + Map<String, dynamic> toJson() => $ProductEntityToJson(this);
  38 +
  39 + @override
  40 + String toString() {
  41 + return jsonEncode(this);
  42 + }
  43 +}
0 44 \ No newline at end of file
... ...
lib/pages/games/bloc.dart 0 → 100644
  1 +import 'package:bloc/bloc.dart';
  2 +import 'package:flutter/cupertino.dart';
  3 +import 'package:flutter/services.dart';
  4 +import 'package:wow_english/common/extension/string_extension.dart';
  5 +
  6 +import 'event.dart';
  7 +import 'game_entity.dart';
  8 +import 'state.dart';
  9 +
  10 +class GamesBloc extends Bloc<GamesEvent, GamesState> {
  11 +
  12 + late MethodChannel _methodChannel;
  13 +
  14 + //手动初始化4个GameEntity对象
  15 + final List<GameEntity> _games = [
  16 + GameEntity()
  17 + ..id = 1
  18 + ..imageName = 'pic_module_game'.assetPng
  19 + ..name = '游戏1',
  20 + GameEntity()
  21 + ..id = 2
  22 + ..imageName = 'pic_module_game'.assetPng
  23 + ..name = '游戏2',
  24 + GameEntity()
  25 + ..id = 3
  26 + ..imageName = 'pic_module_game'.assetPng
  27 + ..name = '游戏3',
  28 + GameEntity()
  29 + ..id = 4
  30 + ..imageName = 'pic_module_game'.assetPng
  31 + ..name = '游戏4'
  32 + ];
  33 +
  34 + List<GameEntity> get listData => _games;
  35 +
  36 + GamesBloc() : super(GamesState().init()) {
  37 + on<InitEvent>(_init);
  38 + on<GotoGamePageEvent>(_gotoGamePage);
  39 + }
  40 +
  41 + void _init(InitEvent event, Emitter<GamesState> emit) async {
  42 + emit(state.clone());
  43 + }
  44 +
  45 + void _gotoGamePage(GotoGamePageEvent event, Emitter<GamesState> emit) async {
  46 + try {
  47 + _methodChannel = const MethodChannel('wow_english/game_method_channel');
  48 + await _methodChannel.invokeMethod('openGamePage', { "gameId": event.gameId });
  49 + } on PlatformException catch (e) {
  50 + debugPrint("Failed to go to native page: '${e.message}'.");
  51 + }
  52 + }
  53 +}
... ...
lib/pages/games/event.dart 0 → 100644
  1 +abstract class GamesEvent {}
  2 +
  3 +class InitEvent extends GamesEvent {}
  4 +
  5 +///进入游戏页面
  6 +class GotoGamePageEvent extends GamesEvent {
  7 + late final int gameId;
  8 +
  9 + GotoGamePageEvent(this.gameId);
  10 +}
0 11 \ No newline at end of file
... ...
lib/pages/games/game_entity.dart 0 → 100644
  1 +
  2 +
  3 +
  4 +class GameEntity {
  5 +
  6 + late int id;
  7 +
  8 + late String imageName;
  9 +
  10 + late String name;
  11 +}
0 12 \ No newline at end of file
... ...
lib/pages/games/state.dart 0 → 100644
  1 +class GamesState {
  2 + GamesState init() {
  3 + return GamesState();
  4 + }
  5 +
  6 + GamesState clone() {
  7 + return GamesState();
  8 + }
  9 +}
... ...
lib/pages/games/view.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
  3 +
  4 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  5 +import 'package:wow_english/common/widgets/we_app_bar.dart';
  6 +import 'package:wow_english/pages/games/state.dart';
  7 +
  8 +import '../games/event.dart';
  9 +import 'bloc.dart';
  10 +
  11 +
  12 +class GamesPage extends StatelessWidget {
  13 + const GamesPage({super.key});
  14 +
  15 + @override
  16 + Widget build(BuildContext context) {
  17 + return BlocProvider(
  18 + create: (BuildContext context) => GamesBloc()..add(InitEvent()),
  19 + child: Builder(builder: (context) => _GamesPageView()),
  20 + );
  21 + }
  22 +}
  23 +
  24 +class _GamesPageView extends StatelessWidget {
  25 + @override
  26 + Widget build(BuildContext context) {
  27 + return BlocListener<GamesBloc, GamesState>(
  28 + listener: (context, state) {},
  29 + child: Scaffold(
  30 + appBar: const WEAppBar(
  31 + titleText: '游戏专区',
  32 + centerTitle: false,
  33 + ),
  34 + body: _gamesView(),
  35 + ),
  36 + );
  37 + }
  38 +
  39 + Widget _gamesView() =>
  40 + BlocBuilder<GamesBloc, GamesState>(builder: (context, state) {
  41 + final bloc = BlocProvider.of<GamesBloc>(context);
  42 + //屏幕中间横着放四张图片一行展示(尺寸120*200),每张图片下方有行文字
  43 + return Container(
  44 + margin: EdgeInsets.symmetric(horizontal: 50.0.w),
  45 + child: GridView.builder(
  46 + padding: EdgeInsets.zero,
  47 + // physics: const NeverScrollableScrollPhysics(),
  48 + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
  49 + crossAxisCount: 3,
  50 + crossAxisSpacing: 10,
  51 + mainAxisSpacing: 10,
  52 + childAspectRatio: 0.6,
  53 + ),
  54 + itemCount: bloc.listData.length,
  55 + itemBuilder: (BuildContext context, int index) {
  56 + final gameEntity = bloc.listData[index];
  57 + return GestureDetector(
  58 + onTap: () {
  59 + bloc.add(GotoGamePageEvent(gameEntity.id));
  60 + },
  61 + child: Column(
  62 + children: [
  63 + Image.asset(gameEntity.imageName,
  64 + width: 120, height: 200),
  65 + Text(gameEntity.name,
  66 + style: TextStyle(
  67 + fontSize: 14.sp,
  68 + color: const Color(0xFF140C10)))
  69 + ],
  70 + ),
  71 + );
  72 + }));
  73 + });
  74 +}
... ...
lib/pages/home/widgets/home_tab_header_widget.dart
... ... @@ -104,14 +104,14 @@ class HomeTabHeaderWidget extends StatelessWidget {
104 104 }
105 105 },
106 106 icon: Image.asset('listen'.assetPng)),
107   - // IconButton(
108   - // onPressed: (){
109   - // if(actionTap != null) {
110   - // actionTap!(HeaderActionType.shop);
111   - // }
112   - // },
113   - // icon: Image.asset('shop'.assetPng)
114   - // ),
  107 + IconButton(
  108 + onPressed: (){
  109 + if(actionTap != null) {
  110 + actionTap!(HeaderActionType.shop);
  111 + }
  112 + },
  113 + icon: Image.asset('shop'.assetPng)
  114 + ),
115 115 ScreenUtil().bottomBarHeight.horizontalSpace,
116 116 ],
117 117 )
... ...
lib/pages/moduleSelect/bloc.dart 0 → 100644
  1 +import 'package:bloc/bloc.dart';
  2 +
  3 +import 'event.dart';
  4 +import 'state.dart';
  5 +
  6 +
  7 +class ModuleSelectBloc extends Bloc<ModuleSelectEvent, ModuleSelectState> {
  8 +
  9 + ModuleSelectBloc() : super(ModuleSelectState().init()) {
  10 + on<InitEvent>(_init);
  11 + }
  12 +
  13 + void _init(InitEvent event, Emitter<ModuleSelectState> emit) async {
  14 + emit(state.clone());
  15 + }
  16 +}
... ...
lib/pages/moduleSelect/event.dart 0 → 100644
  1 +abstract class ModuleSelectEvent {}
  2 +
  3 +class InitEvent extends ModuleSelectEvent {}
0 4 \ No newline at end of file
... ...
lib/pages/moduleSelect/state.dart 0 → 100644
  1 +class ModuleSelectState {
  2 + ModuleSelectState init() {
  3 + return ModuleSelectState();
  4 + }
  5 +
  6 + ModuleSelectState clone() {
  7 + return ModuleSelectState();
  8 + }
  9 +}
... ...
lib/pages/moduleSelect/view.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
  3 +import 'package:wow_english/common/extension/string_extension.dart';
  4 +import 'package:wow_english/pages/moduleSelect/state.dart';
  5 +import 'package:wow_english/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart';
  6 +
  7 +import 'bloc.dart';
  8 +import 'event.dart';
  9 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  10 +import 'package:wow_english/route/route.dart';
  11 +
  12 +class ModuleSelectPage extends StatelessWidget {
  13 + const ModuleSelectPage({super.key});
  14 +
  15 + @override
  16 + Widget build(BuildContext context) {
  17 + return BlocProvider(
  18 + create: (BuildContext context) => ModuleSelectBloc()..add(InitEvent()),
  19 + child: Builder(builder: (context) => _HomePageView()),
  20 + );
  21 + }
  22 +}
  23 +
  24 +class _HomePageView extends StatelessWidget {
  25 + @override
  26 + Widget build(BuildContext context) {
  27 + final bloc = BlocProvider.of<ModuleSelectBloc>(context);
  28 + return BlocListener<ModuleSelectBloc, ModuleSelectState>(
  29 + listener: (context, state) {},
  30 + child: _homeView(),
  31 + );
  32 + }
  33 +
  34 + Widget _homeView() => BlocBuilder<ModuleSelectBloc, ModuleSelectState>(
  35 + builder: (context, state) {
  36 + final bloc = BlocProvider.of<ModuleSelectBloc>(context);
  37 + return Scaffold(
  38 + body: Container(
  39 + color: Colors.white,
  40 + child: Column(
  41 + children: [
  42 + const BaseHomeHeaderWidget(),
  43 + Expanded(
  44 + child: Center(
  45 + child: Row(
  46 + children: [
  47 + Expanded(
  48 + child: GestureDetector(
  49 + onTap: () {
  50 + pushNamed(AppRouteName.home);
  51 + },
  52 + child: Column(
  53 + mainAxisAlignment: MainAxisAlignment.center,
  54 + children: [
  55 + Stack(
  56 + alignment: AlignmentDirectional.center,
  57 + children: [
  58 + Image.asset('bg_frame_module'.assetPng,
  59 + width: 162.5.w, height: 203.5.h),
  60 + Center(
  61 + child: Image.asset(
  62 + 'pic_module_study'.assetPng,
  63 + width: 140.5.w,
  64 + height: 172.h),
  65 + )
  66 + ]),
  67 + 10.verticalSpace,
  68 + Image.asset('label_module_study'.assetPng,
  69 + width: 124.w, height: 34.h),
  70 + ],
  71 + ),
  72 + ),
  73 + ),
  74 + Expanded(
  75 + child: GestureDetector(
  76 + onTap: () {
  77 + pushNamed(AppRouteName.games);
  78 + },
  79 + child: Column(
  80 + mainAxisAlignment: MainAxisAlignment.center,
  81 + children: [
  82 + Stack(
  83 + alignment: AlignmentDirectional.center,
  84 + children: [
  85 + Image.asset('bg_frame_module'.assetPng,
  86 + width: 162.5.w, height: 203.5.h),
  87 + Image.asset('pic_module_game'.assetPng,
  88 + width: 140.5.w, height: 172.h)
  89 + ]),
  90 + 10.verticalSpace,
  91 + Image.asset('label_module_game'.assetPng,
  92 + width: 124.w, height: 34.h),
  93 + ],
  94 + )),
  95 + ),
  96 + ],
  97 + ),
  98 + ),
  99 + )
  100 + ],
  101 + ),
  102 + ),
  103 + );
  104 + });
  105 +}
... ...
lib/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
  3 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  4 +import 'package:wow_english/common/extension/string_extension.dart';
  5 +
  6 +import '../../../common/core/user_util.dart';
  7 +import '../../../models/course_entity.dart';
  8 +import '../../../route/route.dart';
  9 +import '../../../utils/image_util.dart';
  10 +import '../../user/bloc/user_bloc.dart';
  11 +
  12 +class BaseHomeHeaderWidget extends StatelessWidget {
  13 + const BaseHomeHeaderWidget({super.key, this.entity});
  14 +
  15 + final CourseEntity? entity;
  16 +
  17 + @override
  18 + Widget build(BuildContext context) {
  19 + return BlocBuilder<UserBloc, UserState>(
  20 + builder: (context, state) {
  21 + return Container(
  22 + height: 45,
  23 + width: double.infinity,
  24 + decoration: BoxDecoration(
  25 + image: DecorationImage(
  26 + image: AssetImage('bg_header_sliver'.assetPng),
  27 + fit: BoxFit.cover,
  28 + ),
  29 + ),
  30 + padding: EdgeInsets.symmetric(horizontal: 9.5.w),
  31 + child: Row(
  32 + children: [
  33 + ScreenUtil().bottomBarHeight.horizontalSpace,
  34 + GestureDetector(
  35 + onTap: () => {onUserClick()},
  36 + child: Container(
  37 + decoration: BoxDecoration(
  38 + border: Border.all(
  39 + width: 1.0,
  40 + color: const Color(0xFF140C10),
  41 + ),
  42 + borderRadius: BorderRadius.circular(21),
  43 + ),
  44 + child: CircleAvatar(
  45 + radius: 21,
  46 + backgroundImage: ImageUtil.getImageProviderOnDefault(
  47 + UserUtil.getUser()?.avatarUrl),
  48 + ),
  49 + ),
  50 + ),
  51 + GestureDetector(
  52 + onTap: () {
  53 + onUserClick();
  54 + },
  55 + child: Container(
  56 + margin: const EdgeInsets.only(left: 7),
  57 + padding: const EdgeInsets.all(4.0),
  58 + decoration: BoxDecoration(
  59 + color: Colors.white,
  60 + borderRadius: BorderRadius.circular(2),
  61 + border: Border.all(
  62 + width: 1.0,
  63 + color: const Color(0xFF140C10),
  64 + style: BorderStyle.solid),
  65 + ),
  66 + child: Text(
  67 + UserUtil.getUser()?.name ?? '未登录',
  68 + style: TextStyle(
  69 + color: const Color(0xFF333333), fontSize: 16.sp),
  70 + ),
  71 + ),
  72 + ),
  73 + 20.horizontalSpace,
  74 + const Expanded(
  75 + child: Text(
  76 + "WOW ENGLISH",
  77 + textAlign: TextAlign.left,
  78 + style: TextStyle(color: Colors.white, fontSize: 30.0),
  79 + )),
  80 + Row(children: <Widget>[
  81 + Image(
  82 + width: 20.0.w,
  83 + height: 20.0.h,
  84 + image: AssetImage('ic_countdown'.assetPng)),
  85 + // 替换为你的图片资源路径
  86 + const SizedBox(width: 10.0),
  87 + // 图片和文本之间的间隔
  88 + const Text('还剩29天'),
  89 + ]),
  90 + ScreenUtil().bottomBarHeight.horizontalSpace,
  91 + ],
  92 + ));
  93 + },
  94 + );
  95 + }
  96 +}
  97 +
  98 +void onUserClick() {
  99 + if (UserUtil.token.isEmpty) {
  100 + pushNamed(AppRouteName.login);
  101 + } else {
  102 + pushNamed(AppRouteName.user);
  103 + }
  104 +}
... ...
lib/pages/shop/home/bloc/shop_home_bloc.dart
1 1  
2 2 import 'package:bloc/bloc.dart';
3 3 import 'package:meta/meta.dart';
  4 +import 'package:wow_english/common/request/dao/shop_dao.dart';
  5 +import 'package:wow_english/models/product_entity.dart';
  6 +
  7 +import '../../../../common/request/exception.dart';
  8 +import '../../../../utils/loading.dart';
  9 +import '../../../../utils/toast_util.dart';
4 10  
5 11 part 'shop_home_event.dart';
6 12 part 'shop_home_state.dart';
7 13  
8 14 class ShopHomeBloc extends Bloc<ShopHomeEvent, ShopHomeState> {
  15 +
  16 + List<ProductEntity?> _productDatas = [];
  17 +
  18 + List<ProductEntity?> get productDatas => _productDatas;
  19 +
9 20 ShopHomeBloc() : super(ShopHomeInitial()) {
10 21 on<ShopHomeEvent>((event, emit) {
11 22 // TODO: implement event handler
12 23 });
  24 + on<RequestDataEvent>(_requestData);
  25 + }
  26 +
  27 + void _requestData(RequestDataEvent event, Emitter<ShopHomeState> emitter) async {
  28 + try {
  29 + await loading(() async {
  30 + _productDatas = await ShopDao.productList() ?? [];
  31 + emitter(RequestListenDataState());
  32 + });
  33 + } catch (e) {
  34 + if (e is ApiException) {
  35 + showToast(e.message ?? '请求失败,请检查网络连接');
  36 + }
  37 + }
13 38 }
14 39 }
... ...
lib/pages/shop/home/bloc/shop_home_event.dart
... ... @@ -2,3 +2,5 @@ part of &#39;shop_home_bloc.dart&#39;;
2 2  
3 3 @immutable
4 4 abstract class ShopHomeEvent {}
  5 +
  6 +class RequestDataEvent extends ShopHomeEvent {}
... ...
lib/pages/shop/home/bloc/shop_home_state.dart
... ... @@ -4,3 +4,5 @@ part of &#39;shop_home_bloc.dart&#39;;
4 4 abstract class ShopHomeState {}
5 5  
6 6 class ShopHomeInitial extends ShopHomeState {}
  7 +
  8 +class RequestListenDataState extends ShopHomeState {}
7 9 \ No newline at end of file
... ...
lib/pages/shop/home/shop_home_page.dart
... ... @@ -3,7 +3,7 @@ import &#39;package:flutter_bloc/flutter_bloc.dart&#39;;
3 3 import 'package:flutter_screenutil/flutter_screenutil.dart';
4 4 import 'package:wow_english/common/extension/string_extension.dart';
5 5 import 'package:wow_english/common/widgets/we_app_bar.dart';
6   -import 'package:wow_english/pages/shop/home/widgets/lesson_card_item.dart';
  6 +import 'package:wow_english/pages/shop/home/widgets/product_item.dart';
7 7 import 'package:wow_english/route/route.dart';
8 8 import 'package:wow_english/utils/toast_util.dart';
9 9  
... ... @@ -15,7 +15,7 @@ class ShopHomePage extends StatelessWidget {
15 15 @override
16 16 Widget build(BuildContext context) {
17 17 return BlocProvider(
18   - create: (context) => ShopHomeBloc(),
  18 + create: (context) => ShopHomeBloc()..add(RequestDataEvent()),
19 19 child: _ShopHomeView(),
20 20 );
21 21 }
... ... @@ -30,7 +30,9 @@ class _ShopHomeView extends StatelessWidget {
30 30 );
31 31 }
32 32  
33   - Widget _shopHomeWidget() => BlocBuilder<ShopHomeBloc, ShopHomeState>(builder: (context, state) {
  33 + Widget _shopHomeWidget() =>
  34 + BlocBuilder<ShopHomeBloc, ShopHomeState>(builder: (context, state) {
  35 + final bloc = BlocProvider.of<ShopHomeBloc>(context);
34 36 return Scaffold(
35 37 appBar: WEAppBar(
36 38 actions: [
... ... @@ -62,7 +64,7 @@ class _ShopHomeView extends StatelessWidget {
62 64 child: Padding(
63 65 padding: EdgeInsets.symmetric(vertical: 25.h, horizontal: 25.w),
64 66 child: GridView.builder(
65   - itemCount: 4,
  67 + itemCount: bloc.productDatas.length,
66 68 gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
67 69 crossAxisCount: 2,
68 70 childAspectRatio: 2,
... ... @@ -70,9 +72,10 @@ class _ShopHomeView extends StatelessWidget {
70 72 crossAxisSpacing: 4.5.w,
71 73 ),
72 74 itemBuilder: (BuildContext context, int index) {
73   - return LessonCardItem(onTap: () {
74   - showToast('购买');
75   - });
  75 + final productEntity = bloc.productDatas[index];
  76 + return ProductItem(onTap: () {
  77 + pushNamed(AppRouteName.pay, arguments: productEntity);
  78 + }, entity: productEntity);
76 79 }),
77 80 ),
78 81 ),
... ...
lib/pages/shop/home/widgets/lesson_card_item.dart renamed to lib/pages/shop/home/widgets/product_item.dart
  1 +import 'package:cached_network_image/cached_network_image.dart';
1 2 import 'package:flutter/material.dart';
2 3 import 'package:flutter_screenutil/flutter_screenutil.dart';
  4 +import 'package:wow_english/models/product_entity.dart';
3 5  
4   -class LessonCardItem extends StatelessWidget {
5   - const LessonCardItem({super.key, required this.onTap});
  6 +class ProductItem extends StatelessWidget {
  7 + const ProductItem({super.key,
  8 + required this.onTap, this.entity});
  9 +
  10 + final ProductEntity? entity;
6 11  
7 12 final Function() onTap;
8 13  
... ... @@ -11,7 +16,6 @@ class LessonCardItem extends StatelessWidget {
11 16 return Container(
12 17 decoration: BoxDecoration(
13 18 borderRadius: BorderRadius.circular(10.r),
14   - color: Colors.blue,
15 19 border: Border.all(
16 20 width: 1.0,
17 21 color: Colors.black
... ... @@ -34,12 +38,29 @@ class LessonCardItem extends StatelessWidget {
34 38 width: 1.0,
35 39 color: const Color(0xFF333333),
36 40 ),
37   - image: const DecorationImage(
38   - fit: BoxFit.fill,
39   - image: NetworkImage('https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032'),
  41 + image: DecorationImage(
  42 + image: NetworkImage(entity?.picUrl ?? ''),
40 43 )
41 44 ),
42 45 ),
  46 + // CachedNetworkImage(
  47 + // imageUrl: entity?.picUrl ?? '',
  48 + // fit: BoxFit.fill,
  49 + // imageBuilder: (context, imageProvider) =>
  50 + // Container(
  51 + // decoration: BoxDecoration(
  52 + // border: Border.all(
  53 + // width: 1.0,
  54 + // color: const Color(0xFF333333),
  55 + // ),
  56 + // borderRadius: BorderRadius.circular(5.0),
  57 + // ),
  58 + // ),
  59 + // placeholder: (context, url) => const CircularProgressIndicator(),
  60 + // // errorWidget: (context, url, error) => const Icon(Icons.error),
  61 + // height: 124.h,
  62 + // width: 124.w,
  63 + // ),
43 64 21.5.horizontalSpace,
44 65 Expanded(
45 66 child: Column(
... ... @@ -47,7 +68,7 @@ class LessonCardItem extends StatelessWidget {
47 68 crossAxisAlignment: CrossAxisAlignment.end,
48 69 children: [
49 70 Text(
50   - 'Wow English 课程年卡',
  71 + entity?.name ?? '',
51 72 softWrap: true,
52 73 textAlign: TextAlign.left,
53 74 style: TextStyle(
... ... @@ -66,7 +87,7 @@ class LessonCardItem extends StatelessWidget {
66 87 )
67 88 ),
68 89 TextSpan(
69   - text: '998',
  90 + text: entity?.price?.toString() ?? '',
70 91 style: TextStyle(
71 92 fontSize: 40.sp,
72 93 color: const Color(0xFFF51A1A),
... ...
lib/pages/shopping/bloc.dart 0 → 100644
  1 +import 'package:bloc/bloc.dart';
  2 +import 'package:fluwx/fluwx.dart';
  3 +import 'package:tobias/tobias.dart';
  4 +import 'package:wow_english/generated/json/base/json_convert_content.dart';
  5 +import 'package:wow_english/models/product_entity.dart';
  6 +
  7 +import '../../common/request/dao/shop_dao.dart';
  8 +import '../../common/request/exception.dart';
  9 +import '../../utils/loading.dart';
  10 +import '../../utils/log_util.dart';
  11 +import '../../utils/toast_util.dart';
  12 +import 'event.dart';
  13 +import 'state.dart';
  14 +
  15 +class ShoppingBloc extends Bloc<ShoppingEvent, ShoppingState> {
  16 +
  17 + ProductEntity? _productData;
  18 +
  19 + ProductEntity? get productData => _productData;
  20 +
  21 + PaymentChannel _curPaymentChannel = PaymentChannel.wechatPay;
  22 +
  23 + PaymentChannel get curPaymentChannel => _curPaymentChannel;
  24 +
  25 +
  26 + ShoppingBloc(this._productData) : super(ShoppingState().init()) {
  27 + //页面初始化时刻
  28 + on<InitEvent>(_init);
  29 + on<ChangePaymentChannelEvent>(_changePaymentChannel);
  30 + on<DoPayEvent>(_startPay);
  31 + }
  32 +
  33 + void _init(InitEvent event, Emitter<ShoppingState> emit) async {
  34 + //处理一些初始化操作,然后刷新界面
  35 + emit(state.clone());
  36 + }
  37 +
  38 + /// 更换支付渠道
  39 + void _changePaymentChannel(ChangePaymentChannelEvent event,
  40 + Emitter<ShoppingState> emitter) async {
  41 + Log.d("_curPaymentChannel=$_curPaymentChannel, event.paymentChannel=${event.paymentChannel}");
  42 + if (_curPaymentChannel != event.paymentChannel) {
  43 + _curPaymentChannel = event.paymentChannel;
  44 + emitter(PaymentChannelChangeState());
  45 + }
  46 + }
  47 +
  48 + void _startPay(DoPayEvent event,
  49 + Emitter<ShoppingState> emitter) async {
  50 + Log.d("开始支付 ${event.productEntity} ${event.paymentChannel}");
  51 + //如果event.productEntity为空,中断流程并toast提示
  52 + if (event.productEntity == null) {
  53 + showToast("商品信息为空");
  54 + return;
  55 + }
  56 + final productEntitySafely = event.productEntity!;
  57 + try {
  58 + await loading(() async {
  59 + final Map<String, dynamic> orderInfo = await ShopDao.createOrder(productEntitySafely);
  60 + Log.d("orderInfo $orderInfo");
  61 + final String? orderNo = orderInfo.getOrNull("orderNo");
  62 + if (orderNo == null) {
  63 + showToast("订单创建失败");
  64 + return;
  65 + }
  66 + Log.d("orderNo $orderNo");
  67 +
  68 + if (event.paymentChannel == PaymentChannel.wechatPay) {
  69 + Fluwx fluwx = Fluwx();
  70 + fluwx.registerApi(appId: "wxd930ea5d5a228f5f",
  71 + universalLink: "https://app-api.wowenglish.com.cn/.well-known/apple-app-site-association");
  72 + // fluwx.pay(
  73 + // which: Payment(
  74 + // appId: _orderInfo['appid'].toString(),
  75 + // partnerId: _orderInfo['partnerid'].toString(),
  76 + // prepayId: _orderInfo['prepayid'].toString(),
  77 + // packageValue: _orderInfo['package'].toString(),
  78 + // nonceStr: _orderInfo['noncestr'].toString(),
  79 + // timestamp: _orderInfo['timestamp'],
  80 + // sign: _orderInfo['sign'].toString(),
  81 + // ));
  82 + } else {
  83 + final Map<String, dynamic> aliPayOrderInfo = await ShopDao.getAliPayToken(orderNo);
  84 + Log.d("aliPayOrderInfo=$aliPayOrderInfo type=${aliPayOrderInfo.runtimeType}");
  85 + final String? aliPayInfo = aliPayOrderInfo.getOrNull("token");
  86 + if (aliPayInfo == null) {
  87 + showToast("支付宝订单创建失败");
  88 + return;
  89 + }
  90 + Log.d("aliPayInfo=$aliPayInfo");
  91 + ///打印aliPayOrderInfo的type
  92 + Tobias tobias = Tobias();
  93 + final Map aliPayResult = await tobias.pay(aliPayInfo);
  94 + Log.d("aliPayResult=$aliPayResult");
  95 + // 判断resultStatus 为9000则代表支付成功
  96 + if (aliPayResult.getOrNull("resultStatus") == "9000") {
  97 + showToast("支付成功");
  98 + emit(PaySuccessState());
  99 + } else {
  100 + showToast("支付失败");
  101 + }
  102 + }
  103 + });
  104 + } catch (e) {
  105 + if (e is ApiException) {
  106 + showToast(e.message ?? '请求失败,请检查网络连接');
  107 + }
  108 + }
  109 + }
  110 +}
  111 +
  112 +enum PaymentChannel {
  113 +
  114 + wechatPay(1, "微信支付"),
  115 +
  116 + aliPay(2, "支付宝支付");
  117 +
  118 + const PaymentChannel(this.payChannelType, this.payChannelName);
  119 +
  120 + final int payChannelType;
  121 +
  122 + final String payChannelName;
  123 +}
... ...
lib/pages/shopping/event.dart 0 → 100644
  1 +import 'package:wow_english/models/product_entity.dart';
  2 +
  3 +import 'bloc.dart';
  4 +
  5 +abstract class ShoppingEvent {}
  6 +
  7 +class InitEvent extends ShoppingEvent {}
  8 +
  9 +class ChangePaymentChannelEvent extends ShoppingEvent {
  10 + final PaymentChannel paymentChannel;
  11 +
  12 + ChangePaymentChannelEvent(this.paymentChannel);
  13 +}
  14 +
  15 +class DoPayEvent extends ShoppingEvent {
  16 +
  17 + final ProductEntity? productEntity;
  18 +
  19 + final PaymentChannel paymentChannel;
  20 +
  21 + DoPayEvent(this.productEntity, this.paymentChannel);
  22 +}
0 23 \ No newline at end of file
... ...
lib/pages/shopping/state.dart 0 → 100644
  1 +class ShoppingState {
  2 + ShoppingState init() {
  3 + return ShoppingState();
  4 + }
  5 +
  6 + ShoppingState clone() {
  7 + return ShoppingState();
  8 + }
  9 +}
  10 +
  11 +class PaymentChannelChangeState extends ShoppingState {}
  12 +
  13 +class PaySuccessState extends ShoppingState {}
0 14 \ No newline at end of file
... ...
lib/pages/shopping/view.dart 0 → 100644
  1 +import 'package:cached_network_image/cached_network_image.dart';
  2 +import 'package:flutter/material.dart';
  3 +import 'package:flutter_bloc/flutter_bloc.dart';
  4 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  5 +import 'package:wow_english/common/extension/string_extension.dart';
  6 +import 'package:wow_english/models/product_entity.dart';
  7 +
  8 +import '../../common/core/assets_const.dart';
  9 +import '../../common/widgets/we_app_bar.dart';
  10 +import '../../utils/image_util.dart';
  11 +import '../../utils/log_util.dart';
  12 +import 'bloc.dart';
  13 +import 'event.dart';
  14 +import 'state.dart';
  15 +
  16 +Widget buildRadioOption({
  17 + required int value,
  18 + required ImageProvider icon,
  19 + required String text,
  20 + required int groupValue,
  21 + required ValueChanged onChanged,
  22 +}) {
  23 + return Row(
  24 + children: [
  25 + Image(image: icon,
  26 + width: 20.0.w,
  27 + height: 20.0.h,
  28 + fit: BoxFit.contain),
  29 + const SizedBox(width: 10.0),
  30 + // Expanded(
  31 + // child: Text(
  32 + // text,
  33 + // style: TextStyle(color: Color(0xFF333333), fontSize: 12.5.sp),
  34 + // ),
  35 + // ),
  36 + Text(
  37 + text,
  38 + style: TextStyle(color: Color(0xFF333333), fontSize: 12.5.sp),
  39 + ),
  40 + Radio(
  41 + value: value,
  42 + groupValue: groupValue,
  43 + onChanged: onChanged
  44 + ),
  45 + ],
  46 + );
  47 +}
  48 +
  49 +class ShoppingPage extends StatelessWidget {
  50 + const ShoppingPage({super.key, this.productEntity});
  51 +
  52 + final ProductEntity? productEntity;
  53 +
  54 + @override
  55 + Widget build(BuildContext context) {
  56 + return BlocProvider(
  57 + create: (BuildContext context) =>
  58 + ShoppingBloc(productEntity)
  59 + ..add(InitEvent()),
  60 + child: _ShoppingView(),
  61 + );
  62 + }
  63 +}
  64 +
  65 +class _ShoppingView extends StatelessWidget {
  66 +
  67 + @override
  68 + Widget build(BuildContext context) {
  69 + final bloc = BlocProvider.of<ShoppingBloc>(context);
  70 + // var title1 = bloc.productData?.name ?? '';
  71 + return BlocListener<ShoppingBloc, ShoppingState>(
  72 + listener: (context, state) {
  73 + Log.d("wqf state=$state");
  74 + if (state is PaySuccessState) {
  75 + Navigator.pop(context);
  76 + }
  77 + },
  78 + child: Scaffold(
  79 + appBar: const WEAppBar(
  80 + //标题传进来的
  81 + titleText: "商品详情",
  82 + ),
  83 + body: Container(
  84 + margin: const EdgeInsets.only(left: 80.0, top: 28.0, right: 56.0),
  85 + child: Row(
  86 + crossAxisAlignment: CrossAxisAlignment.start,
  87 + children: [
  88 + CachedNetworkImage(
  89 + imageUrl: bloc.productData?.detailPicUrl ?? '',
  90 + imageBuilder: (context, imageProvider) =>
  91 + Container(
  92 + decoration: BoxDecoration(
  93 + image: DecorationImage(
  94 + image: imageProvider,
  95 + fit: BoxFit.cover,
  96 + ),
  97 + borderRadius: BorderRadius.circular(5.0),
  98 + ),
  99 + ),
  100 + placeholder: (context, url) => const CircularProgressIndicator(),
  101 + // errorWidget: (context, url, error) => const Icon(Icons.error),
  102 + height: 210.0.h,
  103 + width: 210.0.w,
  104 + ),
  105 + const SizedBox(width: 35.5),
  106 + _paymentWidget(),
  107 + ],
  108 + ),
  109 + ),
  110 + ),);
  111 + }
  112 +}
  113 +
  114 +Widget _paymentWidget() =>
  115 + BlocBuilder<ShoppingBloc, ShoppingState>
  116 + (
  117 + builder: (context, state) {
  118 + final bloc = BlocProvider.of<ShoppingBloc>(context);
  119 + return Column(
  120 + crossAxisAlignment: CrossAxisAlignment.start,
  121 + children: [
  122 + Text('套餐价格:${bloc.productData?.price ?? ''}',
  123 + style: TextStyle(
  124 + color: const Color(0xFF333333), fontSize: 16.sp)),
  125 + const SizedBox(height: 15.0),
  126 + Text('套餐名称:${bloc.productData?.name ?? ''}',
  127 + style: TextStyle(
  128 + color: const Color(0xFF333333), fontSize: 16.sp)),
  129 + const SizedBox(height: 15.0),
  130 + Container(
  131 + padding:
  132 + EdgeInsets.symmetric(horizontal: 6.w, vertical: 10.h),
  133 + decoration: BoxDecoration(
  134 + image: DecorationImage(
  135 + image: ImageUtil.getImageProviderOnDefault(
  136 + AssetsConst.bgUserInformationText),
  137 + fit: BoxFit.fill)),
  138 + child: const Text('支付方式选择',
  139 + style: TextStyle(
  140 + color: Color(0xFF333333),
  141 + fontSize: 12,
  142 + fontFamily: 'PingFangSC-Regular')),
  143 + ),
  144 + const SizedBox(height: 15.0),
  145 + buildRadioOption(
  146 + value: PaymentChannel.wechatPay.payChannelType,
  147 + icon: AssetImage('weixin'.assetPng),
  148 + text: PaymentChannel.wechatPay.payChannelName,
  149 + groupValue: bloc.curPaymentChannel.payChannelType,
  150 + onChanged: (newValue) {
  151 + bloc.add(
  152 + ChangePaymentChannelEvent(PaymentChannel.wechatPay));
  153 + },
  154 + ),
  155 + buildRadioOption(
  156 + value: PaymentChannel.aliPay.payChannelType,
  157 + icon: AssetImage('zhifubao'.assetPng),
  158 + text: PaymentChannel.aliPay.payChannelName,
  159 + groupValue: bloc.curPaymentChannel.payChannelType,
  160 + onChanged: (newValue) {
  161 + bloc.add(ChangePaymentChannelEvent(PaymentChannel.aliPay));
  162 + },
  163 + ),
  164 + const SizedBox(height: 15.0),
  165 + // 确认支付按钮
  166 + InkWell(
  167 + onTap: () {
  168 + Log.d('点击支付按钮 ${bloc.productData}');
  169 + bloc.add(DoPayEvent(bloc.productData, bloc.curPaymentChannel));
  170 + },
  171 + child: Image(
  172 + width: 125.w,
  173 + height: 45.h,
  174 + image: AssetImage('btn_pay'.assetPng),
  175 + ),
  176 + ),
  177 + ],
  178 + );
  179 + },
  180 + );
... ...
lib/pages/user/user_page.dart
... ... @@ -142,18 +142,18 @@ class _UserView extends StatelessWidget {
142 142 ],
143 143 ),
144 144 30.verticalSpace,
145   - // todo xiaoyu delete 打开游戏界面
146   - OutlinedButton(
  145 + // 打开游戏界面 供审核用
  146 + ((UserUtil.getUser()?.phoneNum == '17730280759' || UserUtil.getUser()?.phoneNum == '17718485544') ? OutlinedButton(
147 147 onPressed: () {
148   - methodChannel.invokeMethod('openGamePage', {});
  148 + methodChannel.invokeMethod('openGamePage', { "gameId": 1 });
149 149 },
150 150 style: normalButtonStyle,
151 151 child: Text(
152   - "打开游戏界面",
  152 + "进入游戏",
153 153 style: textStyle21sp,
154 154 ),
155   - ),
156   - 12.verticalSpace,
  155 + ) : 1.verticalSpace),
  156 + ((UserUtil.getUser()?.phoneNum == '17730280759' || UserUtil.getUser()?.phoneNum == '17718485544') ? 12.verticalSpace : 1.verticalSpace),
157 157 OutlinedButton(
158 158 onPressed: () => pushNamed(AppRouteName.fogPwd),
159 159 style: normalButtonStyle,
... ...
lib/route/route.dart
... ... @@ -2,12 +2,15 @@ import &#39;package:flutter/cupertino.dart&#39;;
2 2 import 'package:flutter/material.dart';
3 3 import 'package:wow_english/app/splash_page.dart';
4 4 import 'package:wow_english/common/pages/wow_web_page.dart';
  5 +import 'package:wow_english/models/product_entity.dart';
  6 +import 'package:wow_english/pages/games/view.dart';
5 7 import 'package:wow_english/pages/home/home_page.dart';
6 8 import 'package:wow_english/pages/lessons/lesson_page.dart';
7 9 import 'package:wow_english/pages/listen/listen_page.dart';
8 10 import 'package:wow_english/pages/login/forgetpwd/forget_password_home_page.dart';
9 11 import 'package:wow_english/pages/login/loginpage/login_page.dart';
10 12 import 'package:wow_english/pages/login/setpwd/set_pwd_page.dart';
  13 +import 'package:wow_english/pages/moduleSelect/view.dart';
11 14 import 'package:wow_english/pages/practice/topic_picture_page.dart';
12 15 import 'package:wow_english/pages/repeatafter/repeat_after_page.dart';
13 16 import 'package:wow_english/pages/repeataftercontent/repeat_after_content_page.dart';
... ... @@ -23,12 +26,16 @@ import &#39;package:wow_english/pages/user/user_page.dart&#39;;
23 26 import 'package:wow_english/pages/video/lookvideo/look_video_page.dart';
24 27  
25 28 import '../pages/reading/reading_page.dart';
  29 +import '../pages/shopping/view.dart';
26 30 import '../pages/user/setting/delete_account_page.dart';
27 31 import '../pages/user/setting/reback_page.dart';
  32 +import '../utils/log_util.dart';
28 33  
29 34 class AppRouteName {
30 35 static const String splash = 'splash';
31 36 static const String login = 'login';
  37 + static const String moduleSelect = 'moduleSelect';
  38 + static const String games = 'games';
32 39 static const String home = 'home';
33 40 static const String fogPwd = 'fogPwd';
34 41  
... ... @@ -43,6 +50,7 @@ class AppRouteName {
43 50 static const String reAfter = 'reAfter';
44 51 static const String topicPic = 'topicPic';
45 52 static const String user = 'user';
  53 + static const String pay = 'pay';
46 54  
47 55 /// 用户详细信息页
48 56 static const String userInformation = 'userInformation';
... ... @@ -84,6 +92,10 @@ class AppRouter {
84 92 transitionsBuilder: (_, __, ___, child) => child);
85 93 case AppRouteName.login:
86 94 return CupertinoPageRoute(builder: (_) => const LoginPage());
  95 + case AppRouteName.moduleSelect:
  96 + return CupertinoPageRoute(builder: (_) => const ModuleSelectPage());
  97 + case AppRouteName.games:
  98 + return CupertinoPageRoute(builder: (_) => const GamesPage());
87 99 case AppRouteName.home:
88 100 var moduleId = '';
89 101 if (settings.arguments != null) {
... ... @@ -101,6 +113,12 @@ class AppRouter {
101 113 return CupertinoPageRoute(builder: (_) => const ListenPage());
102 114 case AppRouteName.shop:
103 115 return CupertinoPageRoute(builder: (_) => const ShopHomePage());
  116 + case AppRouteName.pay:
  117 + var productEntity = ProductEntity();
  118 + if (settings.arguments != null && settings.arguments is ProductEntity) {
  119 + productEntity = settings.arguments as ProductEntity;
  120 + }
  121 + return CupertinoPageRoute(builder: (_) => ShoppingPage(productEntity: productEntity));
104 122 case AppRouteName.exLesson:
105 123 return CupertinoPageRoute(builder: (_) => const ExchangeLessonPage());
106 124 case AppRouteName.exList:
... ...
pubspec.yaml
... ... @@ -16,7 +16,7 @@ publish_to: &#39;none&#39; # Remove this line if you wish to publish to pub.dev
16 16 # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
17 17 # In Windows, build-name is used as the major, minor, and patch parts
18 18 # of the product and file versions while build-number is used as the build suffix.
19   -version: 1.0.2+1
  19 +version: 1.0.3+2
20 20  
21 21 environment:
22 22 sdk: '>=3.0.0 <4.0.0'
... ... @@ -66,15 +66,17 @@ dependencies:
66 66 # 拍照,从相册中选择 https://pub.flutter-io.cn/packages/image_picker
67 67 image_picker: ^0.8.7+5
68 68 # 支付宝支付SDK https://pub.flutter-io.cn/packages/tobias
69   - # tobias: ^3.1.0
  69 + tobias: ^3.3.2
70 70 # 微信SDK相关 https://pub.flutter-io.cn/packages/fluwx
71   - # fluwx: ^4.2.4+1
  71 + fluwx: ^4.5.5
72 72 # json数据解析 https://pub.flutter-io.cn/packages/json_annotation
73 73 json_annotation: ^4.8.1
74 74 # double丢失精度问题 https://pub.dev/packages/decimal
75 75 decimal: ^2.3.2
76 76 # 网络图片缓存 https://pub.flutter-io.cn/packages/cached_network_image
77   - cached_network_image: ^3.2.3
  77 + cached_network_image: ^3.3.1
  78 +# # 网络图片缓存 https://pub.dev/packages/extended_image
  79 +# extended_image: ^4.0.0
78 80 # 常用工具类(时间轴,倒计时等) https://pub.flutter-io.cn/packages/common_utils
79 81 common_utils: ^2.1.0
80 82 # 获取设备信息 https://pub.flutter-io.cn/packages/device_info_plus
... ... @@ -135,3 +137,8 @@ flutter:
135 137 - family: HannotateSC
136 138 fonts:
137 139 - asset: assets/fonts/HannotateSC-W5.ttf
  140 +
  141 +tobias:
  142 + url_scheme: ishowwoweng
  143 + ios:
  144 + ignore_security: true
... ...